This is an automated email from the ASF dual-hosted git repository.
alamb pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
The following commit(s) were added to refs/heads/main by this push:
new 730288822b Introduce `UnsafeFlag` to manage disabling `ArrayData`
validation (#7027)
730288822b is described below
commit 730288822bc2b8e73ecae541fb3ef8d0c24ef43f
Author: Andrew Lamb <[email protected]>
AuthorDate: Thu Feb 6 12:13:00 2025 -0500
Introduce `UnsafeFlag` to manage disabling `ArrayData` validation (#7027)
* Introduce UnsafeFlag to manage disabling validation
* fix docs
---
arrow-data/src/data.rs | 48 +++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 41 insertions(+), 7 deletions(-)
diff --git a/arrow-data/src/data.rs b/arrow-data/src/data.rs
index be7e5f86a0..4314b550d6 100644
--- a/arrow-data/src/data.rs
+++ b/arrow-data/src/data.rs
@@ -28,6 +28,7 @@ use std::mem;
use std::ops::Range;
use std::sync::Arc;
+use crate::data::private::UnsafeFlag;
use crate::{equal, validate_binary_view, validate_string_view};
#[inline]
@@ -255,6 +256,10 @@ impl ArrayData {
buffers: Vec<Buffer>,
child_data: Vec<ArrayData>,
) -> Self {
+ let mut skip_validation = UnsafeFlag::new();
+ // SAFETY: caller responsible for ensuring data is valid
+ skip_validation.set(true);
+
ArrayDataBuilder {
data_type,
len,
@@ -265,8 +270,7 @@ impl ArrayData {
buffers,
child_data,
align_buffers: false,
- // SAFETY: caller responsible for ensuring data is valid
- skip_validation: true,
+ skip_validation,
}
.build()
.unwrap()
@@ -1779,6 +1783,36 @@ impl PartialEq for ArrayData {
}
}
+mod private {
+ /// A boolean flag that cannot be mutated outside of unsafe code.
+ ///
+ /// Defaults to a value of false.
+ ///
+ /// This structure is used to enforce safety in the [`ArrayDataBuilder`]
+ ///
+ /// [`ArrayDataBuilder`]: super::ArrayDataBuilder
+ #[derive(Debug)]
+ pub struct UnsafeFlag(bool);
+
+ impl UnsafeFlag {
+ /// Creates a new `UnsafeFlag` with the value set to `false`
+ #[inline]
+ pub const fn new() -> Self {
+ Self(false)
+ }
+
+ #[inline]
+ pub unsafe fn set(&mut self, val: bool) {
+ self.0 = val;
+ }
+
+ #[inline]
+ pub fn get(&self) -> bool {
+ self.0
+ }
+ }
+}
+
/// Builder for [`ArrayData`] type
#[derive(Debug)]
pub struct ArrayDataBuilder {
@@ -1803,7 +1837,7 @@ pub struct ArrayDataBuilder {
/// This flag can only be set to true using `unsafe` APIs. However, once
true
/// subsequent calls to `build()` may result in undefined behavior if the
data
/// is not valid.
- skip_validation: bool,
+ skip_validation: UnsafeFlag,
}
impl ArrayDataBuilder {
@@ -1820,7 +1854,7 @@ impl ArrayDataBuilder {
buffers: vec![],
child_data: vec![],
align_buffers: false,
- skip_validation: false,
+ skip_validation: UnsafeFlag::new(),
}
}
@@ -1957,7 +1991,7 @@ impl ArrayDataBuilder {
}
// SAFETY: `skip_validation` is only set to true using `unsafe` APIs
- if !skip_validation || cfg!(feature = "force_validate") {
+ if !skip_validation.get() || cfg!(feature = "force_validate") {
data.validate_data()?;
}
Ok(data)
@@ -2003,7 +2037,7 @@ impl ArrayDataBuilder {
/// If validation is skipped, the buffers must form a valid Arrow array,
/// otherwise undefined behavior will result
pub unsafe fn skip_validation(mut self, skip_validation: bool) -> Self {
- self.skip_validation = skip_validation;
+ self.skip_validation.set(skip_validation);
self
}
}
@@ -2020,7 +2054,7 @@ impl From<ArrayData> for ArrayDataBuilder {
null_bit_buffer: None,
null_count: None,
align_buffers: false,
- skip_validation: false,
+ skip_validation: UnsafeFlag::new(),
}
}
}