This is an automated email from the ASF dual-hosted git repository.
paleolimbot pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-nanoarrow.git
The following commit(s) were added to refs/heads/main by this push:
new 86c200e C++ helpers (#60)
86c200e is described below
commit 86c200e4d938b85ef65d19c96b242b4daf8df8df
Author: Dewey Dunnington <[email protected]>
AuthorDate: Mon Oct 24 21:05:29 2022 -0300
C++ helpers (#60)
* start hpp version
* add test
* start on unique array and schema
* test unique array stream
* add nanoarrow.hpp to the bundled build
* some doxygen for nanoarrow.hpp
* document stream utils
* test vector array stream
* remember about virtual deleters
* skelton other wrappers
* simplify unique implementations
* remember to make pointer ops inline
* remember to delete the copy constructor
* test unique bitmap
* test array view
* use the uniquearrayview in a test
* add hpp to dist/ bundle
* maybe get coverage for nanoarrow.hpp
* maybe this will get the coverage in
* one more go
* fix typo
* different approach
* change ordering of files
* revert codecov changes for now
---
.github/workflows/build-and-test.yaml | 6 +-
CMakeLists.txt | 9 +
docs/source/c.rst | 2 +
docs/source/{index.rst => cpp.rst} | 23 ++-
docs/source/index.rst | 1 +
src/nanoarrow/nanoarrow.hpp | 308 ++++++++++++++++++++++++++++++++++
src/nanoarrow/nanoarrow_hpp_test.cc | 210 +++++++++++++++++++++++
7 files changed, 550 insertions(+), 9 deletions(-)
diff --git a/.github/workflows/build-and-test.yaml
b/.github/workflows/build-and-test.yaml
index b0ec3a2..0928563 100644
--- a/.github/workflows/build-and-test.yaml
+++ b/.github/workflows/build-and-test.yaml
@@ -68,7 +68,7 @@ jobs:
cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DNANOARROW_CODE_COVERAGE=ON
-DNANOARROW_BUILD_TESTS=ON
cmake --build .
-
+
- name: Build nanoarrow (namespaced)
if: matrix.config.label == 'namespaced-build'
run: |
@@ -88,7 +88,7 @@ jobs:
cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DNANOARROW_CODE_COVERAGE=ON
-DNANOARROW_BUILD_TESTS=ON -DNANOARROW_BUNDLE=ON
cmake --build .
-
+
- name: Check for non-namespaced symbols in namespaced build
if: matrix.config.label == 'namespaced-build'
run: |
@@ -209,7 +209,7 @@ jobs:
with:
name: nanoarrow-latest
path: nanoarrow-latest.zip
-
+
- name: Commit bundle to dist/
if: success() && github.repository == 'apache/arrow-nanoarrow' &&
github.ref == 'refs/heads/main'
run: |
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7c5e1f1..64f14cf 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -61,6 +61,10 @@ if(NANOARROW_BUNDLE)
string(REGEX REPLACE "#include \"[a-z_.]+\"" "" SRC_FILE_CONTENTS
"${SRC_FILE_CONTENTS}")
file(WRITE ${NANOARROW_H_TEMP} "${SRC_FILE_CONTENTS}")
+ # Copy nanoarrow.hpp too
+ file(READ src/nanoarrow/nanoarrow.hpp SRC_FILE_CONTENTS)
+ file(WRITE ${CMAKE_BINARY_DIR}/amalgamation/nanoarrow/nanoarrow.hpp
"${SRC_FILE_CONTENTS}")
+
# Combine all source files into amalgamation/nanoarrow.c in the build
directory
set(NANOARROW_C_TEMP
${CMAKE_BINARY_DIR}/amalgamation/nanoarrow/nanoarrow.c)
file(READ src/nanoarrow/utils.c SRC_FILE_CONTENTS)
@@ -144,21 +148,26 @@ if(NANOARROW_BUILD_TESTS)
add_executable(buffer_test src/nanoarrow/buffer_test.cc)
add_executable(array_test src/nanoarrow/array_test.cc)
add_executable(schema_test src/nanoarrow/schema_test.cc)
+ add_executable(nanoarrow_hpp_test src/nanoarrow/nanoarrow_hpp_test.cc)
if(NANOARROW_CODE_COVERAGE)
target_compile_options(coverage_config INTERFACE -O0 -g --coverage)
target_link_options(coverage_config INTERFACE --coverage)
target_link_libraries(nanoarrow coverage_config)
+ # Because nanoarrow.hpp is header-only we have to link the test here
to get coverage
+ target_link_libraries(nanoarrow_hpp_test coverage_config)
endif()
target_link_libraries(utils_test nanoarrow GTest::gtest_main arrow_shared)
target_link_libraries(buffer_test nanoarrow GTest::gtest_main)
target_link_libraries(array_test nanoarrow GTest::gtest_main arrow_shared)
target_link_libraries(schema_test nanoarrow GTest::gtest_main arrow_shared)
+ target_link_libraries(nanoarrow_hpp_test nanoarrow GTest::gtest_main)
include(GoogleTest)
gtest_discover_tests(utils_test)
gtest_discover_tests(buffer_test)
gtest_discover_tests(array_test)
gtest_discover_tests(schema_test)
+ gtest_discover_tests(nanoarrow_hpp_test)
endif()
diff --git a/docs/source/c.rst b/docs/source/c.rst
index 9bed1c8..352d0e9 100644
--- a/docs/source/c.rst
+++ b/docs/source/c.rst
@@ -18,6 +18,8 @@
C API Reference
==================
+.. doxygengroup:: nanoarrow
+
Creating schemas
------------------
.. doxygengroup:: nanoarrow-schema
diff --git a/docs/source/index.rst b/docs/source/cpp.rst
similarity index 67%
copy from docs/source/index.rst
copy to docs/source/cpp.rst
index 567d0e9..44b7b4e 100644
--- a/docs/source/index.rst
+++ b/docs/source/cpp.rst
@@ -15,12 +15,23 @@
.. specific language governing permissions and limitations
.. under the License.
-.. include:: README_generated.rst
+C++ API Reference
+==================
-Contents
---------
+.. doxygengroup:: nanoarrow_hpp
-.. toctree::
- :maxdepth: 2
+Owning object wrappers
+----------------------
+.. doxygengroup:: nanoarrow_hpp-unique
+ :members:
- C API Reference <c>
+Array Stream utilities
+----------------------
+
+.. doxygengroup:: nanoarrow_hpp-array-stream
+ :members:
+
+Base classes and utilities
+--------------------------
+.. doxygengroup:: nanoarrow_hpp-unique_base
+ :members:
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 567d0e9..747e97a 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -24,3 +24,4 @@ Contents
:maxdepth: 2
C API Reference <c>
+ C++ API Reference <cpp>
diff --git a/src/nanoarrow/nanoarrow.hpp b/src/nanoarrow/nanoarrow.hpp
new file mode 100644
index 0000000..50d427e
--- /dev/null
+++ b/src/nanoarrow/nanoarrow.hpp
@@ -0,0 +1,308 @@
+// 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 <vector>
+
+#include "nanoarrow.h"
+
+#ifndef NANOARROW_HPP_INCLUDED
+#define NANOARROW_HPP_INCLUDED
+
+/// \defgroup nanoarrow_hpp
+///
+/// The utilities provided in this file are intended to support C++ users
+/// of the nanoarrow C library such that C++-style resource allocation
+/// and error handling can be used with nanoarrow data structures.
+/// These utilities are not intended to mirror the nanoarrow C API.
+
+namespace nanoarrow {
+
+namespace internal {
+
+/// \defgroup nanoarrow_hpp-unique_base Base classes for Unique wrappers
+///
+/// @{
+
+static inline void init_pointer(struct ArrowSchema* data) { data->release =
nullptr; }
+
+static inline void move_pointer(struct ArrowSchema* src, struct ArrowSchema*
dst) {
+ memcpy(dst, src, sizeof(struct ArrowSchema));
+ src->release = nullptr;
+}
+
+static inline void release_pointer(struct ArrowSchema* data) {
+ if (data->release != nullptr) {
+ data->release(data);
+ }
+}
+
+static inline void init_pointer(struct ArrowArray* data) { data->release =
nullptr; }
+
+static inline void move_pointer(struct ArrowArray* src, struct ArrowArray*
dst) {
+ memcpy(dst, src, sizeof(struct ArrowArray));
+ src->release = nullptr;
+}
+
+static inline void release_pointer(struct ArrowArray* data) {
+ if (data->release != nullptr) {
+ data->release(data);
+ }
+}
+
+static inline void init_pointer(struct ArrowArrayStream* data) {
+ data->release = nullptr;
+}
+
+static inline void move_pointer(struct ArrowArrayStream* src,
+ struct ArrowArrayStream* dst) {
+ memcpy(dst, src, sizeof(struct ArrowArrayStream));
+ src->release = nullptr;
+}
+
+static inline void release_pointer(ArrowArrayStream* data) {
+ if (data->release != nullptr) {
+ data->release(data);
+ }
+}
+
+static inline void init_pointer(struct ArrowBuffer* data) {
ArrowBufferInit(data); }
+
+static inline void move_pointer(struct ArrowBuffer* src, struct ArrowBuffer*
dst) {
+ ArrowBufferMove(src, dst);
+}
+
+static inline void release_pointer(struct ArrowBuffer* data) {
ArrowBufferReset(data); }
+
+static inline void init_pointer(struct ArrowBitmap* data) {
ArrowBitmapInit(data); }
+
+static inline void move_pointer(struct ArrowBitmap* src, struct ArrowBitmap*
dst) {
+ ArrowBufferMove(&src->buffer, &dst->buffer);
+ dst->size_bits = src->size_bits;
+ src->size_bits = 0;
+}
+
+static inline void release_pointer(struct ArrowBitmap* data) {
ArrowBitmapReset(data); }
+
+static inline void init_pointer(struct ArrowArrayView* data) {
+ ArrowArrayViewInit(data, NANOARROW_TYPE_UNINITIALIZED);
+}
+
+static inline void move_pointer(struct ArrowArrayView* src, struct
ArrowArrayView* dst) {
+ memcpy(dst, src, sizeof(struct ArrowArrayView));
+ init_pointer(src);
+}
+
+static inline void release_pointer(struct ArrowArrayView* data) {
+ ArrowArrayViewReset(data);
+}
+
+/// \brief A unique_ptr-like base class for stack-allocatable objects
+/// \tparam T The object type
+template <typename T>
+class Unique {
+ public:
+ /// \brief Construct an invalid instance of T holding no resources
+ Unique() { init_pointer(&data_); }
+
+ /// \brief Move and take ownership of data
+ Unique(T* data) { move_pointer(data, &data_); }
+
+ /// \brief Move and take ownership of data wrapped by rhs
+ Unique(Unique&& rhs) : Unique(rhs.get()) {}
+
+ // These objects are not copyable
+ Unique(Unique& rhs) = delete;
+
+ /// \brief Get a pointer to the data owned by this object
+ T* get() noexcept { return &data_; }
+
+ /// \brief Use the pointer operator to access fields of this object
+ T* operator->() { return &data_; }
+
+ /// \brief Call data's release callback if valid
+ void reset() { release_pointer(&data_); }
+
+ /// \brief Call data's release callback if valid and move ownership of the
data
+ /// pointed to by data
+ void reset(T* data) {
+ reset();
+ move_pointer(data, &data_);
+ }
+
+ /// \brief Move ownership of this object to the data pointed to by out
+ void move(T* out) { move_pointer(&data_, out); }
+
+ ~Unique() { reset(); }
+
+ protected:
+ T data_;
+};
+
+/// @}
+
+} // namespace internal
+
+/// \defgroup nanoarrow_hpp-unique
+///
+/// The Arrow C Data interface, the Arrow C Stream interface, and the
+/// nanoarrow C library use stack-allocatable objects, some of which
+/// require initialization or cleanup.
+///
+/// @{
+
+/// \brief Class wrapping a unique struct ArrowSchema
+using UniqueSchema = internal::Unique<struct ArrowSchema>;
+
+/// \brief Class wrapping a unique struct ArrowArray
+using UniqueArray = internal::Unique<struct ArrowArray>;
+
+/// \brief Class wrapping a unique struct ArrowArrayStream
+using UniqueArrayStream = internal::Unique<struct ArrowArrayStream>;
+
+/// \brief Class wrapping a unique struct ArrowBuffer
+using UniqueBuffer = internal::Unique<struct ArrowBuffer>;
+
+/// \brief Class wrapping a unique struct ArrowBitmap
+using UniqueBitmap = internal::Unique<struct ArrowBitmap>;
+
+/// \brief Class wrapping a unique struct ArrowArrayView
+using UniqueArrayView = internal::Unique<struct ArrowArrayView>;
+
+/// @}
+
+/// \defgroup nanoarrow_hpp-array-stream ArrayStream helpers
+///
+/// These classes provide simple struct ArrowArrayStream implementations that
+/// can be extended to help simplify the process of creating a valid
+/// ArrowArrayStream implementation or used as-is for testing.
+///
+/// @{
+
+/// \brief An empty array stream
+///
+/// This class can be constructed from an enum ArrowType or
+/// struct ArrowSchema and implements a default get_next() method that
+/// always marks the output ArrowArray as released. This class can
+/// be extended with an implementation of get_next() for a custom
+/// source.
+class EmptyArrayStream {
+ public:
+ /// \brief Create an empty UniqueArrayStream from a struct ArrowSchema
+ ///
+ /// This object takes ownership of the schema and marks the source schema
+ /// as released.
+ static UniqueArrayStream MakeUnique(struct ArrowSchema* schema) {
+ UniqueArrayStream stream;
+ (new EmptyArrayStream(schema))->MakeStream(stream.get());
+ return stream;
+ }
+
+ virtual ~EmptyArrayStream() {}
+
+ protected:
+ UniqueSchema schema_;
+ struct ArrowError error_;
+
+ EmptyArrayStream(struct ArrowSchema* schema) : schema_(schema) {
+ error_.message[0] = '\0';
+ }
+
+ void MakeStream(struct ArrowArrayStream* stream) {
+ stream->get_schema = &get_schema_wrapper;
+ stream->get_next = &get_next_wrapper;
+ stream->get_last_error = &get_last_error_wrapper;
+ stream->release = &release_wrapper;
+ stream->private_data = this;
+ }
+
+ virtual int get_schema(struct ArrowSchema* schema) {
+ return ArrowSchemaDeepCopy(schema_.get(), schema);
+ }
+
+ virtual int get_next(struct ArrowArray* array) {
+ array->release = nullptr;
+ return NANOARROW_OK;
+ }
+
+ virtual const char* get_last_error() { return error_.message; }
+
+ private:
+ static int get_schema_wrapper(struct ArrowArrayStream* stream,
+ struct ArrowSchema* schema) {
+ return
reinterpret_cast<EmptyArrayStream*>(stream->private_data)->get_schema(schema);
+ }
+
+ static int get_next_wrapper(struct ArrowArrayStream* stream, struct
ArrowArray* array) {
+ return
reinterpret_cast<EmptyArrayStream*>(stream->private_data)->get_next(array);
+ }
+
+ static const char* get_last_error_wrapper(struct ArrowArrayStream* stream) {
+ return
reinterpret_cast<EmptyArrayStream*>(stream->private_data)->get_last_error();
+ }
+
+ static void release_wrapper(struct ArrowArrayStream* stream) {
+ delete reinterpret_cast<EmptyArrayStream*>(stream->private_data);
+ }
+};
+
+/// \brief Implementation of an ArrowArrayStream backed by a vector of
ArrowArray objects
+class VectorArrayStream : public EmptyArrayStream {
+ public:
+ /// \brief Create a UniqueArrowArrayStream from an existing array
+ ///
+ /// Takes ownership of the schema and the array.
+ static UniqueArrayStream MakeUnique(struct ArrowSchema* schema,
+ struct ArrowArray* array) {
+ std::vector<UniqueArray> arrays;
+ arrays.emplace_back(array);
+ return MakeUnique(schema, std::move(arrays));
+ }
+
+ /// \brief Create a UniqueArrowArrayStream from existing arrays
+ ///
+ /// This object takes ownership of the schema and arrays.
+ static UniqueArrayStream MakeUnique(struct ArrowSchema* schema,
+ std::vector<UniqueArray> arrays) {
+ UniqueArrayStream stream;
+ (new VectorArrayStream(schema,
std::move(arrays)))->MakeStream(stream.get());
+ return stream;
+ }
+
+ protected:
+ VectorArrayStream(struct ArrowSchema* schema, std::vector<UniqueArray>
arrays)
+ : EmptyArrayStream(schema), offset_(0), arrays_(std::move(arrays)) {}
+
+ int get_next(struct ArrowArray* array) {
+ if (offset_ < arrays_.size()) {
+ arrays_[offset_++].move(array);
+ } else {
+ array->release = nullptr;
+ }
+
+ return NANOARROW_OK;
+ }
+
+ private:
+ std::vector<UniqueArray> arrays_;
+ int64_t offset_;
+};
+
+/// @}
+
+} // namespace nanoarrow
+
+#endif
diff --git a/src/nanoarrow/nanoarrow_hpp_test.cc
b/src/nanoarrow/nanoarrow_hpp_test.cc
new file mode 100644
index 0000000..d8c9033
--- /dev/null
+++ b/src/nanoarrow/nanoarrow_hpp_test.cc
@@ -0,0 +1,210 @@
+// 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 <gtest/gtest.h>
+
+#include "nanoarrow/nanoarrow.hpp"
+
+TEST(NanoarrowHppTest, NanoarrowHppUniqueArrayTest) {
+ nanoarrow::UniqueArray array;
+ EXPECT_EQ(array->release, nullptr);
+
+ ArrowArrayInit(array.get(), NANOARROW_TYPE_INT32);
+ ASSERT_EQ(ArrowArrayStartAppending(array.get()), NANOARROW_OK);
+ ASSERT_EQ(ArrowArrayAppendInt(array.get(), 123), NANOARROW_OK);
+ ASSERT_EQ(ArrowArrayFinishBuilding(array.get(), nullptr), NANOARROW_OK);
+
+ EXPECT_NE(array->release, nullptr);
+ EXPECT_EQ(array->length, 1);
+
+ // move constructor
+ nanoarrow::UniqueArray array2 = std::move(array);
+ EXPECT_EQ(array->release, nullptr);
+ EXPECT_NE(array2->release, nullptr);
+ EXPECT_EQ(array2->length, 1);
+
+ // pointer constructor
+ nanoarrow::UniqueArray array3(array2.get());
+ EXPECT_EQ(array2->release, nullptr);
+ EXPECT_NE(array3->release, nullptr);
+ EXPECT_EQ(array3->length, 1);
+}
+
+TEST(NanoarrowHppTest, NanoarrowHppUniqueSchemaTest) {
+ nanoarrow::UniqueSchema schema;
+ EXPECT_EQ(schema->release, nullptr);
+
+ ArrowSchemaInit(schema.get(), NANOARROW_TYPE_INT32);
+ EXPECT_NE(schema->release, nullptr);
+ EXPECT_STREQ(schema->format, "i");
+
+ // move constructor
+ nanoarrow::UniqueSchema schema2 = std::move(schema);
+ EXPECT_EQ(schema->release, nullptr);
+ EXPECT_NE(schema2->release, nullptr);
+ EXPECT_STREQ(schema2->format, "i");
+
+ // pointer constructor
+ nanoarrow::UniqueSchema schema3(schema2.get());
+ EXPECT_EQ(schema2->release, nullptr);
+ EXPECT_NE(schema3->release, nullptr);
+ EXPECT_STREQ(schema3->format, "i");
+}
+
+TEST(NanoarrowHppTest, NanoarrowHppUniqueArrayStreamTest) {
+ nanoarrow::UniqueSchema schema;
+ schema->format = NULL;
+
+ nanoarrow::UniqueArrayStream array_stream_default;
+ EXPECT_EQ(array_stream_default->release, nullptr);
+
+ nanoarrow::UniqueSchema schema_in;
+ EXPECT_EQ(ArrowSchemaInit(schema_in.get(), NANOARROW_TYPE_INT32),
NANOARROW_OK);
+ auto array_stream = nanoarrow::EmptyArrayStream::MakeUnique(schema_in.get());
+ EXPECT_NE(array_stream->release, nullptr);
+ EXPECT_EQ(array_stream->get_schema(array_stream.get(), schema.get()),
NANOARROW_OK);
+ EXPECT_STREQ(schema->format, "i");
+ schema.reset();
+ schema->format = NULL;
+
+ // move constructor
+ nanoarrow::UniqueArrayStream array_stream2 = std::move(array_stream);
+ EXPECT_EQ(array_stream->release, nullptr);
+ EXPECT_NE(array_stream2->release, nullptr);
+ EXPECT_EQ(array_stream2->get_schema(array_stream2.get(), schema.get()),
NANOARROW_OK);
+ EXPECT_STREQ(schema->format, "i");
+ schema.reset();
+ schema->format = NULL;
+
+ // pointer constructor
+ nanoarrow::UniqueArrayStream array_stream3(array_stream2.get());
+ EXPECT_EQ(array_stream2->release, nullptr);
+ EXPECT_NE(array_stream3->release, nullptr);
+ EXPECT_EQ(array_stream3->get_schema(array_stream2.get(), schema.get()),
NANOARROW_OK);
+ EXPECT_STREQ(schema->format, "i");
+}
+
+TEST(NanoarrowHppTest, NanoarrowHppUniqueBufferTest) {
+ nanoarrow::UniqueBuffer buffer;
+ EXPECT_EQ(buffer->data, nullptr);
+ EXPECT_EQ(buffer->size_bytes, 0);
+
+ ASSERT_EQ(ArrowBufferAppendFill(buffer.get(), 0xff, 123), NANOARROW_OK);
+ EXPECT_NE(buffer->data, nullptr);
+ EXPECT_EQ(buffer->size_bytes, 123);
+
+ // move constructor
+ nanoarrow::UniqueBuffer buffer2 = std::move(buffer);
+ EXPECT_EQ(buffer->data, nullptr);
+ EXPECT_EQ(buffer->size_bytes, 0);
+ EXPECT_NE(buffer2->data, nullptr);
+ EXPECT_EQ(buffer2->size_bytes, 123);
+
+ // pointer constructor
+ nanoarrow::UniqueBuffer buffer3(buffer2.get());
+ EXPECT_EQ(buffer2->data, nullptr);
+ EXPECT_EQ(buffer2->size_bytes, 0);
+ EXPECT_NE(buffer3->data, nullptr);
+ EXPECT_EQ(buffer3->size_bytes, 123);
+}
+
+TEST(NanoarrowHppTest, NanoarrowHppUniqueBitmapTest) {
+ nanoarrow::UniqueBitmap bitmap;
+ EXPECT_EQ(bitmap->buffer.data, nullptr);
+ EXPECT_EQ(bitmap->size_bits, 0);
+
+ ASSERT_EQ(ArrowBitmapAppend(bitmap.get(), true, 123), NANOARROW_OK);
+ EXPECT_NE(bitmap->buffer.data, nullptr);
+ EXPECT_EQ(bitmap->size_bits, 123);
+
+ // move constructor
+ nanoarrow::UniqueBitmap bitmap2 = std::move(bitmap);
+ EXPECT_EQ(bitmap->buffer.data, nullptr);
+ EXPECT_EQ(bitmap->size_bits, 0);
+ EXPECT_NE(bitmap2->buffer.data, nullptr);
+ EXPECT_EQ(bitmap2->size_bits, 123);
+
+ // pointer constructor
+ nanoarrow::UniqueBitmap bitmap3(bitmap2.get());
+ EXPECT_EQ(bitmap2->buffer.data, nullptr);
+ EXPECT_EQ(bitmap2->size_bits, 0);
+ EXPECT_NE(bitmap3->buffer.data, nullptr);
+ EXPECT_EQ(bitmap3->size_bits, 123);
+}
+
+TEST(NanoarrowHppTest, NanoarrowHppUniqueArrayViewTest) {
+ nanoarrow::UniqueArrayView array_view;
+ EXPECT_EQ(array_view->storage_type, NANOARROW_TYPE_UNINITIALIZED);
+
+ // Use an ArrayView with children, since an ArrayView with no children
+ // doesn't hold any resources
+ ArrowArrayViewInit(array_view.get(), NANOARROW_TYPE_STRUCT);
+ ArrowArrayViewAllocateChildren(array_view.get(), 2);
+ EXPECT_EQ(array_view->storage_type, NANOARROW_TYPE_STRUCT);
+
+ // move constructor
+ nanoarrow::UniqueArrayView array_view2 = std::move(array_view);
+ EXPECT_EQ(array_view->storage_type, NANOARROW_TYPE_UNINITIALIZED);
+ EXPECT_EQ(array_view2->storage_type, NANOARROW_TYPE_STRUCT);
+
+ // pointer constructor
+ nanoarrow::UniqueArrayView array_view3(array_view2.get());
+ EXPECT_EQ(array_view2->storage_type, NANOARROW_TYPE_UNINITIALIZED);
+ EXPECT_EQ(array_view3->storage_type, NANOARROW_TYPE_STRUCT);
+}
+
+TEST(NanoarrowHppTest, NanoarrowHppEmptyArrayStreamTest) {
+ nanoarrow::UniqueSchema schema;
+ struct ArrowArray array;
+
+ nanoarrow::UniqueSchema schema_in;
+ EXPECT_EQ(ArrowSchemaInit(schema_in.get(), NANOARROW_TYPE_INT32),
NANOARROW_OK);
+ auto array_stream = nanoarrow::EmptyArrayStream::MakeUnique(schema_in.get());
+
+ EXPECT_EQ(array_stream->get_schema(array_stream.get(), schema.get()),
NANOARROW_OK);
+ EXPECT_STREQ(schema->format, "i");
+ EXPECT_EQ(array_stream->get_next(array_stream.get(), &array), NANOARROW_OK);
+ EXPECT_EQ(array.release, nullptr);
+ EXPECT_STREQ(array_stream->get_last_error(array_stream.get()), "");
+}
+
+TEST(NanoarrowHppTest, NanoarrowHppVectorArrayStreamTest) {
+ nanoarrow::UniqueSchema schema;
+ nanoarrow::UniqueArray array;
+ nanoarrow::UniqueArrayView array_view;
+
+ nanoarrow::UniqueArray array_in;
+ EXPECT_EQ(ArrowArrayInit(array_in.get(), NANOARROW_TYPE_INT32),
NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayStartAppending(array_in.get()), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayAppendInt(array_in.get(), 1234), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuilding(array_in.get(), nullptr), NANOARROW_OK);
+
+ nanoarrow::UniqueSchema schema_in;
+ EXPECT_EQ(ArrowSchemaInit(schema_in.get(), NANOARROW_TYPE_INT32),
NANOARROW_OK);
+
+ auto array_stream =
+ nanoarrow::VectorArrayStream::MakeUnique(schema_in.get(),
array_in.get());
+
+ EXPECT_EQ(array_stream->get_next(array_stream.get(), array.get()),
NANOARROW_OK);
+ ArrowArrayViewInit(array_view.get(), NANOARROW_TYPE_INT32);
+ ASSERT_EQ(ArrowArrayViewSetArray(array_view.get(), array.get(), nullptr),
NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayViewGetIntUnsafe(array_view.get(), 0), 1234);
+ array.reset();
+
+ EXPECT_EQ(array_stream->get_next(array_stream.get(), array.get()),
NANOARROW_OK);
+ EXPECT_EQ(array->release, nullptr);
+}