1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
1718use crate::{i256, IntervalDayTime, IntervalMonthDayNano};
19use half::f16;
2021mod private {
22pub trait Sealed {}
23}
2425/// Trait expressing a Rust type that has the same in-memory representation as
26/// Arrow.
27///
28/// This includes `i16`, `f32`, but excludes `bool` (which in arrow is
29/// represented in bits).
30///
31/// In little endian machines, types that implement [`ArrowNativeType`] can be
32/// memcopied to arrow buffers as is.
33///
34/// # Transmute Safety
35///
36/// A type T implementing this trait means that any arbitrary slice of bytes of length and
37/// alignment `size_of::<T>()` can be safely interpreted as a value of that type without
38/// being unsound, i.e. potentially resulting in undefined behaviour.
39///
40/// Note: in the case of floating point numbers this transmutation can result in a signalling
41/// NaN, which, whilst sound, can be unwieldy. In general, whilst it is perfectly sound to
42/// reinterpret bytes as different types using this trait, it is likely unwise. For more information
43/// see [f32::from_bits] and [f64::from_bits].
44///
45/// Note: `bool` is restricted to `0` or `1`, and so `bool: !ArrowNativeType`
46///
47/// # Sealed
48///
49/// Due to the above restrictions, this trait is sealed to prevent accidental misuse
50pub trait ArrowNativeType:
51 std::fmt::Debug + Send + Sync + Copy + PartialOrd + Default + private::Sealed + 'static
52{
53/// Returns the byte width of this native type.
54fn get_byte_width() -> usize {
55 std::mem::size_of::<Self>()
56 }
5758/// Convert native integer type from usize
59 ///
60 /// Returns `None` if [`Self`] is not an integer or conversion would result
61 /// in truncation/overflow
62fn from_usize(_: usize) -> Option<Self>;
6364/// Convert to usize according to the [`as`] operator
65 ///
66 /// [`as`]: https://doc.rust-lang.org/reference/expressions/operator-expr.html#numeric-cast
67fn as_usize(self) -> usize;
6869/// Convert from usize according to the [`as`] operator
70 ///
71 /// [`as`]: https://doc.rust-lang.org/reference/expressions/operator-expr.html#numeric-cast
72fn usize_as(i: usize) -> Self;
7374/// Convert native type to usize.
75 ///
76 /// Returns `None` if [`Self`] is not an integer or conversion would result
77 /// in truncation/overflow
78fn to_usize(self) -> Option<usize>;
7980/// Convert native type to isize.
81 ///
82 /// Returns `None` if [`Self`] is not an integer or conversion would result
83 /// in truncation/overflow
84fn to_isize(self) -> Option<isize>;
8586/// Convert native type to i64.
87 ///
88 /// Returns `None` if [`Self`] is not an integer or conversion would result
89 /// in truncation/overflow
90fn to_i64(self) -> Option<i64>;
9192/// Convert native type from i32.
93 ///
94 /// Returns `None` if [`Self`] is not `i32`
95#[deprecated(note = "please use `Option::Some` instead")]
96fn from_i32(_: i32) -> Option<Self> {
97None
98}
99100/// Convert native type from i64.
101 ///
102 /// Returns `None` if [`Self`] is not `i64`
103#[deprecated(note = "please use `Option::Some` instead")]
104fn from_i64(_: i64) -> Option<Self> {
105None
106}
107108/// Convert native type from i128.
109 ///
110 /// Returns `None` if [`Self`] is not `i128`
111#[deprecated(note = "please use `Option::Some` instead")]
112fn from_i128(_: i128) -> Option<Self> {
113None
114}
115}
116117macro_rules! native_integer {
118 ($t: ty $(, $from:ident)*) => {
119impl private::Sealed for $t {}
120impl ArrowNativeType for $t {
121#[inline]
122fn from_usize(v: usize) -> Option<Self> {
123 v.try_into().ok()
124 }
125126#[inline]
127fn to_usize(self) -> Option<usize> {
128self.try_into().ok()
129 }
130131#[inline]
132fn to_isize(self) -> Option<isize> {
133self.try_into().ok()
134 }
135136#[inline]
137fn to_i64(self) -> Option<i64> {
138self.try_into().ok()
139 }
140141#[inline]
142fn as_usize(self) -> usize {
143self as _
144}
145146#[inline]
147fn usize_as(i: usize) -> Self {
148 i as _
149}
150151152 $(
153#[inline]
154fn $from(v: $t) -> Option<Self> {
155Some(v)
156 }
157 )*
158 }
159 };
160}
161162native_integer!(i8);
163native_integer!(i16);
164native_integer!(i32, from_i32);
165native_integer!(i64, from_i64);
166native_integer!(i128, from_i128);
167native_integer!(u8);
168native_integer!(u16);
169native_integer!(u32);
170native_integer!(u64);
171native_integer!(u128);
172173macro_rules! native_float {
174 ($t:ty, $s:ident, $as_usize: expr, $i:ident, $usize_as: expr) => {
175impl private::Sealed for $t {}
176impl ArrowNativeType for $t {
177#[inline]
178fn from_usize(_: usize) -> Option<Self> {
179None
180}
181182#[inline]
183fn to_usize(self) -> Option<usize> {
184None
185}
186187#[inline]
188fn to_isize(self) -> Option<isize> {
189None
190}
191192#[inline]
193fn to_i64(self) -> Option<i64> {
194None
195}
196197#[inline]
198fn as_usize($s) -> usize {
199$as_usize
200}
201202#[inline]
203fn usize_as($i: usize) -> Self {
204$usize_as
205}
206 }
207 };
208}
209210native_float!(f16, self, self.to_f32() as _, i, f16::from_f32(i as _));
211native_float!(f32, self, self as _, i, i as _);
212native_float!(f64, self, self as _, i, i as _);
213214impl private::Sealed for i256 {}
215impl ArrowNativeType for i256 {
216fn from_usize(u: usize) -> Option<Self> {
217Some(Self::from_parts(u as u128, 0))
218 }
219220fn as_usize(self) -> usize {
221self.to_parts().0 as usize
222 }
223224fn usize_as(i: usize) -> Self {
225Self::from_parts(i as u128, 0)
226 }
227228fn to_usize(self) -> Option<usize> {
229let (low, high) = self.to_parts();
230if high != 0 {
231return None;
232 }
233 low.try_into().ok()
234 }
235236fn to_isize(self) -> Option<isize> {
237self.to_i128()?.try_into().ok()
238 }
239240fn to_i64(self) -> Option<i64> {
241self.to_i128()?.try_into().ok()
242 }
243}
244245impl private::Sealed for IntervalMonthDayNano {}
246impl ArrowNativeType for IntervalMonthDayNano {
247fn from_usize(_: usize) -> Option<Self> {
248None
249}
250251fn as_usize(self) -> usize {
252 ((self.months as u64) | ((self.days as u64) << 32)) as usize
253 }
254255fn usize_as(i: usize) -> Self {
256Self::new(i as _, ((i as u64) >> 32) as _, 0)
257 }
258259fn to_usize(self) -> Option<usize> {
260None
261}
262263fn to_isize(self) -> Option<isize> {
264None
265}
266267fn to_i64(self) -> Option<i64> {
268None
269}
270}
271272impl private::Sealed for IntervalDayTime {}
273impl ArrowNativeType for IntervalDayTime {
274fn from_usize(_: usize) -> Option<Self> {
275None
276}
277278fn as_usize(self) -> usize {
279 ((self.days as u64) | ((self.milliseconds as u64) << 32)) as usize
280 }
281282fn usize_as(i: usize) -> Self {
283Self::new(i as _, ((i as u64) >> 32) as _)
284 }
285286fn to_usize(self) -> Option<usize> {
287None
288}
289290fn to_isize(self) -> Option<isize> {
291None
292}
293294fn to_i64(self) -> Option<i64> {
295None
296}
297}
298299/// Allows conversion from supported Arrow types to a byte slice.
300pub trait ToByteSlice {
301/// Converts this instance into a byte slice
302fn to_byte_slice(&self) -> &[u8];
303}
304305impl<T: ArrowNativeType> ToByteSlice for [T] {
306#[inline]
307fn to_byte_slice(&self) -> &[u8] {
308let raw_ptr = self.as_ptr() as *const u8;
309unsafe { std::slice::from_raw_parts(raw_ptr, std::mem::size_of_val(self)) }
310 }
311}
312313impl<T: ArrowNativeType> ToByteSlice for T {
314#[inline]
315fn to_byte_slice(&self) -> &[u8] {
316let raw_ptr = self as *const T as *const u8;
317unsafe { std::slice::from_raw_parts(raw_ptr, std::mem::size_of::<T>()) }
318 }
319}
320321#[cfg(test)]
322mod tests {
323use super::*;
324325#[test]
326fn test_i256() {
327let a = i256::from_parts(0, 0);
328assert_eq!(a.as_usize(), 0);
329assert_eq!(a.to_usize().unwrap(), 0);
330assert_eq!(a.to_isize().unwrap(), 0);
331332let a = i256::from_parts(0, -1);
333assert_eq!(a.as_usize(), 0);
334assert!(a.to_usize().is_none());
335assert!(a.to_usize().is_none());
336337let a = i256::from_parts(u128::MAX, -1);
338assert_eq!(a.as_usize(), usize::MAX);
339assert!(a.to_usize().is_none());
340assert_eq!(a.to_isize().unwrap(), -1);
341 }
342343#[test]
344fn test_interval_usize() {
345assert_eq!(IntervalDayTime::new(1, 0).as_usize(), 1);
346assert_eq!(IntervalMonthDayNano::new(1, 0, 0).as_usize(), 1);
347348let a = IntervalDayTime::new(23, 53);
349let b = IntervalDayTime::usize_as(a.as_usize());
350assert_eq!(a, b);
351352let a = IntervalMonthDayNano::new(23, 53, 0);
353let b = IntervalMonthDayNano::usize_as(a.as_usize());
354assert_eq!(a, b);
355 }
356}