You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by pa...@apache.org on 2022/08/08 18:56:48 UTC

[arrow-nanoarrow] branch main updated: Owning/mutable `struct ArrowArray` (#14)

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 1257834  Owning/mutable `struct ArrowArray` (#14)
1257834 is described below

commit 1257834139216f5d5fc3f9a24526040acbd95b97
Author: Dewey Dunnington <de...@fishandwhistle.net>
AuthorDate: Mon Aug 8 15:56:43 2022 -0300

    Owning/mutable `struct ArrowArray` (#14)
    
    * add array files + init function
    
    * initial array memory implementation
    
    * Add changes from #10
    
    * add a few more methods that need to exist
    
    * test child/dictionary allocation
    
    * add bitmap setter, test setbuffer
    
    * less confusing buffer setting
    
    * clarify lifecycle of child/dictionary members when allocating their memory
    
    * add one more valid storage type
    
    * more test coverage
---
 CMakeLists.txt                  |   5 +-
 src/nanoarrow/array.c           | 230 ++++++++++++++++++++++++++++++++++++++++
 src/nanoarrow/array_test.cc     | 130 +++++++++++++++++++++++
 src/nanoarrow/nanoarrow.c       |   1 +
 src/nanoarrow/nanoarrow.h       |  86 +++++++--------
 src/nanoarrow/typedefs_inline.h |  66 ++++++++++++
 6 files changed, 470 insertions(+), 48 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index b7f7663..a9e4637 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -29,6 +29,7 @@ include_directories(src)
 add_library(
     nanoarrow
     src/nanoarrow/allocator.c
+    src/nanoarrow/array.c
     src/nanoarrow/error.c
     src/nanoarrow/metadata.c
     src/nanoarrow/schema.c
@@ -59,6 +60,7 @@ if (NANOARROW_BUILD_TESTS)
     add_executable(allocator_test src/nanoarrow/allocator_test.cc)
     add_executable(buffer_test src/nanoarrow/buffer_test.cc)
     add_executable(bitmap_test src/nanoarrow/bitmap_test.cc)
+    add_executable(array_test src/nanoarrow/array_test.cc)
     add_executable(error_test src/nanoarrow/error_test.cc)
     add_executable(metadata_test src/nanoarrow/metadata_test.cc)
     add_executable(schema_test src/nanoarrow/schema_test.cc)
@@ -73,6 +75,7 @@ if (NANOARROW_BUILD_TESTS)
     target_link_libraries(allocator_test nanoarrow GTest::gtest_main arrow_shared arrow_testing_shared)
     target_link_libraries(buffer_test nanoarrow GTest::gtest_main)
     target_link_libraries(bitmap_test nanoarrow GTest::gtest_main)
+    target_link_libraries(array_test nanoarrow GTest::gtest_main)
     target_link_libraries(error_test nanoarrow GTest::gtest_main)
     target_link_libraries(metadata_test nanoarrow GTest::gtest_main arrow_shared arrow_testing_shared)
     target_link_libraries(schema_test nanoarrow GTest::gtest_main arrow_shared arrow_testing_shared)
@@ -82,9 +85,9 @@ if (NANOARROW_BUILD_TESTS)
     gtest_discover_tests(allocator_test)
     gtest_discover_tests(buffer_test)
     gtest_discover_tests(bitmap_test)
+    gtest_discover_tests(array_test)
     gtest_discover_tests(error_test)
     gtest_discover_tests(metadata_test)
     gtest_discover_tests(schema_test)
     gtest_discover_tests(schema_view_test)
-
 endif()
diff --git a/src/nanoarrow/array.c b/src/nanoarrow/array.c
new file mode 100644
index 0000000..89e6cac
--- /dev/null
+++ b/src/nanoarrow/array.c
@@ -0,0 +1,230 @@
+// 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 <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "nanoarrow.h"
+
+static void ArrowArrayRelease(struct ArrowArray* array) {
+  // Release buffers held by this array
+  struct ArrowArrayPrivateData* data = (struct ArrowArrayPrivateData*)array->private_data;
+  if (data != NULL) {
+    ArrowBitmapReset(&data->bitmap);
+    ArrowBufferReset(&data->buffers[0]);
+    ArrowBufferReset(&data->buffers[1]);
+    ArrowFree(data);
+  }
+
+  // This object owns the memory for all the children, but those
+  // children may have been generated elsewhere and might have
+  // their own release() callback.
+  if (array->children != NULL) {
+    for (int64_t i = 0; i < array->n_children; i++) {
+      if (array->children[i] != NULL) {
+        if (array->children[i]->release != NULL) {
+          array->children[i]->release(array->children[i]);
+        }
+
+        ArrowFree(array->children[i]);
+      }
+    }
+
+    ArrowFree(array->children);
+  }
+
+  // This object owns the memory for the dictionary but it
+  // may have been generated somewhere else and have its own
+  // release() callback.
+  if (array->dictionary != NULL) {
+    if (array->dictionary->release != NULL) {
+      array->dictionary->release(array->dictionary);
+    }
+
+    ArrowFree(array->dictionary);
+  }
+
+  // Mark released
+  array->release = NULL;
+}
+
+ArrowErrorCode ArrowArraySetStorageType(struct ArrowArray* array,
+                                        enum ArrowType storage_type) {
+  switch (storage_type) {
+    case NANOARROW_TYPE_UNINITIALIZED:
+    case NANOARROW_TYPE_NA:
+      array->n_buffers = 0;
+      break;
+
+    case NANOARROW_TYPE_LIST:
+    case NANOARROW_TYPE_LARGE_LIST:
+    case NANOARROW_TYPE_FIXED_SIZE_LIST:
+    case NANOARROW_TYPE_STRUCT:
+    case NANOARROW_TYPE_MAP:
+    case NANOARROW_TYPE_SPARSE_UNION:
+      array->n_buffers = 1;
+      break;
+
+    case NANOARROW_TYPE_BOOL:
+    case NANOARROW_TYPE_UINT8:
+    case NANOARROW_TYPE_INT8:
+    case NANOARROW_TYPE_UINT16:
+    case NANOARROW_TYPE_INT16:
+    case NANOARROW_TYPE_UINT32:
+    case NANOARROW_TYPE_INT32:
+    case NANOARROW_TYPE_UINT64:
+    case NANOARROW_TYPE_INT64:
+    case NANOARROW_TYPE_HALF_FLOAT:
+    case NANOARROW_TYPE_FLOAT:
+    case NANOARROW_TYPE_DOUBLE:
+    case NANOARROW_TYPE_INTERVAL_MONTHS:
+    case NANOARROW_TYPE_INTERVAL_DAY_TIME:
+    case NANOARROW_TYPE_INTERVAL_MONTH_DAY_NANO:
+    case NANOARROW_TYPE_FIXED_SIZE_BINARY:
+    case NANOARROW_TYPE_DENSE_UNION:
+      array->n_buffers = 2;
+      break;
+
+    case NANOARROW_TYPE_STRING:
+    case NANOARROW_TYPE_LARGE_STRING:
+    case NANOARROW_TYPE_BINARY:
+    case NANOARROW_TYPE_LARGE_BINARY:
+      array->n_buffers = 3;
+      break;
+
+    default:
+      return EINVAL;
+  }
+
+  struct ArrowArrayPrivateData* data = (struct ArrowArrayPrivateData*)array->private_data;
+  data->storage_type = storage_type;
+  return NANOARROW_OK;
+}
+
+ArrowErrorCode ArrowArrayInit(struct ArrowArray* array, enum ArrowType storage_type) {
+  array->length = 0;
+  array->null_count = -1;
+  array->offset = 0;
+  array->n_buffers = 0;
+  array->n_children = 0;
+  array->buffers = NULL;
+  array->children = NULL;
+  array->dictionary = NULL;
+  array->release = &ArrowArrayRelease;
+  array->private_data = NULL;
+
+  struct ArrowArrayPrivateData* data =
+      (struct ArrowArrayPrivateData*)ArrowMalloc(sizeof(struct ArrowArrayPrivateData));
+  if (data == NULL) {
+    array->release = NULL;
+    return ENOMEM;
+  }
+
+  ArrowBitmapInit(&data->bitmap);
+  ArrowBufferInit(&data->buffers[0]);
+  ArrowBufferInit(&data->buffers[1]);
+  data->buffer_data[0] = NULL;
+  data->buffer_data[1] = NULL;
+  data->buffer_data[2] = NULL;
+
+  array->private_data = data;
+  array->buffers = (const void**)(&data->buffer_data);
+
+  int result = ArrowArraySetStorageType(array, storage_type);
+  if (result != NANOARROW_OK) {
+    array->release(array);
+    return result;
+  }
+
+  return NANOARROW_OK;
+}
+
+ArrowErrorCode ArrowArrayAllocateChildren(struct ArrowArray* array, int64_t n_children) {
+  if (array->children != NULL) {
+    return EINVAL;
+  }
+
+  if (n_children == 0) {
+    return NANOARROW_OK;
+  }
+
+  array->children =
+      (struct ArrowArray**)ArrowMalloc(n_children * sizeof(struct ArrowArray*));
+  if (array->children == NULL) {
+    return ENOMEM;
+  }
+
+  for (int64_t i = 0; i < n_children; i++) {
+    array->children[i] = NULL;
+  }
+
+  for (int64_t i = 0; i < n_children; i++) {
+    array->children[i] = (struct ArrowArray*)ArrowMalloc(sizeof(struct ArrowArray));
+    if (array->children[i] == NULL) {
+      return ENOMEM;
+    }
+    array->children[i]->release = NULL;
+  }
+
+  array->n_children = n_children;
+  return NANOARROW_OK;
+}
+
+ArrowErrorCode ArrowArrayAllocateDictionary(struct ArrowArray* array) {
+  if (array->dictionary != NULL) {
+    return EINVAL;
+  }
+
+  array->dictionary = (struct ArrowArray*)ArrowMalloc(sizeof(struct ArrowArray));
+  if (array->dictionary == NULL) {
+    return ENOMEM;
+  }
+
+  array->dictionary->release = NULL;
+  return NANOARROW_OK;
+}
+
+void ArrowArraySetValidityBitmap(struct ArrowArray* array, struct ArrowBitmap* bitmap) {
+  struct ArrowArrayPrivateData* data = (struct ArrowArrayPrivateData*)array->private_data;
+  ArrowBufferMove(&bitmap->buffer, &data->bitmap.buffer);
+  data->bitmap.size_bits = bitmap->size_bits;
+  bitmap->size_bits = 0;
+  data->buffer_data[0] = data->bitmap.buffer.data;
+}
+
+ArrowErrorCode ArrowArraySetBuffer(struct ArrowArray* array, int64_t i,
+                                   struct ArrowBuffer* buffer) {
+  struct ArrowArrayPrivateData* data = (struct ArrowArrayPrivateData*)array->private_data;
+
+  switch (i) {
+    case 0:
+      ArrowBufferMove(buffer, &data->bitmap.buffer);
+      data->buffer_data[i] = data->bitmap.buffer.data;
+      break;
+    case 1:
+    case 2:
+      ArrowBufferMove(buffer, &data->buffers[i - 1]);
+      data->buffer_data[i] = data->buffers[i - 1].data;
+      break;
+    default:
+      return EINVAL;
+  }
+
+  return NANOARROW_OK;
+}
diff --git a/src/nanoarrow/array_test.cc b/src/nanoarrow/array_test.cc
new file mode 100644
index 0000000..d61047c
--- /dev/null
+++ b/src/nanoarrow/array_test.cc
@@ -0,0 +1,130 @@
+// 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.h"
+
+TEST(ArrayTest, ArrayTestBasic) {
+  struct ArrowArray array;
+
+  EXPECT_EQ(ArrowArrayInit(&array, NANOARROW_TYPE_UNINITIALIZED), NANOARROW_OK);
+  EXPECT_EQ(array.n_buffers, 0);
+  array.release(&array);
+
+  EXPECT_EQ(ArrowArrayInit(&array, NANOARROW_TYPE_STRUCT), NANOARROW_OK);
+  EXPECT_EQ(array.n_buffers, 1);
+  array.release(&array);
+
+  EXPECT_EQ(ArrowArrayInit(&array, NANOARROW_TYPE_INT32), NANOARROW_OK);
+  EXPECT_EQ(array.n_buffers, 2);
+  array.release(&array);
+
+  EXPECT_EQ(ArrowArrayInit(&array, NANOARROW_TYPE_STRING), NANOARROW_OK);
+  EXPECT_EQ(array.n_buffers, 3);
+  array.release(&array);
+
+  EXPECT_EQ(ArrowArrayInit(&array, NANOARROW_TYPE_DATE64), EINVAL);
+}
+
+TEST(ArrayTest, ArrayTestAllocateChildren) {
+  struct ArrowArray array;
+
+  ASSERT_EQ(ArrowArrayInit(&array, NANOARROW_TYPE_STRUCT), NANOARROW_OK);
+  EXPECT_EQ(ArrowArrayAllocateChildren(&array, 0), NANOARROW_OK);
+  EXPECT_EQ(array.n_children, 0);
+  array.release(&array);
+
+  ASSERT_EQ(ArrowArrayInit(&array, NANOARROW_TYPE_STRUCT), NANOARROW_OK);
+  EXPECT_EQ(ArrowArrayAllocateChildren(&array, std::numeric_limits<int64_t>::max()),
+            ENOMEM);
+  array.release(&array);
+
+  ASSERT_EQ(ArrowArrayInit(&array, NANOARROW_TYPE_STRUCT), NANOARROW_OK);
+  EXPECT_EQ(ArrowArrayAllocateChildren(&array, 2), NANOARROW_OK);
+  EXPECT_EQ(array.n_children, 2);
+  ASSERT_NE(array.children, nullptr);
+  ASSERT_NE(array.children[0], nullptr);
+  ASSERT_NE(array.children[1], nullptr);
+
+  ASSERT_EQ(ArrowArrayInit(array.children[0], NANOARROW_TYPE_INT32), NANOARROW_OK);
+  ASSERT_EQ(ArrowArrayInit(array.children[1], NANOARROW_TYPE_STRING), NANOARROW_OK);
+
+  EXPECT_EQ(ArrowArrayAllocateChildren(&array, 0), EINVAL);
+
+  array.release(&array);
+}
+
+TEST(ArrayTest, ArrayTestAllocateDictionary) {
+  struct ArrowArray array;
+
+  ASSERT_EQ(ArrowArrayInit(&array, NANOARROW_TYPE_STRUCT), NANOARROW_OK);
+  EXPECT_EQ(ArrowArrayAllocateDictionary(&array), NANOARROW_OK);
+  ASSERT_NE(array.dictionary, nullptr);
+
+  ASSERT_EQ(ArrowArrayInit(array.dictionary, NANOARROW_TYPE_STRING), NANOARROW_OK);
+
+  EXPECT_EQ(ArrowArrayAllocateDictionary(&array), EINVAL);
+
+  array.release(&array);
+}
+
+TEST(ArrayTest, ArrayTestSetBitmap) {
+  struct ArrowBitmap bitmap;
+  ArrowBitmapInit(&bitmap);
+  ArrowBitmapAppend(&bitmap, true, 9);
+
+  struct ArrowArray array;
+  ASSERT_EQ(ArrowArrayInit(&array, NANOARROW_TYPE_INT32), NANOARROW_OK);
+  ArrowArraySetValidityBitmap(&array, &bitmap);
+  EXPECT_EQ(bitmap.buffer.data, nullptr);
+  const uint8_t* bitmap_buffer = reinterpret_cast<const uint8_t*>(array.buffers[0]);
+  EXPECT_EQ(bitmap_buffer[0], 0xff);
+  EXPECT_EQ(bitmap_buffer[1], 0x01);
+
+  array.release(&array);
+}
+
+TEST(ArrayTest, ArrayTestSetBuffer) {
+  // the array ["a", null, "bc", null, "def", null, "ghij"]
+  uint8_t validity_bitmap[] = {0x05};
+  int32_t offsets[] = {0, 1, 1, 3, 3, 6, 6, 10, 10};
+  const char* data = "abcdefghij";
+
+  struct ArrowBuffer buffer0, buffer1, buffer2;
+  ArrowBufferInit(&buffer0);
+  ArrowBufferAppend(&buffer0, validity_bitmap, 1);
+  ArrowBufferInit(&buffer1);
+  ArrowBufferAppend(&buffer1, offsets, 9 * sizeof(int32_t));
+  ArrowBufferInit(&buffer2);
+  ArrowBufferAppend(&buffer2, data, strlen(data));
+
+  struct ArrowArray array;
+  ASSERT_EQ(ArrowArrayInit(&array, NANOARROW_TYPE_STRING), NANOARROW_OK);
+  EXPECT_EQ(ArrowArraySetBuffer(&array, 0, &buffer0), NANOARROW_OK);
+  EXPECT_EQ(ArrowArraySetBuffer(&array, 1, &buffer1), NANOARROW_OK);
+  EXPECT_EQ(ArrowArraySetBuffer(&array, 2, &buffer2), NANOARROW_OK);
+
+  EXPECT_EQ(memcmp(array.buffers[0], validity_bitmap, 1), 0);
+  EXPECT_EQ(memcmp(array.buffers[1], offsets, 8 * sizeof(int32_t)), 0);
+  EXPECT_EQ(memcmp(array.buffers[2], data, 10), 0);
+
+  // try to set a buffer that isn't, 0, 1, or 2
+  EXPECT_EQ(ArrowArraySetBuffer(&array, 3, &buffer0), EINVAL);
+
+  array.release(&array);
+}
diff --git a/src/nanoarrow/nanoarrow.c b/src/nanoarrow/nanoarrow.c
index 55103de..d3e33c9 100644
--- a/src/nanoarrow/nanoarrow.c
+++ b/src/nanoarrow/nanoarrow.c
@@ -16,6 +16,7 @@
 // under the License.
 
 #include "allocator.c"
+#include "array.c"
 #include "error.c"
 #include "metadata.c"
 #include "schema.c"
diff --git a/src/nanoarrow/nanoarrow.h b/src/nanoarrow/nanoarrow.h
index e4da6c5..8958951 100644
--- a/src/nanoarrow/nanoarrow.h
+++ b/src/nanoarrow/nanoarrow.h
@@ -100,53 +100,6 @@ struct ArrowStringView {
   int64_t n_bytes;
 };
 
-/// \brief Arrow type enumerator
-///
-/// These names are intended to map to the corresponding arrow::Type::type
-/// enumerator; however, the numeric values are specifically not equal
-/// (i.e., do not rely on numeric comparison).
-enum ArrowType {
-  NANOARROW_TYPE_UNINITIALIZED = 0,
-  NANOARROW_TYPE_NA = 1,
-  NANOARROW_TYPE_BOOL,
-  NANOARROW_TYPE_UINT8,
-  NANOARROW_TYPE_INT8,
-  NANOARROW_TYPE_UINT16,
-  NANOARROW_TYPE_INT16,
-  NANOARROW_TYPE_UINT32,
-  NANOARROW_TYPE_INT32,
-  NANOARROW_TYPE_UINT64,
-  NANOARROW_TYPE_INT64,
-  NANOARROW_TYPE_HALF_FLOAT,
-  NANOARROW_TYPE_FLOAT,
-  NANOARROW_TYPE_DOUBLE,
-  NANOARROW_TYPE_STRING,
-  NANOARROW_TYPE_BINARY,
-  NANOARROW_TYPE_FIXED_SIZE_BINARY,
-  NANOARROW_TYPE_DATE32,
-  NANOARROW_TYPE_DATE64,
-  NANOARROW_TYPE_TIMESTAMP,
-  NANOARROW_TYPE_TIME32,
-  NANOARROW_TYPE_TIME64,
-  NANOARROW_TYPE_INTERVAL_MONTHS,
-  NANOARROW_TYPE_INTERVAL_DAY_TIME,
-  NANOARROW_TYPE_DECIMAL128,
-  NANOARROW_TYPE_DECIMAL256,
-  NANOARROW_TYPE_LIST,
-  NANOARROW_TYPE_STRUCT,
-  NANOARROW_TYPE_SPARSE_UNION,
-  NANOARROW_TYPE_DENSE_UNION,
-  NANOARROW_TYPE_DICTIONARY,
-  NANOARROW_TYPE_MAP,
-  NANOARROW_TYPE_EXTENSION,
-  NANOARROW_TYPE_FIXED_SIZE_LIST,
-  NANOARROW_TYPE_DURATION,
-  NANOARROW_TYPE_LARGE_STRING,
-  NANOARROW_TYPE_LARGE_BINARY,
-  NANOARROW_TYPE_LARGE_LIST,
-  NANOARROW_TYPE_INTERVAL_MONTH_DAY_NANO
-};
-
 /// \brief Arrow time unit enumerator
 ///
 /// These names and values map to the corresponding arrow::TimeUnit::type
@@ -503,6 +456,45 @@ static inline void ArrowBitmapReset(struct ArrowBitmap* bitmap);
 
 /// }@
 
+/// \defgroup nanoarrow-array Array producer helpers
+/// These functions allocate, copy, and destroy ArrowArray structures
+
+/// \brief Initialize the fields of an array
+///
+/// Initializes the fields and release callback of array. Caller
+/// is responsible for calling the array->release callback if
+/// NANOARROW_OK is returned.
+ArrowErrorCode ArrowArrayInit(struct ArrowArray* array, enum ArrowType storage_type);
+
+/// \brief Allocate the array->children array
+///
+/// Includes the memory for each child struct ArrowArray,
+/// whose members are marked as released and may be subsequently initialized
+/// with ArrowArrayInit or moved from an existing ArrowArray.
+/// schema must have been allocated using ArrowArrayInit.
+ArrowErrorCode ArrowArrayAllocateChildren(struct ArrowArray* array, int64_t n_children);
+
+/// \brief Allocate the array->dictionary member
+///
+/// Includes the memory for the struct ArrowArray, whose contents
+/// is marked as released and may be subsequently initialized
+/// with ArrowArrayInit or moved from an existing ArrowArray.
+/// array must have been allocated using ArrowArrayInit
+ArrowErrorCode ArrowArrayAllocateDictionary(struct ArrowArray* array);
+
+/// \brief Set the validity bitmap of an ArrowArray
+///
+/// array must have been allocated using ArrowArrayInit
+void ArrowArraySetValidityBitmap(struct ArrowArray* array, struct ArrowBitmap* bitmap);
+
+/// \brief Set a buffer of an ArrowArray
+///
+/// array must have been allocated using ArrowArrayInit
+ArrowErrorCode ArrowArraySetBuffer(struct ArrowArray* array, int64_t i,
+                                   struct ArrowBuffer* buffer);
+
+/// }@
+
 // Inline function definitions
 #include "bitmap_inline.h"
 #include "buffer_inline.h"
diff --git a/src/nanoarrow/typedefs_inline.h b/src/nanoarrow/typedefs_inline.h
index 2a30ba1..c04f909 100644
--- a/src/nanoarrow/typedefs_inline.h
+++ b/src/nanoarrow/typedefs_inline.h
@@ -119,6 +119,53 @@ struct ArrowArrayStream {
 /// \brief Represents an errno-compatible error code
 typedef int ArrowErrorCode;
 
+/// \brief Arrow type enumerator
+///
+/// These names are intended to map to the corresponding arrow::Type::type
+/// enumerator; however, the numeric values are specifically not equal
+/// (i.e., do not rely on numeric comparison).
+enum ArrowType {
+  NANOARROW_TYPE_UNINITIALIZED = 0,
+  NANOARROW_TYPE_NA = 1,
+  NANOARROW_TYPE_BOOL,
+  NANOARROW_TYPE_UINT8,
+  NANOARROW_TYPE_INT8,
+  NANOARROW_TYPE_UINT16,
+  NANOARROW_TYPE_INT16,
+  NANOARROW_TYPE_UINT32,
+  NANOARROW_TYPE_INT32,
+  NANOARROW_TYPE_UINT64,
+  NANOARROW_TYPE_INT64,
+  NANOARROW_TYPE_HALF_FLOAT,
+  NANOARROW_TYPE_FLOAT,
+  NANOARROW_TYPE_DOUBLE,
+  NANOARROW_TYPE_STRING,
+  NANOARROW_TYPE_BINARY,
+  NANOARROW_TYPE_FIXED_SIZE_BINARY,
+  NANOARROW_TYPE_DATE32,
+  NANOARROW_TYPE_DATE64,
+  NANOARROW_TYPE_TIMESTAMP,
+  NANOARROW_TYPE_TIME32,
+  NANOARROW_TYPE_TIME64,
+  NANOARROW_TYPE_INTERVAL_MONTHS,
+  NANOARROW_TYPE_INTERVAL_DAY_TIME,
+  NANOARROW_TYPE_DECIMAL128,
+  NANOARROW_TYPE_DECIMAL256,
+  NANOARROW_TYPE_LIST,
+  NANOARROW_TYPE_STRUCT,
+  NANOARROW_TYPE_SPARSE_UNION,
+  NANOARROW_TYPE_DENSE_UNION,
+  NANOARROW_TYPE_DICTIONARY,
+  NANOARROW_TYPE_MAP,
+  NANOARROW_TYPE_EXTENSION,
+  NANOARROW_TYPE_FIXED_SIZE_LIST,
+  NANOARROW_TYPE_DURATION,
+  NANOARROW_TYPE_LARGE_STRING,
+  NANOARROW_TYPE_LARGE_BINARY,
+  NANOARROW_TYPE_LARGE_LIST,
+  NANOARROW_TYPE_INTERVAL_MONTH_DAY_NANO
+};
+
 /// \brief Array buffer allocation and deallocation
 ///
 /// Container for allocate, reallocate, and free methods that can be used
@@ -165,6 +212,25 @@ struct ArrowBitmap {
   int64_t size_bits;
 };
 
+// Used as the private data member for ArrowArrays allocated here and accessed
+// internally within inline ArrowArray* helpers.
+struct ArrowArrayPrivateData {
+  // Holder for the validity buffer (or first buffer for union types, which are
+  // the only type whose first buffer is not a valdiity buffer)
+  struct ArrowBitmap bitmap;
+
+  // Holder for additional buffers as required
+  struct ArrowBuffer buffers[2];
+
+  // The array of pointers to buffers. This must be updated after a sequence
+  // of appends to synchronize its values with the actual buffer addresses
+  // (which may have ben reallocated uring that time)
+  const void* buffer_data[3];
+
+  // The storage data type, or NANOARROW_TYPE_UNINITIALIZED if unknown
+  enum ArrowType storage_type;
+};
+
 /// }@
 
 #ifdef __cplusplus