Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions matlab/src/cpp/arrow/matlab/error/error.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,13 @@ namespace arrow::matlab::error {
static const char* RECORD_BATCH_NUMERIC_INDEX_WITH_EMPTY_RECORD_BATCH = "arrow:tabular:recordbatch:NumericIndexWithEmptyRecordBatch";
static const char* RECORD_BATCH_INVALID_NUMERIC_COLUMN_INDEX = "arrow:tabular:recordbatch:InvalidNumericColumnIndex";
static const char* FAILED_TO_OPEN_FILE_FOR_WRITE = "arrow:io:FailedToOpenFileForWrite";
static const char* FAILED_TO_OPEN_FILE_FOR_READ = "arrow:io:FailedToOpenFileForRead";
static const char* FEATHER_FAILED_TO_WRITE_TABLE = "arrow:io:feather:FailedToWriteTable";
static const char* TABLE_FROM_RECORD_BATCH = "arrow:table:FromRecordBatch";
static const char* FEATHER_FAILED_TO_CREATE_READER = "arrow:io:feather:FailedToCreateReader";
static const char* FEATHER_VERSION_2 = "arrow:io:feather:FeatherVersion2";
static const char* FEATHER_VERSION_UNKNOWN = "arrow:io:feather:FeatherVersionUnknown";
static const char* FEATHER_FAILED_TO_READ_TABLE = "arrow:io:feather:FailedToReadTable";
static const char* FEATHER_FAILED_TO_READ_RECORD_BATCH = "arrow:io:feather:FailedToReadRecordBatch";

}
98 changes: 98 additions & 0 deletions matlab/src/cpp/arrow/matlab/io/feather/proxy/reader.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

#include "libmexclass/proxy/ProxyManager.h"

#include "arrow/matlab/error/error.h"
#include "arrow/matlab/io/feather/proxy/reader.h"
#include "arrow/matlab/tabular/proxy/record_batch.h"

#include "arrow/util/utf8.h"

#include "arrow/result.h"

#include "arrow/io/file.h"
#include "arrow/ipc/feather.h"
#include "arrow/table.h"

namespace arrow::matlab::io::feather::proxy {

Reader::Reader(const std::string& filename) : filename{filename} {
REGISTER_METHOD(Reader, read);
REGISTER_METHOD(Reader, getFilename);
}

libmexclass::proxy::MakeResult Reader::make(const libmexclass::proxy::FunctionArguments& constructor_arguments) {
namespace mda = ::matlab::data;
using ReaderProxy = arrow::matlab::io::feather::proxy::Reader;

mda::StructArray args = constructor_arguments[0];
const mda::StringArray filename_utf16_mda = args[0]["Filename"];
const auto filename_utf16 = std::u16string(filename_utf16_mda[0]);
MATLAB_ASSIGN_OR_ERROR(const auto filename, arrow::util::UTF16StringToUTF8(filename_utf16), error::UNICODE_CONVERSION_ERROR_ID);

return std::make_shared<ReaderProxy>(filename);
}

void Reader::read(libmexclass::proxy::method::Context& context) {
namespace mda = ::matlab::data;
using namespace libmexclass::proxy;
using RecordBatchProxy = arrow::matlab::tabular::proxy::RecordBatch;

mda::ArrayFactory factory;

// Create a file input stream.
MATLAB_ASSIGN_OR_ERROR_WITH_CONTEXT(auto source, arrow::io::ReadableFile::Open(filename, arrow::default_memory_pool()), context, error::FAILED_TO_OPEN_FILE_FOR_READ);

// Create a Reader from the file input stream.
MATLAB_ASSIGN_OR_ERROR_WITH_CONTEXT(auto reader, arrow::ipc::feather::Reader::Open(source), context, error::FEATHER_FAILED_TO_CREATE_READER);

// Error if not Feather V1.
const auto version = reader->version();
if (version == ipc::feather::kFeatherV2Version) {
MATLAB_ERROR_IF_NOT_OK_WITH_CONTEXT(Status::NotImplemented("Support for Feather V2 has not been implemented."), context, error::FEATHER_VERSION_2);
} else if (version != ipc::feather::kFeatherV1Version) {
MATLAB_ERROR_IF_NOT_OK_WITH_CONTEXT(Status::Invalid("Unknown Feather format version."), context, error::FEATHER_VERSION_UNKNOWN);
}

// Read a Table from the file.
std::shared_ptr<arrow::Table> table = nullptr;
MATLAB_ERROR_IF_NOT_OK_WITH_CONTEXT(reader->Read(&table), context, error::FEATHER_FAILED_TO_READ_TABLE);

// Get the first RecordBatch from the Table.
arrow::TableBatchReader table_batch_reader{table};
std::shared_ptr<arrow::RecordBatch> record_batch = nullptr;
MATLAB_ERROR_IF_NOT_OK_WITH_CONTEXT(table_batch_reader.ReadNext(&record_batch), context, error::FEATHER_FAILED_TO_READ_RECORD_BATCH);

// Create a Proxy from the first RecordBatch.
auto record_batch_proxy = std::make_shared<RecordBatchProxy>(record_batch);
const auto record_batch_proxy_id = ProxyManager::manageProxy(record_batch_proxy);

const auto record_batch_proxy_id_mda = factory.createScalar(record_batch_proxy_id);

context.outputs[0] = record_batch_proxy_id_mda;
}

void Reader::getFilename(libmexclass::proxy::method::Context& context) {
namespace mda = ::matlab::data;
mda::ArrayFactory factory;

MATLAB_ASSIGN_OR_ERROR_WITH_CONTEXT(const auto filename_utf16, arrow::util::UTF8StringToUTF16(filename), context, error::UNICODE_CONVERSION_ERROR_ID);
auto filename_utf16_mda = factory.createScalar(filename_utf16);
context.outputs[0] = filename_utf16_mda;
}

}
39 changes: 39 additions & 0 deletions matlab/src/cpp/arrow/matlab/io/feather/proxy/reader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

