diff --git a/arrow/src/datatypes/native.rs b/arrow/src/datatypes/native.rs index 2a8c99f0f89..efb1d3e6b2d 100644 --- a/arrow/src/datatypes/native.rs +++ b/arrow/src/datatypes/native.rs @@ -19,6 +19,10 @@ use super::DataType; use half::f16; use serde_json::{Number, Value}; +mod private { + pub trait Sealed {} +} + /// Trait declaring any type that is serializable to JSON. This includes all primitive types (bool, i32, etc.). pub trait JsonSerializable: 'static { fn into_json_value(self) -> Option; @@ -26,8 +30,25 @@ pub trait JsonSerializable: 'static { /// Trait expressing a Rust type that has the same in-memory representation /// as Arrow. This includes `i16`, `f32`, but excludes `bool` (which in arrow is represented in bits). +/// /// In little endian machines, types that implement [`ArrowNativeType`] can be memcopied to arrow buffers /// as is. +/// +/// # Transmute Safety +/// +/// A type T implementing this trait means that any arbitrary slice of bytes of length and +/// alignment `size_of::()` can be safely interpreted as a value of that type without +/// being unsound, i.e. potentially resulting in undefined behaviour. +/// +/// Note: in the case of floating point numbers this transmutation can result in a signalling +/// NaN, which, whilst sound, can be unwieldy. In general, whilst it is perfectly sound to +/// reinterpret bytes as different types using this trait, it is likely unwise +/// +/// Note: `bool` is restricted to `0` or `1`, and so `bool: !ArrowNativeType` +/// +/// # Sealed +/// +/// Due to the above restrictions, this trait is sealed to prevent accidental misuse pub trait ArrowNativeType: std::fmt::Debug + Send @@ -37,6 +58,7 @@ pub trait ArrowNativeType: + std::str::FromStr + Default + JsonSerializable + + private::Sealed { /// Convert native type from usize. #[inline] @@ -109,6 +131,7 @@ impl JsonSerializable for i8 { } } +impl private::Sealed for i8 {} impl ArrowNativeType for i8 { #[inline] fn from_usize(v: usize) -> Option { @@ -132,6 +155,7 @@ impl JsonSerializable for i16 { } } +impl private::Sealed for i16 {} impl ArrowNativeType for i16 { #[inline] fn from_usize(v: usize) -> Option { @@ -155,6 +179,7 @@ impl JsonSerializable for i32 { } } +impl private::Sealed for i32 {} impl ArrowNativeType for i32 { #[inline] fn from_usize(v: usize) -> Option { @@ -184,6 +209,7 @@ impl JsonSerializable for i64 { } } +impl private::Sealed for i64 {} impl ArrowNativeType for i64 { #[inline] fn from_usize(v: usize) -> Option { @@ -217,6 +243,7 @@ impl JsonSerializable for i128 { } } +impl private::Sealed for i128 {} impl ArrowNativeType for i128 { #[inline] fn from_usize(v: usize) -> Option { @@ -246,6 +273,7 @@ impl JsonSerializable for u8 { } } +impl private::Sealed for u8 {} impl ArrowNativeType for u8 { #[inline] fn from_usize(v: usize) -> Option { @@ -269,6 +297,7 @@ impl JsonSerializable for u16 { } } +impl private::Sealed for u16 {} impl ArrowNativeType for u16 { #[inline] fn from_usize(v: usize) -> Option { @@ -292,6 +321,7 @@ impl JsonSerializable for u32 { } } +impl private::Sealed for u32 {} impl ArrowNativeType for u32 { #[inline] fn from_usize(v: usize) -> Option { @@ -315,6 +345,7 @@ impl JsonSerializable for u64 { } } +impl private::Sealed for u64 {} impl ArrowNativeType for u64 { #[inline] fn from_usize(v: usize) -> Option { @@ -351,8 +382,11 @@ impl JsonSerializable for f64 { } impl ArrowNativeType for f16 {} +impl private::Sealed for f16 {} impl ArrowNativeType for f32 {} +impl private::Sealed for f32 {} impl ArrowNativeType for f64 {} +impl private::Sealed for f64 {} /// Allows conversion from supported Arrow types to a byte slice. pub trait ToByteSlice {