This is an automated email from the ASF dual-hosted git repository.

kevingurney pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/main by this push:
     new c37059ad7b GH-38015: [MATLAB] Add `arrow.buffer.Buffer` class to the 
MATLAB Interface (#38020)
c37059ad7b is described below

commit c37059ad7b87f0cbb681f6388aca0e3f02860351
Author: sgilmore10 <[email protected]>
AuthorDate: Tue Oct 10 10:29:24 2023 -0400

    GH-38015: [MATLAB] Add `arrow.buffer.Buffer` class to the MATLAB Interface 
(#38020)
    
    
    
    ### Rationale for this change
    
    To unblock use cases that are not satisfied by the default Arrow -> MATLAB 
conversions (i.e. the `toMATLAB()` on `arrow.array.Array`), we would like 
expose the underlying Arrow data representation as a property on 
`arrow.array.Array`. One possible name for this property would be `DataLayout`, 
which would be an `arrow.array.DataLayout` object. Note, this class does not 
yet exist, so we would have to add it.
    
    For example, the `DataLayout` property for temporal array types would 
return an object of the following class type:
    
    ```matlab
    classdef TemporalDataLayout < arrow.array.DataLayout
        properties
           Values % an arrow.array.Int32Array or an arrow.array.Int64Array
           Valid  % an arrow.buffer.Buffer
        end
    end
    ```
    
    However, the `Valid` property on this class would need to be an 
`arrow.buffer.Buffer` object, which does not yet exist in the MATLAB interface. 
 Therefore, it would be helpful to first add the `arrow.buffer.Buffer` class 
before adding the `DataLayout` property/class hierarchy. It's worth mentioning 
that adding `arrow.buffer.Buffer` will open up additional advanced use cases in 
the future.
    
    ### What changes are included in this PR?
    
    Added `arrow.buffer.Buffer` MATLAB class.
    
    *Properties of `arrow.buffer.Buffer`*
     1. `NumBytes` - a  scalar `int64` value representing the size of the 
buffer in bytes.
    
    *Methods of `arrow.buffer.Buffer`*
    1. `toMATLAB` - returns the data in the buffer as `Nx1` `uint8` vector, 
where `N` is the number of bytes.
    2. `fromMATLAB(data)` - Static method that creates an `arrow.buffer.Buffer` 
from a numeric array.
    
    **Example:**
    ```matlab
    >> dataIn = [1 2];
    >> buffer = arrow.buffer.Buffer.fromMATLAB(dataIn)
    
    buffer =
    
      Buffer with properties:
    
        NumBytes: 16
    
    >> dataOut = toMATLAB(buffer)
    
    dataOut =
    
      16×1 uint8 column vector
    
         0
         0
         0
         0
         0
         0
       240
        63
         0
         0
         0
         0
         0
         0
         0
        64
    
    % Reinterpret bit pattern as a double array
    >> toDouble = typecast(dataOut, "double")
    
    toDouble =
    
         1
         2
    ```
    
    ### Are these changes tested?
    
    Yes. Added a new test class called `tBuffer.m`
    
    ### Are there any user-facing changes?
    
    Yes. Users can now create `arrow.buffer.Buffer` objects via the 
`fromMATLAB` static method. However, there's not much users can do with this 
object as of now. We implemented this class to facilitate adding `DataLayout` 
property to `arrow.array.Array`, as described in the **Rational for this 
change** section.
    
    * Closes: #38015
    
    Authored-by: Sarah Gilmore <[email protected]>
    Signed-off-by: Kevin Gurney <[email protected]>
---
 matlab/src/cpp/arrow/matlab/buffer/proxy/buffer.cc |  96 ++++++++++
 matlab/src/cpp/arrow/matlab/buffer/proxy/buffer.h  |  46 +++++
 matlab/src/cpp/arrow/matlab/error/error.h          |   1 +
 matlab/src/cpp/arrow/matlab/proxy/factory.cc       |   2 +
 matlab/src/matlab/+arrow/+buffer/Buffer.m          |  81 ++++++++
 matlab/test/arrow/buffer/tBuffer.m                 | 209 +++++++++++++++++++++
 matlab/tools/cmake/BuildMatlabArrowInterface.cmake |   4 +-
 7 files changed, 438 insertions(+), 1 deletion(-)

diff --git a/matlab/src/cpp/arrow/matlab/buffer/proxy/buffer.cc 
b/matlab/src/cpp/arrow/matlab/buffer/proxy/buffer.cc
new file mode 100644
index 0000000000..633b82d9fa
--- /dev/null
+++ b/matlab/src/cpp/arrow/matlab/buffer/proxy/buffer.cc
@@ -0,0 +1,96 @@
+// 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.
+
+
+#include "arrow/matlab/buffer/proxy/buffer.h"
+#include "arrow/matlab/buffer/matlab_buffer.h"
+#include "arrow/matlab/error/error.h"
+#include "libmexclass/proxy/ProxyManager.h"
+
+namespace arrow::matlab::buffer::proxy {
+
+    Buffer::Buffer(std::shared_ptr<arrow::Buffer> buffer) : 
buffer{std::move(buffer)} {
+        REGISTER_METHOD(Buffer, getNumBytes);
+        REGISTER_METHOD(Buffer, isEqual);
+        REGISTER_METHOD(Buffer, toMATLAB);
+    }
+
+    libmexclass::proxy::MakeResult Buffer::make(const 
libmexclass::proxy::FunctionArguments& constructor_arguments) {
+        namespace mda = ::matlab::data;
+        using BufferProxy = proxy::Buffer;
+        using MatlabBuffer = arrow::matlab::buffer::MatlabBuffer;
+
+        mda::StructArray opts = constructor_arguments[0];
+        const mda::TypedArray<uint8_t> values_mda = opts[0]["Values"];
+        auto buffer = std::make_shared<MatlabBuffer>(values_mda);
+        return std::make_shared<BufferProxy>(std::move(buffer));
+    }
+
+    std::shared_ptr<arrow::Buffer> Buffer::unwrap() {
+        return buffer;
+    }
+
+    void Buffer::getNumBytes(libmexclass::proxy::method::Context& context) {
+        namespace mda = ::matlab::data;
+        mda::ArrayFactory factory;        
+        auto num_bytes_mda = factory.createScalar(buffer->size());
+        context.outputs[0] = num_bytes_mda; 
+    }
+
+    void Buffer::isEqual(libmexclass::proxy::method::Context& context) { 
+        namespace mda = ::matlab::data;
+
+        bool is_equal = true;
+        const mda::TypedArray<uint64_t> buffer_proxy_ids = context.inputs[0];
+        for (const auto& buffer_proxy_id : buffer_proxy_ids) {
+            // Retrieve the Buffer proxy from the ProxyManager
+            auto proxy = 
libmexclass::proxy::ProxyManager::getProxy(buffer_proxy_id);
+            auto buffer_proxy = std::static_pointer_cast<proxy::Buffer>(proxy);
+            auto buffer_to_compare = buffer_proxy->unwrap();
+
+            if (!buffer->Equals(*buffer_to_compare)) {
+                is_equal = false;
+                break;
+            }
+        }
+        mda::ArrayFactory factory;
+        context.outputs[0] = factory.createScalar(is_equal);
+    }
+
+    void Buffer::toMATLAB(libmexclass::proxy::method::Context& context) { 
+        namespace mda = ::matlab::data;
+
+        // If buffer->is_cpu() returns false, invoking buffer->data() may 
cause a crash.
+        // Avoid this potential crash by first invoking ViewOrCopy(buffer, 
memory_manager_device).
+        // This function tries to create a no-copy view of the buffer on the 
given memory
+        // manager device. If not possible, then ViewOrCopy copies the 
buffer's contents.
+        MATLAB_ASSIGN_OR_ERROR_WITH_CONTEXT(
+            auto cpu_buffer, 
+            arrow::Buffer::ViewOrCopy(buffer, 
arrow::default_cpu_memory_manager()),
+            context, error::BUFFER_VIEW_OR_COPY_FAILED
+        );
+
+        const auto* data_begin = cpu_buffer->data();
+        const auto num_bytes = cpu_buffer->size();
+        // data_begin is a uint8_t*, so num_bytes is equal to the number of 
elements
+        const auto* data_end = data_begin + num_bytes;
+
+        mda::ArrayFactory factory;
+        context.outputs[0] = 
factory.createArray<uint8_t>({static_cast<size_t>(num_bytes), 1}, data_begin, 
data_end);
+    }
+
+}
\ No newline at end of file
diff --git a/matlab/src/cpp/arrow/matlab/buffer/proxy/buffer.h 
b/matlab/src/cpp/arrow/matlab/buffer/proxy/buffer.h
new file mode 100644
index 0000000000..bb6dc5e4c5
--- /dev/null
+++ b/matlab/src/cpp/arrow/matlab/buffer/proxy/buffer.h
@@ -0,0 +1,46 @@
+// 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 "arrow/buffer.h"
+
+#include "libmexclass/proxy/Proxy.h"
+
+namespace arrow::matlab::buffer::proxy {
+
+class Buffer : public libmexclass::proxy::Proxy {
+    public:
+        Buffer(std::shared_ptr<arrow::Buffer> buffer);
+    
+        ~Buffer() {}
+
+        std::shared_ptr<arrow::Buffer> unwrap();
+
+        static libmexclass::proxy::MakeResult make(const 
libmexclass::proxy::FunctionArguments& constructor_arguments);
+
+    protected:
+        void getNumBytes(libmexclass::proxy::method::Context& context);
+
+        void toMATLAB(libmexclass::proxy::method::Context& context);
+
+        void isEqual(libmexclass::proxy::method::Context& context);
+
+        std::shared_ptr<arrow::Buffer> buffer;
+};
+
+}
diff --git a/matlab/src/cpp/arrow/matlab/error/error.h 
b/matlab/src/cpp/arrow/matlab/error/error.h
index 347bc25b5f..b8376c0a06 100644
--- a/matlab/src/cpp/arrow/matlab/error/error.h
+++ b/matlab/src/cpp/arrow/matlab/error/error.h
@@ -198,4 +198,5 @@ namespace arrow::matlab::error {
     static const char* STRUCT_ARRAY_MAKE_FAILED = 
"arrow:array:StructArrayMakeFailed";
     static const char* INDEX_EMPTY_CONTAINER = "arrow:index:EmptyContainer";
     static const char* INDEX_OUT_OF_RANGE = "arrow:index:OutOfRange";
+    static const char* BUFFER_VIEW_OR_COPY_FAILED = 
"arrow:buffer:ViewOrCopyFailed";
 }
diff --git a/matlab/src/cpp/arrow/matlab/proxy/factory.cc 
b/matlab/src/cpp/arrow/matlab/proxy/factory.cc
index 62ed84fedc..3091d248f8 100644
--- a/matlab/src/cpp/arrow/matlab/proxy/factory.cc
+++ b/matlab/src/cpp/arrow/matlab/proxy/factory.cc
@@ -40,6 +40,7 @@
 #include "arrow/matlab/io/feather/proxy/reader.h"
 #include "arrow/matlab/io/csv/proxy/table_writer.h"
 #include "arrow/matlab/io/csv/proxy/table_reader.h"
+#include "arrow/matlab/buffer/proxy/buffer.h"
 
 #include "factory.h"
 
@@ -65,6 +66,7 @@ libmexclass::proxy::MakeResult Factory::make_proxy(const 
ClassName& class_name,
     REGISTER_PROXY(arrow.array.proxy.Date32Array   , 
arrow::matlab::array::proxy::NumericArray<arrow::Date32Type>);
     REGISTER_PROXY(arrow.array.proxy.Date64Array   , 
arrow::matlab::array::proxy::NumericArray<arrow::Date64Type>);
     REGISTER_PROXY(arrow.array.proxy.ChunkedArray  , 
arrow::matlab::array::proxy::ChunkedArray);
+    REGISTER_PROXY(arrow.buffer.proxy.Buffer       , 
arrow::matlab::buffer::proxy::Buffer);
     REGISTER_PROXY(arrow.tabular.proxy.RecordBatch , 
arrow::matlab::tabular::proxy::RecordBatch);
     REGISTER_PROXY(arrow.tabular.proxy.Table       , 
arrow::matlab::tabular::proxy::Table);
     REGISTER_PROXY(arrow.tabular.proxy.Schema      , 
arrow::matlab::tabular::proxy::Schema);
diff --git a/matlab/src/matlab/+arrow/+buffer/Buffer.m 
b/matlab/src/matlab/+arrow/+buffer/Buffer.m
new file mode 100644
index 0000000000..6c46276810
--- /dev/null
+++ b/matlab/src/matlab/+arrow/+buffer/Buffer.m
@@ -0,0 +1,81 @@
+%BUFFER Represents a block of contiguous memory with a specified size.
+
+% 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 Buffer < matlab.mixin.Scalar
+
+    properties (Dependent, GetAccess=public, SetAccess=private)
+        NumBytes
+    end
+
+    properties (Hidden, GetAccess=public, SetAccess=private)
+        Proxy
+    end
+
+    methods
+        function obj = Buffer(proxy)
+            arguments
+                proxy(1, 1) libmexclass.proxy.Proxy {validate(proxy, 
"arrow.buffer.proxy.Buffer")}
+            end
+            import arrow.internal.proxy.validate
+            obj.Proxy = proxy;
+        end
+
+        function numBytes = get.NumBytes(obj)
+            numBytes = obj.Proxy.getNumBytes();
+        end
+
+        function data = toMATLAB(obj)
+            data = obj.Proxy.toMATLAB();
+        end
+
+        function tf = isequal(obj, varargin)
+            narginchk(2, inf);
+            tf = false;
+
+            bufferProxyIDs = zeros([1 numel(varargin)], "uint64");
+            for ii = 1:numel(varargin)
+                maybeBuffer = varargin{ii};
+                if ~isa(maybeBuffer, "arrow.buffer.Buffer")
+                    % If maybeBuffer is not an instance of
+                    % arrow.buffer.Buffer, return false early.
+                    return;
+                end
+                % Otherwise, extract the proxy ID associated with
+                % maybeBuffer.
+                bufferProxyIDs(ii) = maybeBuffer.Proxy.ID;
+            end
+
+            % Invoke the isEqual method on the Buffer Proxy class.
+            tf = obj.Proxy.isEqual(bufferProxyIDs);
+        end
+    end
+
+    methods (Static, Hidden)
+        function buffer = fromMATLAB(data)
+            arguments
+                data(:, 1) {mustBeNumeric, mustBeNonsparse, mustBeReal}
+            end
+
+            % Re-interpret bit pattern as uint8s without changing the
+            % underlying data.
+            data = typecast(data, "uint8");
+            args = struct(Values=data);
+            proxy = arrow.internal.proxy.create("arrow.buffer.proxy.Buffer", 
args);
+            buffer = arrow.buffer.Buffer(proxy);
+        end
+    end
+end
\ No newline at end of file
diff --git a/matlab/test/arrow/buffer/tBuffer.m 
b/matlab/test/arrow/buffer/tBuffer.m
new file mode 100644
index 0000000000..d58af2fc9d
--- /dev/null
+++ b/matlab/test/arrow/buffer/tBuffer.m
@@ -0,0 +1,209 @@
+%TBUFFER Unit tests for arrow.buffer.Buffer
+
+% 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 tBuffer < matlab.unittest.TestCase
+
+    methods (Test)
+        function Smoke(testCase)
+            import arrow.buffer.Buffer
+            
+            source = uint8([1 2 3]);
+            buffer = Buffer.fromMATLAB(source);
+            testCase.verifyInstanceOf(buffer, "arrow.buffer.Buffer");
+        end
+
+        function fromMATLABUInt8Scalar(testCase)
+            % Verifies fromMATLAB returns the expected arrow.buffer.Buffer
+            % instance when given a scalar uint8 value.
+
+            import arrow.buffer.Buffer
+            
+            source = uint8(20);
+            buffer = Buffer.fromMATLAB(source);
+            testCase.verifyEqual(buffer.NumBytes, int64(1));
+            values = toMATLAB(buffer);
+            testCase.verifyEqual(values, source);
+        end
+
+        function fromMATLABFromEmptyUInt8(testCase)
+            % Verifies fromMATLAB returns the expected arrow.buffer.Buffer
+            % value when given an empty uint8 array.
+
+            import arrow.buffer.Buffer
+            
+            % Create buffer from 0x0 uint8 array
+            source = uint8.empty(0, 0);
+            buffer = Buffer.fromMATLAB(source);
+            testCase.verifyEqual(buffer.NumBytes, int64(0));
+            values = toMATLAB(buffer);
+            testCase.verifyEqual(values, uint8.empty(0, 1));
+
+            % Create buffer from 0x1 uint8 array
+            source = uint8.empty(0, 1);
+            buffer = Buffer.fromMATLAB(source);
+            testCase.verifyEqual(buffer.NumBytes, int64(0));
+            values = toMATLAB(buffer);
+            testCase.verifyEqual(values, uint8.empty(0, 1));
+
+            % Create buffer from 1x0 uint8 array
+            source = uint8.empty(1, 0);
+            buffer = Buffer.fromMATLAB(source);
+            testCase.verifyEqual(buffer.NumBytes, int64(0));
+            values = toMATLAB(buffer);
+            testCase.verifyEqual(values, uint8.empty(0, 1));
+        end
+
+        function fromMATLABUInt8Vector(testCase)
+            % Verifies fromMATLAB returns the expected arrow.buffer.Buffer
+            % value when given a uint8 vector.
+
+            import arrow.buffer.Buffer
+            
+            % Create buffer from 1x3 uint8 array
+            source = uint8([3 9 27]);
+            buffer = Buffer.fromMATLAB(source);
+            testCase.verifyEqual(buffer.NumBytes, int64(3));
+            values = toMATLAB(buffer);
+            testCase.verifyEqual(values, uint8([3 9 27]'));
+
+            % Create buffer from 3x1 uint8 array
+            source =  uint8([3 9 27]');
+            buffer = Buffer.fromMATLAB(source);
+            testCase.verifyEqual(buffer.NumBytes, int64(3));
+            values = toMATLAB(buffer);
+            testCase.verifyEqual(values, uint8([3 9 27]'));
+        end
+
+        function fromMATLABDoubleVector(testCase)
+            % Verifies fromMATLAB returns the expected arrow.buffer.Buffer
+            % value when given a double vector.
+
+            import arrow.buffer.Buffer
+            
+            % Create buffer from 1x3 double array
+            source = [3 9 27];
+            buffer = Buffer.fromMATLAB(source);
+            % Since the input vector is a 1x3 double (i.e. 64-bit floating 
+            % point value)  array - each of the 3 elements takes up 8 bytes
+            % (3 elements * 8 bytes per element = 24 bytes).
+            testCase.verifyEqual(buffer.NumBytes, int64(24));
+            values = toMATLAB(buffer);
+            expected = typecast(source', "uint8");
+            testCase.verifyEqual(values, expected);
+            testCase.verifyEqual(typecast(values, "double"), source');
+
+            % Create buffer from 3x1 double array
+            source =  [3 9 27]';
+            buffer = Buffer.fromMATLAB(source);
+            testCase.verifyEqual(buffer.NumBytes, int64(24));
+            values = toMATLAB(buffer);
+            expected = typecast(source, "uint8");
+            testCase.verifyEqual(values, expected);
+            testCase.verifyEqual(typecast(values, "double"), source);
+        end
+
+        function fromMATLABNonNumericError(testCase)
+            % Verify fromMATLAB throws an error if given a non-numeric
+            % array as input.
+            import arrow.buffer.Buffer
+
+            fcn = @() Buffer.fromMATLAB(true);
+            testCase.verifyError(fcn, "MATLAB:validators:mustBeNumeric");
+
+            fcn = @() Buffer.fromMATLAB("A");
+            testCase.verifyError(fcn, "MATLAB:validators:mustBeNumeric");
+
+            fcn = @() Buffer.fromMATLAB(datetime(2023, 1, 1));
+            testCase.verifyError(fcn, "MATLAB:validators:mustBeNumeric");
+        end
+
+        function fromMATLABNonRealError(testCase)
+            % Verify fromMATLAB throws an error if given a complex
+            % numeric  array as input.
+            import arrow.buffer.Buffer
+
+            fcn = @() Buffer.fromMATLAB(10 + 3i);
+            testCase.verifyError(fcn, "MATLAB:validators:mustBeReal");
+        end
+
+        function fromMATLABNonSparseError(testCase)
+            % Verify fromMATLAB throws an error if given a sparse
+            % numeric array as input.
+            import arrow.buffer.Buffer
+
+            fcn = @() Buffer.fromMATLAB(sparse(ones([5 1])));
+            testCase.verifyError(fcn, "MATLAB:validators:mustBeNonsparse");
+        end
+
+        function NumBytesNoSetter(testCase)
+            % Verifies the NumBytes property is not settable.
+
+            import arrow.buffer.Buffer
+
+            buffer = Buffer.fromMATLAB([1 2 3]);
+            fcn = @() setfield(buffer, "NumBytes", int64(1));
+            testCase.verifyError(fcn, "MATLAB:class:SetProhibited");
+        end
+
+        function IsEqualTrue(testCase)
+            % Verifies two buffers are considered equal if
+            %   1. They have the same size (NumBytes)
+            %   2. They contain the same bytes
+
+            import arrow.buffer.Buffer
+
+            % Compare two non-empty buffers
+            buffer1 = Buffer.fromMATLAB([1 2 3]);
+            buffer2 = Buffer.fromMATLAB([1 2 3]);
+            testCase.verifyTrue(isequal(buffer1, buffer2));
+
+            % Compare two buffers, one of which was created from a double 
+            % array and the other created from a uint8 array. However, both
+            % arrays have the same bit pattern.
+            data = zeros([1 24], "uint8");
+            data([7 8 16 23 24]) = [240 63 64  8 64];
+            buffer3 = Buffer.fromMATLAB(data);
+            testCase.verifyTrue(isequal(buffer1, buffer3));
+
+            % Compare two empty buffers 
+            buffer4 = Buffer.fromMATLAB([]);
+            buffer5 = Buffer.fromMATLAB([]);
+            testCase.verifyTrue(isequal(buffer4, buffer5));
+
+            % Compare more than two buffers
+            testCase.verifyTrue(isequal(buffer1, buffer2, buffer3));
+        end
+
+        function IsEqualFalse(testCase)
+            % Verifies two buffers are not considered equal if
+            %   1. They do not have the same size (NumBytes) OR
+            %   2. They do not contain the same bytes
+
+            import arrow.buffer.Buffer
+                
+            buffer1 = Buffer.fromMATLAB([1 2 3]);
+            buffer2 = Buffer.fromMATLAB([1 3 2]);
+            buffer3 = Buffer.fromMATLAB([1 2 3 4]);
+            testCase.verifyFalse(isequal(buffer1, buffer2));
+            testCase.verifyFalse(isequal(buffer1, buffer3));
+            testCase.verifyFalse(isequal(buffer1, buffer2, buffer3));
+
+            % Compare a buffer to a string
+            testCase.verifyFalse(isequal(buffer1, "A"));
+        end
+    end
+end
\ No newline at end of file
diff --git a/matlab/tools/cmake/BuildMatlabArrowInterface.cmake 
b/matlab/tools/cmake/BuildMatlabArrowInterface.cmake
index 149a688b27..50daab6532 100644
--- a/matlab/tools/cmake/BuildMatlabArrowInterface.cmake
+++ b/matlab/tools/cmake/BuildMatlabArrowInterface.cmake
@@ -73,7 +73,9 @@ set(MATLAB_ARROW_LIBMEXCLASS_CLIENT_PROXY_SOURCES 
"${CMAKE_SOURCE_DIR}/src/cpp/a
                                                   
"${CMAKE_SOURCE_DIR}/src/cpp/arrow/matlab/io/feather/proxy/reader.cc"
                                                   
"${CMAKE_SOURCE_DIR}/src/cpp/arrow/matlab/io/csv/proxy/table_writer.cc"
                                                   
"${CMAKE_SOURCE_DIR}/src/cpp/arrow/matlab/io/csv/proxy/table_reader.cc"
-                                                  
"${CMAKE_SOURCE_DIR}/src/cpp/arrow/matlab/index/validate.cc")
+                                                  
"${CMAKE_SOURCE_DIR}/src/cpp/arrow/matlab/index/validate.cc"
+                                                  
"${CMAKE_SOURCE_DIR}/src/cpp/arrow/matlab/buffer/proxy/buffer.cc")
+
 
 set(MATLAB_ARROW_LIBMEXCLASS_CLIENT_PROXY_FACTORY_INCLUDE_DIR 
"${CMAKE_SOURCE_DIR}/src/cpp/arrow/matlab/proxy")
 set(MATLAB_ARROW_LIBMEXCLASS_CLIENT_PROXY_FACTORY_SOURCES 
"${CMAKE_SOURCE_DIR}/src/cpp/arrow/matlab/proxy/factory.cc")

Reply via email to