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 230cfd4 feat!: Allow explicit validation level in
`ArrowArrayFinishBuilding()` (#175)
230cfd4 is described below
commit 230cfd497bc351c667523aaa288546e03b7d621f
Author: Dewey Dunnington <[email protected]>
AuthorDate: Wed Mar 29 12:12:39 2023 -0400
feat!: Allow explicit validation level in `ArrowArrayFinishBuilding()`
(#175)
This is a breaking change! The signature of `ArrowArrayFinishBuilding()`
gains a `validation_level` argument, and the original function was
renamed to `ArrowArrayFinishBuildingDefault()`. I could do this in a
non-breaking way but there are no non-awkward names for
`ArrowArrayFinishBuildingWithExplicitValidationLevel()` and it seems
more important to cultivate a quality API at this point rather than
maintain full backward compatibility (plus it's a relatively easy rename
fix).
This adds two important features. First, it lets you preform more
validation if you want to (via `NANOARROW_VALIDATION_LEVEL_FULL`,
implemented with the just-added `ArrowArrayViewValidateFull()`). Second,
it lets you perform less validation if you want to (e.g., if your
buffers are sitting on a GPU and dereferencing a buffer value will
crash).
---
README.md | 6 +-
examples/cmake-minimal/src/library.c | 4 +-
examples/vendored-minimal/src/library.c | 2 +-
.../src/nanoarrow/nanoarrow_ipc_decoder.c | 2 +-
r/src/array.c | 4 +-
r/src/as_array.c | 20 +--
src/nanoarrow/array.c | 34 +++-
src/nanoarrow/array_stream_test.cc | 6 +-
src/nanoarrow/array_test.cc | 172 +++++++++++++++------
src/nanoarrow/nanoarrow.h | 20 ++-
src/nanoarrow/nanoarrow_hpp_test.cc | 4 +-
src/nanoarrow/nanoarrow_types.h | 19 +++
12 files changed, 220 insertions(+), 73 deletions(-)
diff --git a/README.md b/README.md
index b411cd0..0c1c2bd 100644
--- a/README.md
+++ b/README.md
@@ -51,14 +51,14 @@ int make_simple_array(struct ArrowArray* array_out, struct
ArrowSchema* schema_o
array_out->release = NULL;
schema_out->release = NULL;
- NANOARROW_RETURN_NOT_OK(ArrowArrayInit(array_out, NANOARROW_TYPE_INT32));
+ NANOARROW_RETURN_NOT_OK(ArrowArrayInitFromType(array_out,
NANOARROW_TYPE_INT32));
NANOARROW_RETURN_NOT_OK(ArrowArrayStartAppending(array_out));
NANOARROW_RETURN_NOT_OK(ArrowArrayAppendInt(array_out, 1));
NANOARROW_RETURN_NOT_OK(ArrowArrayAppendInt(array_out, 2));
NANOARROW_RETURN_NOT_OK(ArrowArrayAppendInt(array_out, 3));
- NANOARROW_RETURN_NOT_OK(ArrowArrayFinishBuilding(array_out, &error));
-
+ NANOARROW_RETURN_NOT_OK(ArrowArrayFinishBuildingDefault(array_out, &error));
+
NANOARROW_RETURN_NOT_OK(ArrowSchemaInit(schema_out, NANOARROW_TYPE_INT32));
return NANOARROW_OK;
diff --git a/examples/cmake-minimal/src/library.c
b/examples/cmake-minimal/src/library.c
index b44f9ec..ac16184 100644
--- a/examples/cmake-minimal/src/library.c
+++ b/examples/cmake-minimal/src/library.c
@@ -39,8 +39,8 @@ int make_simple_array(struct ArrowArray* array_out, struct
ArrowSchema* schema_o
NANOARROW_RETURN_NOT_OK(ArrowArrayAppendInt(array_out, 1));
NANOARROW_RETURN_NOT_OK(ArrowArrayAppendInt(array_out, 2));
NANOARROW_RETURN_NOT_OK(ArrowArrayAppendInt(array_out, 3));
- NANOARROW_RETURN_NOT_OK(ArrowArrayFinishBuilding(array_out, &global_error));
-
+ NANOARROW_RETURN_NOT_OK(ArrowArrayFinishBuildingDefault(array_out,
&global_error));
+
NANOARROW_RETURN_NOT_OK(ArrowSchemaInitFromType(schema_out,
NANOARROW_TYPE_INT32));
return NANOARROW_OK;
diff --git a/examples/vendored-minimal/src/library.c
b/examples/vendored-minimal/src/library.c
index c1e634f..fe6f396 100644
--- a/examples/vendored-minimal/src/library.c
+++ b/examples/vendored-minimal/src/library.c
@@ -39,7 +39,7 @@ int make_simple_array(struct ArrowArray* array_out, struct
ArrowSchema* schema_o
NANOARROW_RETURN_NOT_OK(ArrowArrayAppendInt(array_out, 1));
NANOARROW_RETURN_NOT_OK(ArrowArrayAppendInt(array_out, 2));
NANOARROW_RETURN_NOT_OK(ArrowArrayAppendInt(array_out, 3));
- NANOARROW_RETURN_NOT_OK(ArrowArrayFinishBuilding(array_out, &global_error));
+ NANOARROW_RETURN_NOT_OK(ArrowArrayFinishBuildingDefault(array_out,
&global_error));
NANOARROW_RETURN_NOT_OK(ArrowSchemaInitFromType(schema_out,
NANOARROW_TYPE_INT32));
diff --git a/extensions/nanoarrow_ipc/src/nanoarrow/nanoarrow_ipc_decoder.c
b/extensions/nanoarrow_ipc/src/nanoarrow/nanoarrow_ipc_decoder.c
index 2f9f845..db4169c 100644
--- a/extensions/nanoarrow_ipc/src/nanoarrow/nanoarrow_ipc_decoder.c
+++ b/extensions/nanoarrow_ipc/src/nanoarrow/nanoarrow_ipc_decoder.c
@@ -1381,7 +1381,7 @@ static ArrowErrorCode ArrowIpcDecoderDecodeArrayInternal(
// TODO: this performs some validation but doesn't do everything we need it
to do
// notably it doesn't loop over offset buffers to look for values that will
cause
// out-of-bounds buffer access on the data buffer or child arrays.
- result = ArrowArrayFinishBuilding(&temp, error);
+ result = ArrowArrayFinishBuildingDefault(&temp, error);
if (result != NANOARROW_OK) {
temp.release(&temp);
return result;
diff --git a/r/src/array.c b/r/src/array.c
index 4e38c14..dce4a33 100644
--- a/r/src/array.c
+++ b/r/src/array.c
@@ -288,9 +288,9 @@ SEXP nanoarrow_c_array_validate_after_modify(SEXP
array_xptr, SEXP schema_xptr)
Rf_error("move_array_buffers: %s", error.message);
}
- result = ArrowArrayFinishBuilding(array_dst, &error);
+ result = ArrowArrayFinishBuildingDefault(array_dst, &error);
if (result != NANOARROW_OK) {
- Rf_error("ArrowArrayFinishBuilding(): %s", error.message);
+ Rf_error("ArrowArrayFinishBuildingDefault(): %s", error.message);
}
UNPROTECT(1);
diff --git a/r/src/as_array.c b/r/src/as_array.c
index 592e83b..6221d8e 100644
--- a/r/src/as_array.c
+++ b/r/src/as_array.c
@@ -109,9 +109,9 @@ static void as_array_int(SEXP x_sexp, struct ArrowArray*
array, SEXP schema_xptr
}
array->null_count = null_count;
- result = ArrowArrayFinishBuilding(array, error);
+ result = ArrowArrayFinishBuildingDefault(array, error);
if (result != NANOARROW_OK) {
- Rf_error("ArrowArrayFinishBuilding(): %s", error->message);
+ Rf_error("ArrowArrayFinishBuildingDefault(): %s", error->message);
}
}
@@ -187,9 +187,9 @@ static void as_array_lgl(SEXP x_sexp, struct ArrowArray*
array, SEXP schema_xptr
}
array->null_count = null_count;
- result = ArrowArrayFinishBuilding(array, error);
+ result = ArrowArrayFinishBuildingDefault(array, error);
if (result != NANOARROW_OK) {
- Rf_error("ArrowArrayFinishBuilding(): %s", error->message);
+ Rf_error("ArrowArrayFinishBuildingDefault(): %s", error->message);
}
}
@@ -312,9 +312,9 @@ static void as_array_dbl(SEXP x_sexp, struct ArrowArray*
array, SEXP schema_xptr
}
array->null_count = null_count;
- result = ArrowArrayFinishBuilding(array, error);
+ result = ArrowArrayFinishBuildingDefault(array, error);
if (result != NANOARROW_OK) {
- Rf_error("ArrowArrayFinishBuilding(): %s", error->message);
+ Rf_error("ArrowArrayFinishBuildingDefault(): %s", error->message);
}
}
@@ -397,9 +397,9 @@ static void as_array_chr(SEXP x_sexp, struct ArrowArray*
array, SEXP schema_xptr
}
array->null_count = null_count;
- result = ArrowArrayFinishBuilding(array, error);
+ result = ArrowArrayFinishBuildingDefault(array, error);
if (result != NANOARROW_OK) {
- Rf_error("ArrowArrayFinishBuilding(): %s", error->message);
+ Rf_error("ArrowArrayFinishBuildingDefault(): %s", error->message);
}
}
@@ -529,9 +529,9 @@ static void as_array_list(SEXP x_sexp, struct ArrowArray*
array, SEXP schema_xpt
}
array->null_count = null_count;
- result = ArrowArrayFinishBuilding(array, error);
+ result = ArrowArrayFinishBuildingDefault(array, error);
if (result != NANOARROW_OK) {
- Rf_error("ArrowArrayFinishBuilding(): %s", error->message);
+ Rf_error("ArrowArrayFinishBuildingDefault(): %s", error->message);
}
}
diff --git a/src/nanoarrow/array.c b/src/nanoarrow/array.c
index 81675bb..fc88fd6 100644
--- a/src/nanoarrow/array.c
+++ b/src/nanoarrow/array.c
@@ -435,14 +435,23 @@ static ArrowErrorCode ArrowArrayCheckInternalBufferSizes(
}
ArrowErrorCode ArrowArrayFinishBuilding(struct ArrowArray* array,
+ enum ArrowValidationLevel
validation_level,
struct ArrowError* error) {
- // Even if the data buffer is size zero, the value needs to be non-null
- NANOARROW_RETURN_NOT_OK(ArrowArrayFinalizeBuffers(array));
+ // Even if the data buffer is size zero, the pointer value needed to be
non-null
+ // in some implementations (at least one version of Arrow C++ at the time
this
+ // was added). Only do this fix if we can assume CPU data access.
+ if (validation_level >= NANOARROW_VALIDATION_LEVEL_DEFAULT) {
+ NANOARROW_RETURN_NOT_OK(ArrowArrayFinalizeBuffers(array));
+ }
// Make sure the value we get with array->buffers[i] is set to the actual
// pointer (which may have changed from the original due to reallocation)
ArrowArrayFlushInternalPointers(array);
+ if (validation_level == NANOARROW_VALIDATION_LEVEL_NONE) {
+ return NANOARROW_OK;
+ }
+
// Check buffer sizes to make sure we are not sending an ArrowArray
// into the wild that is going to segfault
struct ArrowArrayView array_view;
@@ -458,6 +467,11 @@ ArrowErrorCode ArrowArrayFinishBuilding(struct ArrowArray*
array,
return result;
}
+ if (validation_level == NANOARROW_VALIDATION_LEVEL_MINIMAL) {
+ ArrowArrayViewReset(&array_view);
+ return NANOARROW_OK;
+ }
+
result = ArrowArrayViewSetArray(&array_view, array, error);
if (result != NANOARROW_OK) {
ArrowArrayViewReset(&array_view);
@@ -465,10 +479,26 @@ ArrowErrorCode ArrowArrayFinishBuilding(struct
ArrowArray* array,
}
result = ArrowArrayCheckInternalBufferSizes(array, &array_view, 0, error);
+ if (result != NANOARROW_OK) {
+ ArrowArrayViewReset(&array_view);
+ return result;
+ }
+
+ if (validation_level == NANOARROW_VALIDATION_LEVEL_DEFAULT) {
+ ArrowArrayViewReset(&array_view);
+ return NANOARROW_OK;
+ }
+
+ result = ArrowArrayViewValidateFull(&array_view, error);
ArrowArrayViewReset(&array_view);
return result;
}
+ArrowErrorCode ArrowArrayFinishBuildingDefault(struct ArrowArray* array,
+ struct ArrowError* error) {
+ return ArrowArrayFinishBuilding(array, NANOARROW_VALIDATION_LEVEL_DEFAULT,
error);
+}
+
void ArrowArrayViewInitFromType(struct ArrowArrayView* array_view,
enum ArrowType storage_type) {
memset(array_view, 0, sizeof(struct ArrowArrayView));
diff --git a/src/nanoarrow/array_stream_test.cc
b/src/nanoarrow/array_stream_test.cc
index efb39dc..aa2c10d 100644
--- a/src/nanoarrow/array_stream_test.cc
+++ b/src/nanoarrow/array_stream_test.cc
@@ -31,7 +31,7 @@ TEST(ArrayStreamTest, ArrayStreamTestBasic) {
ASSERT_EQ(ArrowArrayInitFromType(&array, NANOARROW_TYPE_INT32),
NANOARROW_OK);
ASSERT_EQ(ArrowArrayStartAppending(&array), NANOARROW_OK);
ASSERT_EQ(ArrowArrayAppendInt(&array, 123), NANOARROW_OK);
- ASSERT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ ASSERT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
ArrowBasicArrayStreamSetArray(&array_stream, 0, &array);
EXPECT_EQ(array.release, nullptr);
@@ -90,7 +90,7 @@ TEST(ArrayStreamTest, ArrayStreamTestIncomplete) {
for (int j = 0; j < i; j++) {
ASSERT_EQ(ArrowArrayAppendInt(&array, 123), NANOARROW_OK);
}
- ASSERT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ ASSERT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
ArrowBasicArrayStreamSetArray(&array_stream, i, &array);
}
@@ -114,7 +114,7 @@ TEST(ArrayStreamTest, ArrayStreamTestInvalid) {
ASSERT_EQ(ArrowArrayInitFromType(&array, NANOARROW_TYPE_STRING),
NANOARROW_OK);
ASSERT_EQ(ArrowArrayStartAppending(&array), NANOARROW_OK);
- ASSERT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ ASSERT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
ArrowBasicArrayStreamSetArray(&array_stream, 0, &array);
EXPECT_EQ(ArrowBasicArrayStreamValidate(&array_stream, &error), EINVAL);
diff --git a/src/nanoarrow/array_test.cc b/src/nanoarrow/array_test.cc
index ce07da2..493541f 100644
--- a/src/nanoarrow/array_test.cc
+++ b/src/nanoarrow/array_test.cc
@@ -207,7 +207,7 @@ TEST(ArrayTest, ArrayTestBuildByBuffer) {
array.length = 7;
EXPECT_EQ(ArrowArrayShrinkToFit(&array), NANOARROW_OK);
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, &error), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, &error), NANOARROW_OK);
EXPECT_EQ(memcmp(array.buffers[0], validity_bitmap, 1), 0);
EXPECT_EQ(memcmp(array.buffers[1], offsets, 8 * sizeof(int32_t)), 0);
@@ -222,20 +222,102 @@ TEST(ArrayTest, ArrayTestBuildByBuffer) {
EXPECT_EQ(ArrowArrayBuffer(&array, 2)->size_bytes, 10);
array.length = 8;
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, &error), EINVAL);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, &error), EINVAL);
EXPECT_STREQ(ArrowErrorMessage(&error),
"Expected buffer 1 to size >= 36 bytes but found buffer with 32
bytes");
array.length = 7;
int32_t* offsets_buffer =
reinterpret_cast<int32_t*>(ArrowArrayBuffer(&array, 1)->data);
offsets_buffer[7] = offsets_buffer[7] + 1;
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, &error), EINVAL);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, &error), EINVAL);
EXPECT_STREQ(ArrowErrorMessage(&error),
"Expected buffer 2 to size >= 11 bytes but found buffer with 10
bytes");
array.release(&array);
}
+TEST(ArrayTest, ArrayTestExplicitValidationLevel) {
+ struct ArrowArray array;
+ struct ArrowError error;
+
+ ASSERT_EQ(ArrowArrayInitFromType(&array, NANOARROW_TYPE_STRING),
NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayStartAppending(&array), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayAppendString(&array, ArrowCharView("1234")),
NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayAppendString(&array, ArrowCharView("5678")),
NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuilding(&array, NANOARROW_VALIDATION_LEVEL_NONE,
&error),
+ NANOARROW_OK);
+
+ int32_t* offsets =
+ const_cast<int32_t*>(reinterpret_cast<const int32_t*>(array.buffers[1]));
+
+ // Valid at validation_level < NANOARROW_VALIDATION_LEVEL_FULL
+ offsets[1] = -1;
+ EXPECT_EQ(ArrowArrayFinishBuilding(&array, NANOARROW_VALIDATION_LEVEL_NONE,
&error),
+ NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuilding(&array,
NANOARROW_VALIDATION_LEVEL_MINIMAL, &error),
+ NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuilding(&array,
NANOARROW_VALIDATION_LEVEL_DEFAULT, &error),
+ NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuilding(&array, NANOARROW_VALIDATION_LEVEL_FULL,
&error),
+ EINVAL);
+ EXPECT_STREQ(error.message, "[1] Expected element size >= 0 but found
element size -1");
+ offsets[1] = 4;
+
+ // Valid at validation_level < NANOARROW_VALIDATION_LEVEL_DEFAULT
+ offsets[0] = -1;
+ EXPECT_EQ(ArrowArrayFinishBuilding(&array, NANOARROW_VALIDATION_LEVEL_NONE,
&error),
+ NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuilding(&array,
NANOARROW_VALIDATION_LEVEL_MINIMAL, &error),
+ NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuilding(&array,
NANOARROW_VALIDATION_LEVEL_DEFAULT, &error),
+ EINVAL);
+ EXPECT_EQ(ArrowArrayFinishBuilding(&array, NANOARROW_VALIDATION_LEVEL_FULL,
&error),
+ EINVAL);
+ EXPECT_STREQ(error.message, "Expected first offset >= 0 but found -1");
+ offsets[0] = 0;
+
+ // Valid at validation_level < NANOARROW_VALIDATION_LEVEL_MINIMAL
+ ArrowBufferReset(ArrowArrayBuffer(&array, 1));
+ EXPECT_EQ(ArrowArrayFinishBuilding(&array, NANOARROW_VALIDATION_LEVEL_NONE,
&error),
+ NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuilding(&array,
NANOARROW_VALIDATION_LEVEL_MINIMAL, &error),
+ EINVAL);
+ EXPECT_EQ(ArrowArrayFinishBuilding(&array,
NANOARROW_VALIDATION_LEVEL_DEFAULT, &error),
+ EINVAL);
+ EXPECT_EQ(ArrowArrayFinishBuilding(&array, NANOARROW_VALIDATION_LEVEL_FULL,
&error),
+ EINVAL);
+ EXPECT_STREQ(error.message,
+ "Expected buffer 1 to size >= 12 bytes but found buffer with 0
bytes");
+
+ array.release(&array);
+}
+
+TEST(ArrayTest, ArrayTestValidateMinimalBufferAccess) {
+ struct ArrowArray array;
+
+ ASSERT_EQ(ArrowArrayInitFromType(&array, NANOARROW_TYPE_STRING),
NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayStartAppending(&array), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayAppendString(&array, ArrowCharView("1234")),
NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayAppendString(&array, ArrowCharView("5678")),
NANOARROW_OK);
+
+ // Temporarily make it so that referencing the offsets buffer will crash
+ // but make sure it has the correct size_bytes and passes minimal validation
+ uint8_t* tmp = ArrowArrayBuffer(&array, 1)->data;
+ ArrowArrayBuffer(&array, 1)->data = nullptr;
+ EXPECT_EQ(ArrowArrayFinishBuilding(&array,
NANOARROW_VALIDATION_LEVEL_MINIMAL, nullptr),
+ NANOARROW_OK);
+
+ // ...and fails without crashing with the incorrect size_bytes
+ ArrowArrayBuffer(&array, 1)->size_bytes = 0;
+ EXPECT_EQ(ArrowArrayFinishBuilding(&array,
NANOARROW_VALIDATION_LEVEL_MINIMAL, nullptr),
+ EINVAL);
+
+ // ...restore the pointer so we don't leak memory
+ ArrowArrayBuffer(&array, 1)->data = tmp;
+
+ array.release(&array);
+}
+
TEST(ArrayTest, ArrayTestAppendToNullArray) {
struct ArrowArray array;
ASSERT_EQ(ArrowArrayInitFromType(&array, NANOARROW_TYPE_NA), NANOARROW_OK);
@@ -244,7 +326,7 @@ TEST(ArrayTest, ArrayTestAppendToNullArray) {
EXPECT_EQ(ArrowArrayAppendNull(&array, 0), NANOARROW_OK);
EXPECT_EQ(ArrowArrayAppendNull(&array, 2), NANOARROW_OK);
EXPECT_EQ(ArrowArrayAppendEmpty(&array, 1), NANOARROW_OK);
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
EXPECT_EQ(array.length, 3);
EXPECT_EQ(array.null_count, 3);
@@ -277,7 +359,7 @@ TEST(ArrayTest, ArrayTestAppendToInt64Array) {
EXPECT_EQ(ArrowArrayAppendUInt(&array, 3), NANOARROW_OK);
EXPECT_EQ(ArrowArrayAppendEmpty(&array, 1), NANOARROW_OK);
EXPECT_EQ(ArrowArrayAppendUInt(&array,
std::numeric_limits<uint64_t>::max()), EINVAL);
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
EXPECT_EQ(array.length, 5);
EXPECT_EQ(array.null_count, 2);
@@ -311,7 +393,7 @@ TEST(ArrayTest, ArrayTestAppendToInt32Array) {
EXPECT_EQ(ArrowArrayAppendInt(&array, 123), NANOARROW_OK);
EXPECT_EQ(ArrowArrayAppendInt(&array, std::numeric_limits<int64_t>::max()),
EINVAL);
EXPECT_EQ(ArrowArrayAppendUInt(&array,
std::numeric_limits<uint64_t>::max()), EINVAL);
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
EXPECT_EQ(array.length, 1);
EXPECT_EQ(array.null_count, 0);
@@ -337,7 +419,7 @@ TEST(ArrayTest, ArrayTestAppendToInt16Array) {
EXPECT_EQ(ArrowArrayAppendInt(&array, 123), NANOARROW_OK);
EXPECT_EQ(ArrowArrayAppendInt(&array, std::numeric_limits<int64_t>::max()),
EINVAL);
EXPECT_EQ(ArrowArrayAppendUInt(&array,
std::numeric_limits<uint64_t>::max()), EINVAL);
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
EXPECT_EQ(array.length, 1);
EXPECT_EQ(array.null_count, 0);
@@ -363,7 +445,7 @@ TEST(ArrayTest, ArrayTestAppendToInt8Array) {
EXPECT_EQ(ArrowArrayAppendInt(&array, 123), NANOARROW_OK);
EXPECT_EQ(ArrowArrayAppendInt(&array, std::numeric_limits<int64_t>::max()),
EINVAL);
EXPECT_EQ(ArrowArrayAppendUInt(&array,
std::numeric_limits<uint64_t>::max()), EINVAL);
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
EXPECT_EQ(array.length, 1);
EXPECT_EQ(array.null_count, 0);
@@ -395,7 +477,7 @@ TEST(ArrayTest, ArrayTestAppendToStringArray) {
EXPECT_EQ(ArrowArrayAppendNull(&array, 2), NANOARROW_OK);
EXPECT_EQ(ArrowArrayAppendString(&array, ArrowCharView("56789")),
NANOARROW_OK);
EXPECT_EQ(ArrowArrayAppendEmpty(&array, 1), NANOARROW_OK);
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
EXPECT_EQ(array.length, 5);
EXPECT_EQ(array.null_count, 2);
@@ -428,7 +510,7 @@ TEST(ArrayTest, ArrayTestAppendEmptyToString) {
ASSERT_EQ(ArrowArrayInitFromType(&array, NANOARROW_TYPE_STRING),
NANOARROW_OK);
ASSERT_EQ(ArrowArrayStartAppending(&array), NANOARROW_OK);
ASSERT_EQ(ArrowArrayAppendString(&array, ArrowCharView("")), NANOARROW_OK);
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
EXPECT_NE(array.buffers[2], nullptr);
array.release(&array);
}
@@ -441,7 +523,7 @@ TEST(ArrayTest, ArrayTestAppendToUInt64Array) {
EXPECT_EQ(ArrowArrayAppendUInt(&array, 1), NANOARROW_OK);
EXPECT_EQ(ArrowArrayAppendNull(&array, 2), NANOARROW_OK);
EXPECT_EQ(ArrowArrayAppendInt(&array, 3), NANOARROW_OK);
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
EXPECT_EQ(array.length, 4);
EXPECT_EQ(array.null_count, 2);
@@ -476,7 +558,7 @@ TEST(ArrayTest, ArrayTestAppendToUInt32Array) {
EXPECT_EQ(ArrowArrayAppendUInt(&array,
std::numeric_limits<uint64_t>::max()), EINVAL);
EXPECT_EQ(ArrowArrayAppendInt(&array, -1), EINVAL);
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
EXPECT_EQ(array.length, 2);
EXPECT_EQ(array.null_count, 0);
@@ -507,7 +589,7 @@ TEST(ArrayTest, ArrayTestAppendToUInt16Array) {
EXPECT_EQ(ArrowArrayAppendUInt(&array,
std::numeric_limits<uint64_t>::max()), EINVAL);
EXPECT_EQ(ArrowArrayAppendInt(&array, -1), EINVAL);
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
EXPECT_EQ(array.length, 2);
EXPECT_EQ(array.null_count, 0);
@@ -538,7 +620,7 @@ TEST(ArrayTest, ArrayTestAppendToUInt8Array) {
EXPECT_EQ(ArrowArrayAppendUInt(&array,
std::numeric_limits<uint64_t>::max()), EINVAL);
EXPECT_EQ(ArrowArrayAppendInt(&array, -1), EINVAL);
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
EXPECT_EQ(array.length, 2);
EXPECT_EQ(array.null_count, 0);
@@ -574,7 +656,7 @@ TEST(ArrayTest, ArrayTestAppendToDoubleArray) {
EXPECT_EQ(ArrowArrayAppendDouble(&array, -INFINITY), NANOARROW_OK);
EXPECT_EQ(ArrowArrayAppendDouble(&array, -1), NANOARROW_OK);
EXPECT_EQ(ArrowArrayAppendDouble(&array, 0), NANOARROW_OK);
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
EXPECT_EQ(array.length, 11);
EXPECT_EQ(array.null_count, 2);
@@ -631,7 +713,7 @@ TEST(ArrayTest, ArrayTestAppendToFloatArray) {
EXPECT_EQ(ArrowArrayAppendDouble(&array, -INFINITY), NANOARROW_OK);
EXPECT_EQ(ArrowArrayAppendDouble(&array, -1), NANOARROW_OK);
EXPECT_EQ(ArrowArrayAppendDouble(&array, 0), NANOARROW_OK);
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
EXPECT_EQ(array.length, 11);
EXPECT_EQ(array.null_count, 2);
@@ -679,7 +761,7 @@ TEST(ArrayTest, ArrayTestAppendToBoolArray) {
EXPECT_EQ(ArrowArrayAppendInt(&array, 1), NANOARROW_OK);
EXPECT_EQ(ArrowArrayAppendNull(&array, 2), NANOARROW_OK);
EXPECT_EQ(ArrowArrayAppendUInt(&array, 0), NANOARROW_OK);
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
EXPECT_EQ(array.length, 4);
EXPECT_EQ(array.null_count, 2);
@@ -717,7 +799,7 @@ TEST(ArrayTest, ArrayTestAppendToLargeStringArray) {
EXPECT_EQ(ArrowArrayAppendNull(&array, 2), NANOARROW_OK);
EXPECT_EQ(ArrowArrayAppendString(&array, ArrowCharView("56789")),
NANOARROW_OK);
EXPECT_EQ(ArrowArrayAppendEmpty(&array, 1), NANOARROW_OK);
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
EXPECT_EQ(array.length, 5);
EXPECT_EQ(array.null_count, 2);
@@ -764,7 +846,7 @@ TEST(ArrayTest, ArrayTestAppendToFixedSizeBinaryArray) {
EXPECT_EQ(ArrowArrayAppendNull(&array, 2), NANOARROW_OK);
EXPECT_EQ(ArrowArrayAppendBytes(&array, {"67890", 5}), NANOARROW_OK);
EXPECT_EQ(ArrowArrayAppendEmpty(&array, 1), NANOARROW_OK);
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
EXPECT_EQ(array.length, 5);
EXPECT_EQ(array.null_count, 2);
@@ -818,20 +900,20 @@ TEST(ArrayTest, ArrayTestAppendToListArray) {
// Make sure number of children is checked at finish
array.n_children = 0;
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, &error), EINVAL);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, &error), EINVAL);
EXPECT_STREQ(ArrowErrorMessage(&error),
"Expected 1 child of list array but found 0 child arrays");
array.n_children = 1;
// Make sure final child size is checked at finish
array.children[0]->length = array.children[0]->length - 1;
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, &error), EINVAL);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, &error), EINVAL);
EXPECT_STREQ(
ArrowErrorMessage(&error),
"Expected child of list array with length >= 3 but found array with
length 2");
array.children[0]->length = array.children[0]->length + 1;
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, &error), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, &error), NANOARROW_OK);
auto arrow_array = ImportArray(&array, &schema);
ARROW_EXPECT_OK(arrow_array);
@@ -879,20 +961,20 @@ TEST(ArrayTest, ArrayTestAppendToLargeListArray) {
// Make sure number of children is checked at finish
array.n_children = 0;
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, &error), EINVAL);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, &error), EINVAL);
EXPECT_STREQ(ArrowErrorMessage(&error),
"Expected 1 child of large list array but found 0 child
arrays");
array.n_children = 1;
// Make sure final child size is checked at finish
array.children[0]->length = array.children[0]->length - 1;
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, &error), EINVAL);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, &error), EINVAL);
EXPECT_STREQ(ArrowErrorMessage(&error),
"Expected child of large list array with length >= 3 but found
array with "
"length 2");
array.children[0]->length = array.children[0]->length + 1;
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, &error), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, &error), NANOARROW_OK);
auto arrow_array = ImportArray(&array, &schema);
ARROW_EXPECT_OK(arrow_array);
@@ -944,20 +1026,20 @@ TEST(ArrayTest, ArrayTestAppendToMapArray) {
// Make sure number of children is checked at finish
array.n_children = 0;
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, &error), EINVAL);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, &error), EINVAL);
EXPECT_STREQ(ArrowErrorMessage(&error),
"Expected 1 child of map array but found 0 child arrays");
array.n_children = 1;
// Make sure final child size is checked at finish
array.children[0]->length = array.children[0]->length - 1;
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, &error), EINVAL);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, &error), EINVAL);
EXPECT_STREQ(
ArrowErrorMessage(&error),
"Expected child of map array with length >= 1 but found array with
length 0");
array.children[0]->length = array.children[0]->length + 1;
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, &error), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, &error), NANOARROW_OK);
auto maybe_arrow_array = ImportArray(&array, &schema);
ARROW_EXPECT_OK(maybe_arrow_array);
@@ -1011,20 +1093,20 @@ TEST(ArrayTest, ArrayTestAppendToFixedSizeListArray) {
// Make sure number of children is checked at finish
array.n_children = 0;
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, &error), EINVAL);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, &error), EINVAL);
EXPECT_STREQ(ArrowErrorMessage(&error),
"Expected 1 child of fixed-size array but found 0 child
arrays");
array.n_children = 1;
// Make sure final child size is checked at finish
array.children[0]->length = array.children[0]->length - 1;
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, &error), EINVAL);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, &error), EINVAL);
EXPECT_STREQ(ArrowErrorMessage(&error),
"Expected child of fixed-size list array with length >= 8 but
found array "
"with length 7");
array.children[0]->length = array.children[0]->length + 1;
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
auto arrow_array = ImportArray(&array, &schema);
ARROW_EXPECT_OK(arrow_array);
@@ -1075,7 +1157,7 @@ TEST(ArrayTest, ArrayTestAppendToStructArray) {
ASSERT_EQ(ArrowArrayAppendEmpty(&array, 1), NANOARROW_OK);
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
auto arrow_array = ImportArray(&array, &schema);
ARROW_EXPECT_OK(arrow_array);
@@ -1148,7 +1230,7 @@ TEST(ArrayTest, ArrayTestAppendToDenseUnionArray) {
EXPECT_EQ(ArrowArrayFinishUnionElement(&array, 1), NANOARROW_OK);
EXPECT_EQ(ArrowArrayAppendEmpty(&array, 1), NANOARROW_OK);
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
auto arrow_array = ImportArray(&array, &schema);
ARROW_EXPECT_OK(arrow_array);
@@ -1193,7 +1275,7 @@ TEST(ArrayTest, ArrayTestAppendToSparseUnionArray) {
NANOARROW_OK);
EXPECT_EQ(ArrowArrayFinishUnionElement(&array, 1), NANOARROW_OK);
EXPECT_EQ(ArrowArrayAppendEmpty(&array, 1), NANOARROW_OK);
- EXPECT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
auto arrow_array = ImportArray(&array, &schema);
ARROW_EXPECT_OK(arrow_array);
@@ -1264,7 +1346,7 @@ TEST(ArrayTest, ArrayViewTestBasic) {
ASSERT_EQ(ArrowBufferAppendInt32(ArrowArrayBuffer(&array, 1), 13),
NANOARROW_OK);
array.length = 3;
array.null_count = 0;
- ASSERT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ ASSERT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
EXPECT_EQ(ArrowArrayViewSetArray(&array_view, &array, &error), NANOARROW_OK);
EXPECT_EQ(ArrowArrayViewValidateFull(&array_view, &error), NANOARROW_OK);
@@ -1277,7 +1359,7 @@ TEST(ArrayTest, ArrayViewTestBasic) {
// Build with validity buffer
ASSERT_EQ(ArrowBitmapAppend(ArrowArrayValidityBitmap(&array), 1, 3),
NANOARROW_OK);
array.null_count = -1;
- ASSERT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ ASSERT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
EXPECT_EQ(ArrowArrayViewSetArray(&array_view, &array, &error), NANOARROW_OK);
EXPECT_EQ(ArrowArrayViewValidateFull(&array_view, &error), NANOARROW_OK);
@@ -1362,7 +1444,7 @@ TEST(ArrayTest, ArrayViewTestString) {
ASSERT_EQ(ArrowBufferReserve(ArrowArrayBuffer(&array, 2), 4), NANOARROW_OK);
ArrowBufferAppendUnsafe(ArrowArrayBuffer(&array, 2), "abcd", 4);
array.length = 1;
- ASSERT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ ASSERT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
EXPECT_EQ(ArrowArrayViewSetArray(&array_view, &array, &error), NANOARROW_OK);
EXPECT_EQ(ArrowArrayViewValidateFull(&array_view, &error), NANOARROW_OK);
@@ -1430,7 +1512,7 @@ TEST(ArrayTest, ArrayViewTestLargeString) {
ASSERT_EQ(ArrowBufferReserve(ArrowArrayBuffer(&array, 2), 4), NANOARROW_OK);
ArrowBufferAppendUnsafe(ArrowArrayBuffer(&array, 2), "abcd", 4);
array.length = 1;
- ASSERT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ ASSERT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
EXPECT_EQ(ArrowArrayViewSetArray(&array_view, &array, &error), NANOARROW_OK);
EXPECT_EQ(ArrowArrayViewValidateFull(&array_view, &error), NANOARROW_OK);
@@ -1516,7 +1598,7 @@ TEST(ArrayTest, ArrayViewTestList) {
ASSERT_EQ(ArrowArrayStartAppending(&array), NANOARROW_OK);
ASSERT_EQ(ArrowArrayAppendInt(array.children[0], 1234), NANOARROW_OK);
ASSERT_EQ(ArrowArrayFinishElement(&array), NANOARROW_OK);
- ASSERT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ ASSERT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
EXPECT_EQ(ArrowArrayViewSetArray(&array_view, &array, nullptr),
NANOARROW_OK);
EXPECT_EQ(ArrowArrayViewValidateFull(&array_view, nullptr), NANOARROW_OK);
@@ -1569,7 +1651,7 @@ TEST(ArrayTest, ArrayViewTestLargeList) {
ASSERT_EQ(ArrowArrayStartAppending(&array), NANOARROW_OK);
ASSERT_EQ(ArrowArrayAppendInt(array.children[0], 1234), NANOARROW_OK);
ASSERT_EQ(ArrowArrayFinishElement(&array), NANOARROW_OK);
- ASSERT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ ASSERT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
EXPECT_EQ(ArrowArrayViewSetArray(&array_view, &array, nullptr),
NANOARROW_OK);
EXPECT_EQ(ArrowArrayViewValidateFull(&array_view, nullptr), NANOARROW_OK);
@@ -1646,7 +1728,7 @@ TEST(ArrayTest, ArrayViewTestStructArray) {
ASSERT_EQ(ArrowBufferAppendInt32(ArrowArrayBuffer(array.children[0], 1),
123),
NANOARROW_OK);
array.children[0]->length = 1;
- ASSERT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ ASSERT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
EXPECT_EQ(ArrowArrayViewSetArray(&array_view, &array, &error), NANOARROW_OK);
EXPECT_EQ(ArrowArrayViewValidateFull(&array_view, &error), NANOARROW_OK);
@@ -1689,7 +1771,7 @@ TEST(ArrayTest, ArrayViewTestFixedSizeListArray) {
ASSERT_EQ(ArrowBufferAppendInt32(ArrowArrayBuffer(array.children[0], 1),
789),
NANOARROW_OK);
array.children[0]->length = 3;
- ASSERT_EQ(ArrowArrayFinishBuilding(&array, &error), NANOARROW_OK);
+ ASSERT_EQ(ArrowArrayFinishBuildingDefault(&array, &error), NANOARROW_OK);
EXPECT_EQ(ArrowArrayViewSetArray(&array_view, &array, &error), NANOARROW_OK);
EXPECT_EQ(ArrowArrayViewValidateFull(&array_view, &error), NANOARROW_OK);
@@ -1720,7 +1802,7 @@ TEST(ArrayTest, ArrayViewTestUnionChildIndices) {
ASSERT_EQ(ArrowArrayAppendString(array.children[1], ArrowCharView("one
twenty four")),
NANOARROW_OK);
ASSERT_EQ(ArrowArrayFinishUnionElement(&array, 1), NANOARROW_OK);
- ASSERT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ ASSERT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
// The ArrayView for a union could in theroy be created without a schema,
// in which case the type_ids are assumed to equal child indices
@@ -1822,7 +1904,7 @@ TEST(ArrayTest, ArrayViewTestDenseUnionGet) {
NANOARROW_OK);
ASSERT_EQ(ArrowArrayFinishUnionElement(&array, 1), NANOARROW_OK);
ASSERT_EQ(ArrowArrayAppendNull(&array, 1), NANOARROW_OK);
- ASSERT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ ASSERT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
// Initialize the array view
ASSERT_EQ(ArrowArrayViewInitFromSchema(&array_view, &schema, nullptr),
NANOARROW_OK);
@@ -1867,7 +1949,7 @@ TEST(ArrayTest, ArrayViewTestSparseUnionGet) {
NANOARROW_OK);
ASSERT_EQ(ArrowArrayFinishUnionElement(&array, 1), NANOARROW_OK);
ASSERT_EQ(ArrowArrayAppendNull(&array, 1), NANOARROW_OK);
- ASSERT_EQ(ArrowArrayFinishBuilding(&array, nullptr), NANOARROW_OK);
+ ASSERT_EQ(ArrowArrayFinishBuildingDefault(&array, nullptr), NANOARROW_OK);
// Initialize the array view
ASSERT_EQ(ArrowArrayViewInitFromSchema(&array_view, &schema, nullptr),
NANOARROW_OK);
diff --git a/src/nanoarrow/nanoarrow.h b/src/nanoarrow/nanoarrow.h
index 558d3d1..9b67c4f 100644
--- a/src/nanoarrow/nanoarrow.h
+++ b/src/nanoarrow/nanoarrow.h
@@ -102,6 +102,8 @@
#define ArrowArrayReserve NANOARROW_SYMBOL(NANOARROW_NAMESPACE,
ArrowArrayReserve)
#define ArrowArrayFinishBuilding \
NANOARROW_SYMBOL(NANOARROW_NAMESPACE, ArrowArrayFinishBuilding)
+#define ArrowArrayFinishBuildingDefault \
+ NANOARROW_SYMBOL(NANOARROW_NAMESPACE, ArrowArrayFinishBuildingDefault)
#define ArrowArrayViewInitFromType \
NANOARROW_SYMBOL(NANOARROW_NAMESPACE, ArrowArrayViewInitFromType)
#define ArrowArrayViewInitFromSchema \
@@ -704,7 +706,10 @@ static inline void ArrowBitmapReset(struct ArrowBitmap*
bitmap);
/// \defgroup nanoarrow-array Creating arrays
///
-/// These functions allocate, copy, and destroy ArrowArray structures
+/// These functions allocate, copy, and destroy ArrowArray structures.
+/// Once an ArrowArray has been initialized via ArrowArrayInitFromType()
+/// or ArrowArrayInitFromSchema(), the caller is responsible for releasing
+/// it using the embedded release callback.
///
/// @{
@@ -852,10 +857,21 @@ static inline ArrowErrorCode ArrowArrayShrinkToFit(struct
ArrowArray* array);
/// \brief Finish building an ArrowArray
///
/// Flushes any pointers from internal buffers that may have been reallocated
-/// into the array->buffers array and checks the actual size of the buffers
+/// into array->buffers and checks the actual size of the buffers
/// against the expected size based on the final length.
/// array must have been allocated using ArrowArrayInitFromType()
+ArrowErrorCode ArrowArrayFinishBuildingDefault(struct ArrowArray* array,
+ struct ArrowError* error);
+
+/// \brief Finish building an ArrowArray with explicit validation
+///
+/// Finish building with an explicit validation level. This could perform less
validation
+/// (i.e. NANOARROW_VALIDATION_LEVEL_NONE or
NANOARROW_VALIDATION_LEVEL_MINIMAL) if CPU
+/// buffer data access is not possible or more validation (i.e.,
+/// NANOARROW_VALIDATION_LEVEL_FULL) if buffer content was obtained from an
untrusted or
+/// corruptable source.
ArrowErrorCode ArrowArrayFinishBuilding(struct ArrowArray* array,
+ enum ArrowValidationLevel
validation_level,
struct ArrowError* error);
/// @}
diff --git a/src/nanoarrow/nanoarrow_hpp_test.cc
b/src/nanoarrow/nanoarrow_hpp_test.cc
index b3ed58a..bd5393a 100644
--- a/src/nanoarrow/nanoarrow_hpp_test.cc
+++ b/src/nanoarrow/nanoarrow_hpp_test.cc
@@ -26,7 +26,7 @@ TEST(NanoarrowHppTest, NanoarrowHppUniqueArrayTest) {
ArrowArrayInitFromType(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);
+ ASSERT_EQ(ArrowArrayFinishBuildingDefault(array.get(), nullptr),
NANOARROW_OK);
EXPECT_NE(array->release, nullptr);
EXPECT_EQ(array->length, 1);
@@ -191,7 +191,7 @@ TEST(NanoarrowHppTest, NanoarrowHppVectorArrayStreamTest) {
EXPECT_EQ(ArrowArrayInitFromType(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);
+ EXPECT_EQ(ArrowArrayFinishBuildingDefault(array_in.get(), nullptr),
NANOARROW_OK);
nanoarrow::UniqueSchema schema_in;
EXPECT_EQ(ArrowSchemaInitFromType(schema_in.get(), NANOARROW_TYPE_INT32),
NANOARROW_OK);
diff --git a/src/nanoarrow/nanoarrow_types.h b/src/nanoarrow/nanoarrow_types.h
index b9af6bb..c8eede8 100644
--- a/src/nanoarrow/nanoarrow_types.h
+++ b/src/nanoarrow/nanoarrow_types.h
@@ -319,6 +319,25 @@ enum ArrowTimeUnit {
NANOARROW_TIME_UNIT_NANO = 3
};
+/// \brief Validation level enumerator
+/// \ingroup nanoarrow-array
+enum ArrowValidationLevel {
+ /// \brief Do not validate buffer sizes or content.
+ NANOARROW_VALIDATION_LEVEL_NONE = 0,
+
+ /// \brief Validate buffer sizes that depend on array length but do not
validate buffer
+ /// sizes that depend on buffer data access.
+ NANOARROW_VALIDATION_LEVEL_MINIMAL = 1,
+
+ /// \brief Validate all buffer sizes, including those that require buffer
data access,
+ /// but do not perform any checks that are O(1) along the length of the
buffers.
+ NANOARROW_VALIDATION_LEVEL_DEFAULT = 2,
+
+ /// \brief Validate all buffer sizes and all buffer content. This is useful
in the
+ /// context of untrusted input or input that may have been corrupted in
transit.
+ NANOARROW_VALIDATION_LEVEL_FULL = 3
+};
+
/// \brief Get a string value of an enum ArrowTimeUnit value
/// \ingroup nanoarrow-utils
///