#pragma once

#include "libmexclass/proxy/Proxy.h"

namespace arrow::matlab::io::feather::proxy {

class Reader : public libmexclass::proxy::Proxy {
public:
Reader(const std::string& filename);

virtual ~Reader() {}

static libmexclass::proxy::MakeResult make(const libmexclass::proxy::FunctionArguments& constructor_arguments);

protected:
void read(libmexclass::proxy::method::Context& context);
void getFilename(libmexclass::proxy::method::Context& context);

const std::string filename;
};

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// specific language governing permissions and limitations
// under the License.

#include "arrow/matlab/io/feather/proxy/feather_writer.h"
#include "arrow/matlab/io/feather/proxy/writer.h"
#include "arrow/matlab/tabular/proxy/record_batch.h"
#include "arrow/matlab/error/error.h"

Expand All @@ -30,12 +30,12 @@

namespace arrow::matlab::io::feather::proxy {

FeatherWriter::FeatherWriter(const std::string& filename) : filename{filename} {
REGISTER_METHOD(FeatherWriter, getFilename);
REGISTER_METHOD(FeatherWriter, write);
Writer::Writer(const std::string& filename) : filename{filename} {
REGISTER_METHOD(Writer, getFilename);
REGISTER_METHOD(Writer, write);
}

libmexclass::proxy::MakeResult FeatherWriter::make(const libmexclass::proxy::FunctionArguments& constructor_arguments) {
libmexclass::proxy::MakeResult Writer::make(const libmexclass::proxy::FunctionArguments& constructor_arguments) {
namespace mda = ::matlab::data;
mda::StructArray opts = constructor_arguments[0];
const mda::StringArray filename_mda = opts[0]["Filename"];
Expand All @@ -45,10 +45,10 @@ namespace arrow::matlab::io::feather::proxy {
arrow::util::UTF16StringToUTF8(filename_utf16),
error::UNICODE_CONVERSION_ERROR_ID);

return std::make_shared<FeatherWriter>(filename_utf8);
return std::make_shared<Writer>(filename_utf8);
}

void FeatherWriter::getFilename(libmexclass::proxy::method::Context& context) {
void Writer::getFilename(libmexclass::proxy::method::Context& context) {
namespace mda = ::matlab::data;
MATLAB_ASSIGN_OR_ERROR_WITH_CONTEXT(const auto utf16_filename,
arrow::util::UTF8StringToUTF16(filename),
Expand All @@ -59,7 +59,7 @@ namespace arrow::matlab::io::feather::proxy {
context.outputs[0] = str_mda;
}

void FeatherWriter::write(libmexclass::proxy::method::Context& context) {
void Writer::write(libmexclass::proxy::method::Context& context) {
namespace mda = ::matlab::data;
mda::StructArray opts = context.inputs[0];
const mda::TypedArray<uint64_t> record_batch_proxy_id_mda = opts[0]["RecordBatchProxyID"];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@

namespace arrow::matlab::io::feather::proxy {

class FeatherWriter : public libmexclass::proxy::Proxy {
class Writer : public libmexclass::proxy::Proxy {
public:
FeatherWriter(const std::string& filename);
Writer(const std::string& filename);

~FeatherWriter() {}
~Writer() {}

static libmexclass::proxy::MakeResult make(const libmexclass::proxy::FunctionArguments& constructor_arguments);

Expand Down
6 changes: 4 additions & 2 deletions matlab/src/cpp/arrow/matlab/proxy/factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
#include "arrow/matlab/type/proxy/string_type.h"
#include "arrow/matlab/type/proxy/timestamp_type.h"
#include "arrow/matlab/type/proxy/field.h"
#include "arrow/matlab/io/feather/proxy/feather_writer.h"
#include "arrow/matlab/io/feather/proxy/writer.h"
#include "arrow/matlab/io/feather/proxy/reader.h"

#include "factory.h"

Expand Down Expand Up @@ -61,7 +62,8 @@ libmexclass::proxy::MakeResult Factory::make_proxy(const ClassName& class_name,
REGISTER_PROXY(arrow.type.proxy.BooleanType , arrow::matlab::type::proxy::PrimitiveCType<bool>);
REGISTER_PROXY(arrow.type.proxy.StringType , arrow::matlab::type::proxy::StringType);
REGISTER_PROXY(arrow.type.proxy.TimestampType , arrow::matlab::type::proxy::TimestampType);
REGISTER_PROXY(arrow.io.feather.proxy.FeatherWriter , arrow::matlab::io::feather::proxy::FeatherWriter);
REGISTER_PROXY(arrow.io.feather.proxy.Writer , arrow::matlab::io::feather::proxy::Writer);
REGISTER_PROXY(arrow.io.feather.proxy.Reader , arrow::matlab::io::feather::proxy::Reader);

return libmexclass::error::Error{error::UNKNOWN_PROXY_ERROR_ID, "Did not find matching C++ proxy for " + class_name};
};
Expand Down
52 changes: 52 additions & 0 deletions matlab/src/matlab/+arrow/+internal/+io/+feather/Reader.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
% Licensed to the Apache Software Foundation (ASF) under one or more
% contributor license agreements. See the NOTICE file distributed with
% this work for additional information regarding copyright ownership.
% The ASF licenses this file to you under the Apache License, Version
% 2.0 (the "License"); you may not use this file except in compliance
% with the License. You may obtain a copy of the License at
%
% http://www.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS,
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
% implied. See the License for the specific language governing
% permissions and limitations under the License.

classdef Reader
%READER An internal Reader object for reading Feather files.

properties (GetAccess=public, SetAccess=private, Hidden)
Proxy
end

properties (Dependent, SetAccess=private, GetAccess=public)
% Name of the file to read.
Filename
end

methods

function obj = Reader(filename)
arguments
filename(1, 1) {mustBeNonmissing, mustBeNonzeroLengthText}
end

args = struct(Filename=filename);
obj.Proxy = arrow.internal.proxy.create("arrow.io.feather.proxy.Reader", args);
end

function T = read(obj)
recordBatchProxyID = obj.Proxy.read();
proxy = libmexclass.proxy.Proxy(Name="arrow.tabular.proxy.RecordBatch", ID=recordBatchProxyID);
recordBatch = arrow.tabular.RecordBatch(proxy);
T = recordBatch.toMATLAB();
end

function filename = get.Filename(obj)
filename = obj.Proxy.getFilename();
end

end

end
4 changes: 2 additions & 2 deletions matlab/src/matlab/+arrow/+internal/+io/+feather/Writer.m
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
end

args = struct(Filename=filename);
proxyName = "arrow.io.feather.proxy.FeatherWriter";
proxyName = "arrow.io.feather.proxy.Writer";
obj.Proxy = arrow.internal.proxy.create(proxyName, args);
end

Expand All @@ -45,4 +45,4 @@ function write(obj, T)
filename = obj.Proxy.getFilename();
end
end
end
end
5 changes: 5 additions & 0 deletions matlab/test/arrow/io/feather/tRoundTrip.m
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,9 @@ function Basic(testCase)
function featherwrite(T, filename)
writer = arrow.internal.io.feather.Writer(filename);
writer.write(T);
end

function T = featherread(filename)
reader = arrow.internal.io.feather.Reader(filename);
T = reader.read();
end
4 changes: 2 additions & 2 deletions matlab/tools/cmake/BuildMatlabArrowInterface.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ set(MATLAB_ARROW_LIBMEXCLASS_CLIENT_PROXY_SOURCES "${CMAKE_SOURCE_DIR}/src/cpp/a
"${CMAKE_SOURCE_DIR}/src/cpp/arrow/matlab/type/proxy/timestamp_type.cc"
"${CMAKE_SOURCE_DIR}/src/cpp/arrow/matlab/type/proxy/field.cc"
"${CMAKE_SOURCE_DIR}/src/cpp/arrow/matlab/type/proxy/wrap.cc"
"${CMAKE_SOURCE_DIR}/src/cpp/arrow/matlab/io/feather/proxy/feather_writer.cc")

"${CMAKE_SOURCE_DIR}/src/cpp/arrow/matlab/io/feather/proxy/writer.cc"
"${CMAKE_SOURCE_DIR}/src/cpp/arrow/matlab/io/feather/proxy/reader.cc")


set(MATLAB_ARROW_LIBMEXCLASS_CLIENT_PROXY_FACTORY_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/src/cpp/arrow/matlab/proxy")
Expand Down