Skip to main content

parquet/
data_type.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: See the NOTICE file distributed with this work for additional information regarding copyright ownership
3// SPDX-FileContributor: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements
4
5//! Data types that connect Parquet physical types with their Rust-specific
6//! representations.
7use bytes::Bytes;
8use half::f16;
9use std::cmp::Ordering;
10use std::fmt;
11use std::mem;
12use std::ops::{Deref, DerefMut};
13use std::str::from_utf8;
14
15use crate::basic::Type;
16use crate::column::reader::{ColumnReader, ColumnReaderImpl};
17use crate::column::writer::{ColumnWriter, ColumnWriterImpl};
18use crate::errors::{ParquetError, Result};
19use crate::util::bit_util::FromBytes;
20
21/// Rust representation for logical type INT96, value is backed by an array of `u32`.
22/// The type only takes 12 bytes, without extra padding.
23#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
24pub struct Int96 {
25    value: [u32; 3],
26}
27
28const JULIAN_DAY_OF_EPOCH: i64 = 2_440_588;
29
30/// Number of seconds in a day
31const SECONDS_IN_DAY: i64 = 86_400;
32/// Number of milliseconds in a second
33const MILLISECONDS: i64 = 1_000;
34/// Number of microseconds in a second
35const MICROSECONDS: i64 = 1_000_000;
36/// Number of nanoseconds in a second
37const NANOSECONDS: i64 = 1_000_000_000;
38
39/// Number of milliseconds in a day
40const MILLISECONDS_IN_DAY: i64 = SECONDS_IN_DAY * MILLISECONDS;
41/// Number of microseconds in a day
42const MICROSECONDS_IN_DAY: i64 = SECONDS_IN_DAY * MICROSECONDS;
43/// Number of nanoseconds in a day
44const NANOSECONDS_IN_DAY: i64 = SECONDS_IN_DAY * NANOSECONDS;
45
46impl Int96 {
47    /// Creates new INT96 type struct with no data set.
48    pub fn new() -> Self {
49        Self { value: [0; 3] }
50    }
51
52    /// Returns underlying data as slice of [`u32`].
53    #[inline]
54    pub fn data(&self) -> &[u32] {
55        &self.value
56    }
57
58    /// Sets data for this INT96 type.
59    #[inline]
60    pub fn set_data(&mut self, elem0: u32, elem1: u32, elem2: u32) {
61        self.value = [elem0, elem1, elem2];
62    }
63
64    /// Converts this INT96 into an i64 representing the number of SECONDS since EPOCH
65    ///
66    /// Will wrap around on overflow
67    #[inline]
68    pub fn to_seconds(&self) -> i64 {
69        let (day, nanos) = self.data_as_days_and_nanos();
70        (day as i64 - JULIAN_DAY_OF_EPOCH)
71            .wrapping_mul(SECONDS_IN_DAY)
72            .wrapping_add(nanos / 1_000_000_000)
73    }
74
75    /// Converts this INT96 into an i64 representing the number of MILLISECONDS since EPOCH
76    ///
77    /// Will wrap around on overflow
78    #[inline]
79    pub fn to_millis(&self) -> i64 {
80        let (day, nanos) = self.data_as_days_and_nanos();
81        (day as i64 - JULIAN_DAY_OF_EPOCH)
82            .wrapping_mul(MILLISECONDS_IN_DAY)
83            .wrapping_add(nanos / 1_000_000)
84    }
85
86    /// Converts this INT96 into an i64 representing the number of MICROSECONDS since EPOCH
87    ///
88    /// Will wrap around on overflow
89    #[inline]
90    pub fn to_micros(&self) -> i64 {
91        let (day, nanos) = self.data_as_days_and_nanos();
92        (day as i64 - JULIAN_DAY_OF_EPOCH)
93            .wrapping_mul(MICROSECONDS_IN_DAY)
94            .wrapping_add(nanos / 1_000)
95    }
96
97    /// Converts this INT96 into an i64 representing the number of NANOSECONDS since EPOCH
98    ///
99    /// Will wrap around on overflow
100    #[inline]
101    pub fn to_nanos(&self) -> i64 {
102        let (day, nanos) = self.data_as_days_and_nanos();
103        (day as i64 - JULIAN_DAY_OF_EPOCH)
104            .wrapping_mul(NANOSECONDS_IN_DAY)
105            .wrapping_add(nanos)
106    }
107
108    #[inline]
109    fn get_days(&self) -> i32 {
110        self.data()[2] as i32
111    }
112
113    #[inline]
114    fn get_nanos(&self) -> i64 {
115        ((self.data()[1] as i64) << 32) + self.data()[0] as i64
116    }
117
118    #[inline]
119    fn data_as_days_and_nanos(&self) -> (i32, i64) {
120        (self.get_days(), self.get_nanos())
121    }
122}
123
124impl PartialOrd for Int96 {
125    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
126        Some(self.cmp(other))
127    }
128}
129
130impl Ord for Int96 {
131    /// Order `Int96` correctly for (deprecated) timestamp types.
132    ///
133    /// Note: this is done even though the Int96 type is deprecated.
134    /// Because some engines, notably Spark and Databricks Photon, still write
135    /// Int96 timestamps, a new `ColumnOrder` variant has been added to
136    /// the Parquet specification. See [parquet-format/#584].
137    ///
138    /// [parquet-format/#584]: https://github.com/apache/parquet-format/pull/584
139    fn cmp(&self, other: &Self) -> Ordering {
140        match self.get_days().cmp(&other.get_days()) {
141            Ordering::Equal => self.get_nanos().cmp(&other.get_nanos()),
142            ord => ord,
143        }
144    }
145}
146impl From<Vec<u32>> for Int96 {
147    fn from(buf: Vec<u32>) -> Self {
148        assert_eq!(buf.len(), 3);
149        let mut result = Self::new();
150        result.set_data(buf[0], buf[1], buf[2]);
151        result
152    }
153}
154
155impl fmt::Display for Int96 {
156    #[cold]
157    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
158        write!(f, "{:?}", self.data())
159    }
160}
161
162/// Rust representation for BYTE_ARRAY and FIXED_LEN_BYTE_ARRAY Parquet physical types.
163/// Value is backed by a byte buffer.
164#[derive(Clone, Default)]
165pub struct ByteArray {
166    data: Option<Bytes>,
167}
168
169// Special case Debug that prints out byte arrays that are valid utf8 as &str's
170impl std::fmt::Debug for ByteArray {
171    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
172        let mut debug_struct = f.debug_struct("ByteArray");
173        match self.as_utf8() {
174            Ok(s) => debug_struct.field("data", &s),
175            Err(_) => debug_struct.field("data", &self.data),
176        };
177        debug_struct.finish()
178    }
179}
180
181impl PartialOrd for ByteArray {
182    fn partial_cmp(&self, other: &ByteArray) -> Option<Ordering> {
183        // sort nulls first (consistent with PartialCmp on Option)
184        //
185        // Since ByteBuffer doesn't implement PartialOrd, so can't
186        // derive an implementation
187        match (&self.data, &other.data) {
188            (None, None) => Some(Ordering::Equal),
189            (None, Some(_)) => Some(Ordering::Less),
190            (Some(_), None) => Some(Ordering::Greater),
191            (Some(self_data), Some(other_data)) => {
192                // compare slices directly
193                self_data.partial_cmp(&other_data)
194            }
195        }
196    }
197}
198
199impl ByteArray {
200    /// Creates new byte array with no data set.
201    #[inline]
202    pub fn new() -> Self {
203        ByteArray { data: None }
204    }
205
206    /// Gets length of the underlying byte buffer.
207    ///
208    /// # Panics
209    ///
210    /// Panics if no data has been set, e.g. on a [`ByteArray::new`] instance
211    #[inline]
212    pub fn len(&self) -> usize {
213        assert!(self.data.is_some());
214        self.data.as_ref().unwrap().len()
215    }
216
217    /// Checks if the underlying buffer is empty.
218    ///
219    /// # Panics
220    ///
221    /// Panics if no data has been set, see [`Self::len`]
222    #[inline]
223    pub fn is_empty(&self) -> bool {
224        self.len() == 0
225    }
226
227    /// Returns slice of data.
228    ///
229    /// # Panics
230    ///
231    /// Panics if no data has been set
232    #[inline]
233    pub fn data(&self) -> &[u8] {
234        self.data
235            .as_ref()
236            .expect("set_data should have been called")
237            .as_ref()
238    }
239
240    /// Set data from another byte buffer.
241    #[inline]
242    pub fn set_data(&mut self, data: Bytes) {
243        self.data = Some(data);
244    }
245
246    /// Returns `ByteArray` instance with slice of values for a data.
247    ///
248    /// # Panics
249    ///
250    /// Panics if no data has been set, or if `start + len` is out of bounds
251    #[inline]
252    pub fn slice(&self, start: usize, len: usize) -> Self {
253        Self::from(
254            self.data
255                .as_ref()
256                .expect("set_data should have been called")
257                .slice(start..start + len),
258        )
259    }
260
261    /// Try to convert the byte array to a utf8 slice
262    pub fn as_utf8(&self) -> Result<&str> {
263        let bytes = self
264            .data
265            .as_ref()
266            .map(|ptr| ptr.as_ref())
267            .ok_or_else(|| general_err!("Can't convert empty byte array to utf8"))?;
268        from_utf8(bytes).map_err(|e| e.into())
269    }
270}
271
272impl From<Vec<u8>> for ByteArray {
273    fn from(buf: Vec<u8>) -> ByteArray {
274        Self {
275            data: Some(buf.into()),
276        }
277    }
278}
279
280impl<'a> From<&'a [u8]> for ByteArray {
281    fn from(b: &'a [u8]) -> ByteArray {
282        let mut v = Vec::new();
283        v.extend_from_slice(b);
284        Self {
285            data: Some(v.into()),
286        }
287    }
288}
289
290impl<'a> From<&'a str> for ByteArray {
291    fn from(s: &'a str) -> ByteArray {
292        let mut v = Vec::new();
293        v.extend_from_slice(s.as_bytes());
294        Self {
295            data: Some(v.into()),
296        }
297    }
298}
299
300impl From<Bytes> for ByteArray {
301    fn from(value: Bytes) -> Self {
302        Self { data: Some(value) }
303    }
304}
305
306impl From<f16> for ByteArray {
307    fn from(value: f16) -> Self {
308        Self::from(value.to_le_bytes().as_slice())
309    }
310}
311
312impl PartialEq for ByteArray {
313    fn eq(&self, other: &ByteArray) -> bool {
314        match (&self.data, &other.data) {
315            (Some(d1), Some(d2)) => d1.as_ref() == d2.as_ref(),
316            (None, None) => true,
317            _ => false,
318        }
319    }
320}
321
322impl fmt::Display for ByteArray {
323    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
324        write!(f, "{:?}", self.data())
325    }
326}
327
328/// Wrapper type for performance reasons, this represents `FIXED_LEN_BYTE_ARRAY` but in all other
329/// considerations behaves the same as `ByteArray`
330///
331/// # Performance notes:
332/// This type is a little unfortunate, without it the compiler generates code that takes quite a
333/// big hit on the CPU pipeline. Essentially the previous version stalls awaiting the result of
334/// `T::get_physical_type() == Type::FIXED_LEN_BYTE_ARRAY`.
335///
336/// Its debatable if this is wanted, it is out of spec for what parquet documents as its base
337/// types, although there are code paths in the Rust (and potentially the C++) versions that
338/// warrant this.
339///
340/// With this wrapper type the compiler generates more targeted code paths matching the higher
341/// level logical types, removing the data-hazard from all decoding and encoding paths.
342#[repr(transparent)]
343#[derive(Clone, Debug, Default)]
344pub struct FixedLenByteArray(ByteArray);
345
346impl PartialEq for FixedLenByteArray {
347    fn eq(&self, other: &FixedLenByteArray) -> bool {
348        self.0.eq(&other.0)
349    }
350}
351
352impl PartialEq<ByteArray> for FixedLenByteArray {
353    fn eq(&self, other: &ByteArray) -> bool {
354        self.0.eq(other)
355    }
356}
357
358impl PartialEq<FixedLenByteArray> for ByteArray {
359    fn eq(&self, other: &FixedLenByteArray) -> bool {
360        self.eq(&other.0)
361    }
362}
363
364impl fmt::Display for FixedLenByteArray {
365    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
366        self.0.fmt(f)
367    }
368}
369
370impl PartialOrd for FixedLenByteArray {
371    fn partial_cmp(&self, other: &FixedLenByteArray) -> Option<Ordering> {
372        self.0.partial_cmp(&other.0)
373    }
374}
375
376impl PartialOrd<FixedLenByteArray> for ByteArray {
377    fn partial_cmp(&self, other: &FixedLenByteArray) -> Option<Ordering> {
378        self.partial_cmp(&other.0)
379    }
380}
381
382impl PartialOrd<ByteArray> for FixedLenByteArray {
383    fn partial_cmp(&self, other: &ByteArray) -> Option<Ordering> {
384        self.0.partial_cmp(other)
385    }
386}
387
388impl Deref for FixedLenByteArray {
389    type Target = ByteArray;
390
391    fn deref(&self) -> &Self::Target {
392        &self.0
393    }
394}
395
396impl DerefMut for FixedLenByteArray {
397    fn deref_mut(&mut self) -> &mut Self::Target {
398        &mut self.0
399    }
400}
401
402impl From<ByteArray> for FixedLenByteArray {
403    fn from(other: ByteArray) -> Self {
404        Self(other)
405    }
406}
407
408impl From<Vec<u8>> for FixedLenByteArray {
409    fn from(buf: Vec<u8>) -> FixedLenByteArray {
410        FixedLenByteArray(ByteArray::from(buf))
411    }
412}
413
414impl From<FixedLenByteArray> for ByteArray {
415    fn from(other: FixedLenByteArray) -> Self {
416        other.0
417    }
418}
419
420/// Rust representation for Decimal values.
421///
422/// This is not a representation of Parquet physical type, but rather a wrapper for
423/// DECIMAL logical type, and serves as container for raw parts of decimal values:
424/// unscaled value in bytes, precision and scale.
425#[derive(Clone, Debug)]
426pub enum Decimal {
427    /// Decimal backed by `i32`.
428    Int32 {
429        /// The underlying value
430        value: [u8; 4],
431        /// The total number of digits in the number
432        precision: i32,
433        /// The number of digits to the right of the decimal point
434        scale: i32,
435    },
436    /// Decimal backed by `i64`.
437    Int64 {
438        /// The underlying value
439        value: [u8; 8],
440        /// The total number of digits in the number
441        precision: i32,
442        /// The number of digits to the right of the decimal point
443        scale: i32,
444    },
445    /// Decimal backed by byte array.
446    Bytes {
447        /// The underlying value
448        value: ByteArray,
449        /// The total number of digits in the number
450        precision: i32,
451        /// The number of digits to the right of the decimal point
452        scale: i32,
453    },
454}
455
456impl Decimal {
457    /// Creates new decimal value from `i32`.
458    pub fn from_i32(value: i32, precision: i32, scale: i32) -> Self {
459        let bytes = value.to_be_bytes();
460        Decimal::Int32 {
461            value: bytes,
462            precision,
463            scale,
464        }
465    }
466
467    /// Creates new decimal value from `i64`.
468    pub fn from_i64(value: i64, precision: i32, scale: i32) -> Self {
469        let bytes = value.to_be_bytes();
470        Decimal::Int64 {
471            value: bytes,
472            precision,
473            scale,
474        }
475    }
476
477    /// Creates new decimal value from `ByteArray`.
478    pub fn from_bytes(value: ByteArray, precision: i32, scale: i32) -> Self {
479        Decimal::Bytes {
480            value,
481            precision,
482            scale,
483        }
484    }
485
486    /// Returns bytes of unscaled value.
487    pub fn data(&self) -> &[u8] {
488        match *self {
489            Decimal::Int32 { ref value, .. } => value,
490            Decimal::Int64 { ref value, .. } => value,
491            Decimal::Bytes { ref value, .. } => value.data(),
492        }
493    }
494
495    /// Returns decimal precision.
496    pub fn precision(&self) -> i32 {
497        match *self {
498            Decimal::Int32 { precision, .. } => precision,
499            Decimal::Int64 { precision, .. } => precision,
500            Decimal::Bytes { precision, .. } => precision,
501        }
502    }
503
504    /// Returns decimal scale.
505    pub fn scale(&self) -> i32 {
506        match *self {
507            Decimal::Int32 { scale, .. } => scale,
508            Decimal::Int64 { scale, .. } => scale,
509            Decimal::Bytes { scale, .. } => scale,
510        }
511    }
512}
513
514impl Default for Decimal {
515    fn default() -> Self {
516        Self::from_i32(0, 0, 0)
517    }
518}
519
520impl PartialEq for Decimal {
521    fn eq(&self, other: &Decimal) -> bool {
522        self.precision() == other.precision()
523            && self.scale() == other.scale()
524            && self.data() == other.data()
525    }
526}
527
528/// Converts an instance of data type to a slice of bytes as `u8`.
529pub trait AsBytes {
530    /// Returns slice of bytes for this data type.
531    fn as_bytes(&self) -> &[u8];
532}
533
534/// Converts an slice of a data type to a slice of bytes.
535pub trait SliceAsBytes: Sized {
536    /// Returns slice of bytes for a slice of this data type.
537    fn slice_as_bytes(self_: &[Self]) -> &[u8];
538    /// Return the internal representation as a mutable slice
539    ///
540    /// # Safety
541    /// If modified you are _required_ to ensure the internal representation
542    /// is valid and correct for the actual raw data
543    unsafe fn slice_as_bytes_mut(self_: &mut [Self]) -> &mut [u8];
544}
545
546impl AsBytes for [u8] {
547    fn as_bytes(&self) -> &[u8] {
548        self
549    }
550}
551
552macro_rules! gen_as_bytes {
553    ($source_ty:ident) => {
554        impl AsBytes for $source_ty {
555            fn as_bytes(&self) -> &[u8] {
556                // SAFETY: macro is only used with primitive types that have no padding, so the
557                // resulting slice always refers to initialized memory.
558                unsafe {
559                    std::slice::from_raw_parts(
560                        std::ptr::from_ref::<$source_ty>(self).cast::<u8>(),
561                        std::mem::size_of::<$source_ty>(),
562                    )
563                }
564            }
565        }
566
567        impl SliceAsBytes for $source_ty {
568            #[inline]
569            fn slice_as_bytes(self_: &[Self]) -> &[u8] {
570                // SAFETY: macro is only used with primitive types that have no padding, so the
571                // resulting slice always refers to initialized memory.
572                unsafe {
573                    std::slice::from_raw_parts(
574                        self_.as_ptr().cast::<u8>(),
575                        std::mem::size_of_val(self_),
576                    )
577                }
578            }
579
580            #[inline]
581            unsafe fn slice_as_bytes_mut(self_: &mut [Self]) -> &mut [u8] {
582                // SAFETY: macro is only used with primitive types that have no padding, so the
583                // resulting slice always refers to initialized memory. Moreover, self has no
584                // invalid bit patterns, so all writes to the resulting slice will be valid.
585                unsafe {
586                    std::slice::from_raw_parts_mut(
587                        self_.as_mut_ptr().cast::<u8>(),
588                        std::mem::size_of_val(self_),
589                    )
590                }
591            }
592        }
593    };
594}
595
596gen_as_bytes!(i8);
597gen_as_bytes!(i16);
598gen_as_bytes!(i32);
599gen_as_bytes!(i64);
600gen_as_bytes!(u8);
601gen_as_bytes!(u16);
602gen_as_bytes!(u32);
603gen_as_bytes!(u64);
604gen_as_bytes!(f32);
605gen_as_bytes!(f64);
606
607macro_rules! unimplemented_slice_as_bytes {
608    ($ty: ty) => {
609        impl SliceAsBytes for $ty {
610            fn slice_as_bytes(_self: &[Self]) -> &[u8] {
611                unimplemented!()
612            }
613
614            unsafe fn slice_as_bytes_mut(_self: &mut [Self]) -> &mut [u8] {
615                unimplemented!()
616            }
617        }
618    };
619}
620
621// TODO - Can Int96 and bool be implemented in these terms?
622unimplemented_slice_as_bytes!(Int96);
623unimplemented_slice_as_bytes!(bool);
624unimplemented_slice_as_bytes!(ByteArray);
625unimplemented_slice_as_bytes!(FixedLenByteArray);
626
627impl AsBytes for bool {
628    fn as_bytes(&self) -> &[u8] {
629        // SAFETY: a bool is guaranteed to be either 0x00 or 0x01 in memory, so the memory is
630        // valid.
631        unsafe { std::slice::from_raw_parts(std::ptr::from_ref::<bool>(self).cast::<u8>(), 1) }
632    }
633}
634
635impl AsBytes for Int96 {
636    fn as_bytes(&self) -> &[u8] {
637        // SAFETY: Int96::data is a &[u32; 3].
638        unsafe {
639            std::slice::from_raw_parts(std::ptr::from_ref::<[u32]>(self.data()).cast::<u8>(), 12)
640        }
641    }
642}
643
644impl AsBytes for ByteArray {
645    fn as_bytes(&self) -> &[u8] {
646        self.data()
647    }
648}
649
650impl AsBytes for FixedLenByteArray {
651    fn as_bytes(&self) -> &[u8] {
652        self.data()
653    }
654}
655
656impl AsBytes for Decimal {
657    fn as_bytes(&self) -> &[u8] {
658        self.data()
659    }
660}
661
662impl AsBytes for Vec<u8> {
663    fn as_bytes(&self) -> &[u8] {
664        self.as_slice()
665    }
666}
667
668impl AsBytes for &str {
669    fn as_bytes(&self) -> &[u8] {
670        (self as &str).as_bytes()
671    }
672}
673
674impl AsBytes for str {
675    fn as_bytes(&self) -> &[u8] {
676        (self as &str).as_bytes()
677    }
678}
679
680pub(crate) mod private {
681    use bytes::Bytes;
682
683    use crate::encodings::decoding::PlainDecoderDetails;
684    use crate::util::bit_util::{BitReader, BitWriter, read_num_bytes};
685
686    use super::{ParquetError, Result, SliceAsBytes};
687    use crate::basic::Type;
688    use crate::column::writer::min_max::{
689        fallback_min_max, min_max_f32, min_max_f64, min_max_i32, min_max_i64,
690    };
691    use crate::file::metadata::HeapSize;
692    use crate::schema::types::BasicTypeInfo;
693
694    /// Sealed trait to start to remove specialisation from implementations
695    ///
696    /// This is done to force the associated value type to be unimplementable outside of this
697    /// crate, and thus hint to the type system (and end user) traits are public for the contract
698    /// and not for extension.
699    pub trait ParquetValueType:
700        PartialEq
701        + std::fmt::Debug
702        + std::fmt::Display
703        + Default
704        + Clone
705        + super::AsBytes
706        + super::FromBytes
707        + SliceAsBytes
708        + PartialOrd
709        + Send
710        + HeapSize
711        + crate::encodings::decoding::private::GetDecoder
712        + crate::encodings::encoding::private::GetEncoder
713        + crate::file::statistics::private::MakeStatistics
714    {
715        const PHYSICAL_TYPE: Type;
716
717        /// Encode the value directly from a higher level encoder
718        fn encode<W: std::io::Write>(
719            values: &[Self],
720            writer: &mut W,
721            bit_writer: &mut BitWriter,
722        ) -> Result<()>;
723
724        /// Establish the data that will be decoded in a buffer
725        fn set_data(decoder: &mut PlainDecoderDetails, data: Bytes, num_values: usize);
726
727        /// Decode the value from a given buffer for a higher level decoder
728        fn decode(buffer: &mut [Self], decoder: &mut PlainDecoderDetails) -> Result<usize>;
729
730        fn skip(decoder: &mut PlainDecoderDetails, num_values: usize) -> Result<usize>;
731
732        /// Return the encoded size for a type
733        fn dict_encoding_size(&self) -> (usize, usize) {
734            (std::mem::size_of::<Self>(), 1)
735        }
736
737        /// Return the number of variable length bytes in a given slice of data
738        ///
739        /// Returns the sum of lengths for BYTE_ARRAY data, and None for all other data types
740        fn variable_length_bytes(_: &[Self]) -> Option<i64> {
741            None
742        }
743
744        /// Return the value as i64 if possible
745        ///
746        /// This is essentially the same as `std::convert::TryInto<i64>` but can't be
747        /// implemented for `f32` and `f64`, types that would fail orphan rules
748        fn as_i64(&self) -> Result<i64> {
749            Err(general_err!("Type cannot be converted to i64"))
750        }
751
752        /// Return the value as u64 if possible
753        ///
754        /// This is essentially the same as `std::convert::TryInto<u64>` but can't be
755        /// implemented for `f32` and `f64`, types that would fail orphan rules
756        fn as_u64(&self) -> Result<u64> {
757            self.as_i64()
758                .map_err(|_| general_err!("Type cannot be converted to u64"))
759                .map(|x| x as u64)
760        }
761
762        /// Return the min, max and NaN count of `values` for column statistics,
763        /// or `None` if `values` is empty
764        fn min_max(basic_type_info: &BasicTypeInfo, values: &[Self]) -> Option<(Self, Self, u64)> {
765            fallback_min_max(basic_type_info, values.iter())
766        }
767
768        /// Return the value as an Any to allow for downcasts without transmutation
769        fn as_any(&self) -> &dyn std::any::Any;
770
771        /// Return the value as an mutable Any to allow for downcasts without transmutation
772        fn as_mut_any(&mut self) -> &mut dyn std::any::Any;
773
774        /// Sets the value of this object from the provided [`Bytes`]
775        ///
776        /// Only implemented for `ByteArray` and `FixedLenByteArray`. Will panic for other types.
777        fn set_from_bytes(&mut self, _data: Bytes) {
778            unimplemented!();
779        }
780    }
781
782    impl ParquetValueType for bool {
783        const PHYSICAL_TYPE: Type = Type::BOOLEAN;
784
785        #[inline]
786        fn encode<W: std::io::Write>(
787            values: &[Self],
788            _: &mut W,
789            bit_writer: &mut BitWriter,
790        ) -> Result<()> {
791            bit_writer.put_batch(values, 1);
792            Ok(())
793        }
794
795        #[inline]
796        fn set_data(decoder: &mut PlainDecoderDetails, data: Bytes, num_values: usize) {
797            decoder.bit_reader.replace(BitReader::new(data));
798            decoder.num_values = num_values;
799        }
800
801        #[inline]
802        fn decode(buffer: &mut [Self], decoder: &mut PlainDecoderDetails) -> Result<usize> {
803            let bit_reader = decoder.bit_reader.as_mut().unwrap();
804            let num_values = std::cmp::min(buffer.len(), decoder.num_values);
805            let values_read = bit_reader.get_batch(&mut buffer[..num_values], 1);
806            decoder.num_values -= values_read;
807            Ok(values_read)
808        }
809
810        fn skip(decoder: &mut PlainDecoderDetails, num_values: usize) -> Result<usize> {
811            let bit_reader = decoder.bit_reader.as_mut().unwrap();
812            let num_values = std::cmp::min(num_values, decoder.num_values);
813            let values_read = bit_reader.skip(num_values, 1);
814            decoder.num_values -= values_read;
815            Ok(values_read)
816        }
817
818        #[inline]
819        fn as_i64(&self) -> Result<i64> {
820            Ok(*self as i64)
821        }
822
823        #[inline]
824        fn as_any(&self) -> &dyn std::any::Any {
825            self
826        }
827
828        #[inline]
829        fn as_mut_any(&mut self) -> &mut dyn std::any::Any {
830            self
831        }
832    }
833
834    macro_rules! impl_from_raw {
835        ($ty: ty, $physical_ty: expr, $self: ident => $as_i64: block, min_max: ($info: ident, $values: ident) => $min_max: block) => {
836            impl ParquetValueType for $ty {
837                const PHYSICAL_TYPE: Type = $physical_ty;
838
839                #[inline]
840                fn encode<W: std::io::Write>(values: &[Self], writer: &mut W, _: &mut BitWriter) -> Result<()> {
841                    // SAFETY: Self is one of i32, i64, f32, f64, which have no padding.
842                    let raw = unsafe {
843                        std::slice::from_raw_parts(
844                            values.as_ptr().cast::<u8>(),
845                            std::mem::size_of_val(values),
846                        )
847                    };
848                    writer.write_all(raw)?;
849
850                    Ok(())
851                }
852
853                #[inline]
854                fn set_data(decoder: &mut PlainDecoderDetails, data: Bytes, num_values: usize) {
855                    decoder.data.replace(data);
856                    decoder.start = 0;
857                    decoder.num_values = num_values;
858                }
859
860                #[inline]
861                fn decode(buffer: &mut [Self], decoder: &mut PlainDecoderDetails) -> Result<usize> {
862                    let data = decoder.data.as_ref().expect("set_data should have been called");
863                    let num_values = std::cmp::min(buffer.len(), decoder.num_values);
864                    let bytes_left = data.len() - decoder.start;
865                    let bytes_to_decode = std::mem::size_of::<Self>() * num_values;
866
867                    if bytes_left < bytes_to_decode {
868                        return Err(eof_err!("Not enough bytes to decode"));
869                    }
870
871                    {
872                        // SAFETY: Self has no invalid bit patterns, so writing to the slice
873                        // obtained with slice_as_bytes_mut is always safe.
874                        let raw_buffer = &mut unsafe { Self::slice_as_bytes_mut(buffer) }[..bytes_to_decode];
875                        raw_buffer.copy_from_slice(data.slice(
876                            decoder.start..decoder.start + bytes_to_decode
877                        ).as_ref());
878                    };
879                    decoder.start += bytes_to_decode;
880                    decoder.num_values -= num_values;
881
882                    Ok(num_values)
883                }
884
885                #[inline]
886                fn skip(decoder: &mut PlainDecoderDetails, num_values: usize) -> Result<usize> {
887                    let data = decoder.data.as_ref().expect("set_data should have been called");
888                    let num_values = num_values.min(decoder.num_values);
889                    let bytes_left = data.len() - decoder.start;
890                    let bytes_to_skip = std::mem::size_of::<Self>() * num_values;
891
892                    if bytes_left < bytes_to_skip {
893                        return Err(eof_err!("Not enough bytes to skip"));
894                    }
895
896                    decoder.start += bytes_to_skip;
897                    decoder.num_values -= num_values;
898
899                    Ok(num_values)
900                }
901
902                #[inline]
903                fn as_i64(&$self) -> Result<i64> {
904                    $as_i64
905                }
906
907                #[inline]
908                fn min_max($info: &BasicTypeInfo, $values: &[Self]) -> Option<(Self, Self, u64)> {
909                    $min_max
910                }
911
912                #[inline]
913                fn as_any(&self) -> &dyn std::any::Any {
914                    self
915                }
916
917                #[inline]
918                fn as_mut_any(&mut self) -> &mut dyn std::any::Any {
919                    self
920                }
921            }
922        }
923    }
924
925    impl_from_raw!(
926        i32, Type::INT32, self => { Ok(*self as i64) },
927        min_max: (info, values) => { min_max_i32(info, values).map(|(min, max)| (min, max, 0)) }
928    );
929    impl_from_raw!(
930        i64, Type::INT64, self => { Ok(*self) },
931        min_max: (info, values) => { min_max_i64(info, values).map(|(min, max)| (min, max, 0)) }
932    );
933    // The float kernels return `None` for all NaN input, which the scalar path handles
934    impl_from_raw!(
935        f32, Type::FLOAT, self => { Err(general_err!("Type cannot be converted to i64")) },
936        min_max: (info, values) => { min_max_f32(values).or_else(|| fallback_min_max(info, values.iter())) }
937    );
938    impl_from_raw!(
939        f64, Type::DOUBLE, self => { Err(general_err!("Type cannot be converted to i64")) },
940        min_max: (info, values) => { min_max_f64(values).or_else(|| fallback_min_max(info, values.iter())) }
941    );
942
943    impl ParquetValueType for super::Int96 {
944        const PHYSICAL_TYPE: Type = Type::INT96;
945
946        #[inline]
947        fn encode<W: std::io::Write>(
948            values: &[Self],
949            writer: &mut W,
950            _: &mut BitWriter,
951        ) -> Result<()> {
952            for value in values {
953                let raw = SliceAsBytes::slice_as_bytes(value.data());
954                writer.write_all(raw)?;
955            }
956            Ok(())
957        }
958
959        #[inline]
960        fn set_data(decoder: &mut PlainDecoderDetails, data: Bytes, num_values: usize) {
961            decoder.data.replace(data);
962            decoder.start = 0;
963            decoder.num_values = num_values;
964        }
965
966        #[inline]
967        fn decode(buffer: &mut [Self], decoder: &mut PlainDecoderDetails) -> Result<usize> {
968            // TODO - Remove the duplication between this and the general slice method
969            let data = decoder
970                .data
971                .as_ref()
972                .expect("set_data should have been called");
973            let num_values = std::cmp::min(buffer.len(), decoder.num_values);
974            let bytes_left = data.len() - decoder.start;
975            let bytes_to_decode = 12 * num_values;
976
977            if bytes_left < bytes_to_decode {
978                return Err(eof_err!("Not enough bytes to decode"));
979            }
980
981            let data_range = data.slice(decoder.start..decoder.start + bytes_to_decode);
982            let bytes: &[u8] = &data_range;
983            decoder.start += bytes_to_decode;
984
985            let mut pos = 0; // position in byte array
986            for item in buffer.iter_mut().take(num_values) {
987                let elem0 = u32::from_le_bytes(bytes[pos..pos + 4].try_into().unwrap());
988                let elem1 = u32::from_le_bytes(bytes[pos + 4..pos + 8].try_into().unwrap());
989                let elem2 = u32::from_le_bytes(bytes[pos + 8..pos + 12].try_into().unwrap());
990
991                item.set_data(elem0, elem1, elem2);
992                pos += 12;
993            }
994            decoder.num_values -= num_values;
995
996            Ok(num_values)
997        }
998
999        fn skip(decoder: &mut PlainDecoderDetails, num_values: usize) -> Result<usize> {
1000            let data = decoder
1001                .data
1002                .as_ref()
1003                .expect("set_data should have been called");
1004            let num_values = std::cmp::min(num_values, decoder.num_values);
1005            let bytes_left = data.len() - decoder.start;
1006            let bytes_to_skip = 12 * num_values;
1007
1008            if bytes_left < bytes_to_skip {
1009                return Err(eof_err!("Not enough bytes to skip"));
1010            }
1011            decoder.start += bytes_to_skip;
1012            decoder.num_values -= num_values;
1013
1014            Ok(num_values)
1015        }
1016
1017        #[inline]
1018        fn as_any(&self) -> &dyn std::any::Any {
1019            self
1020        }
1021
1022        #[inline]
1023        fn as_mut_any(&mut self) -> &mut dyn std::any::Any {
1024            self
1025        }
1026    }
1027
1028    impl HeapSize for super::Int96 {
1029        fn heap_size(&self) -> usize {
1030            0 // no heap allocations
1031        }
1032    }
1033
1034    impl ParquetValueType for super::ByteArray {
1035        const PHYSICAL_TYPE: Type = Type::BYTE_ARRAY;
1036
1037        #[inline]
1038        fn encode<W: std::io::Write>(
1039            values: &[Self],
1040            writer: &mut W,
1041            _: &mut BitWriter,
1042        ) -> Result<()> {
1043            for value in values {
1044                let len: u32 = value.len().try_into().unwrap();
1045                writer.write_all(&len.to_ne_bytes())?;
1046                let raw = value.data();
1047                writer.write_all(raw)?;
1048            }
1049            Ok(())
1050        }
1051
1052        #[inline]
1053        fn set_data(decoder: &mut PlainDecoderDetails, data: Bytes, num_values: usize) {
1054            decoder.data.replace(data);
1055            decoder.start = 0;
1056            decoder.num_values = num_values;
1057        }
1058
1059        #[inline]
1060        fn decode(buffer: &mut [Self], decoder: &mut PlainDecoderDetails) -> Result<usize> {
1061            let data = decoder
1062                .data
1063                .as_mut()
1064                .expect("set_data should have been called");
1065            let num_values = std::cmp::min(buffer.len(), decoder.num_values);
1066            for val_array in buffer.iter_mut().take(num_values) {
1067                let len: usize =
1068                    read_num_bytes::<u32>(4, data.slice(decoder.start..).as_ref()) as usize;
1069                decoder.start += std::mem::size_of::<u32>();
1070
1071                if data.len() < decoder.start + len {
1072                    return Err(eof_err!("Not enough bytes to decode"));
1073                }
1074
1075                val_array.set_data(data.slice(decoder.start..decoder.start + len));
1076                decoder.start += len;
1077            }
1078            decoder.num_values -= num_values;
1079
1080            Ok(num_values)
1081        }
1082
1083        fn variable_length_bytes(values: &[Self]) -> Option<i64> {
1084            Some(values.iter().map(|x| x.len() as i64).sum())
1085        }
1086
1087        fn skip(decoder: &mut PlainDecoderDetails, num_values: usize) -> Result<usize> {
1088            let data = decoder
1089                .data
1090                .as_mut()
1091                .expect("set_data should have been called");
1092            let num_values = num_values.min(decoder.num_values);
1093
1094            for _ in 0..num_values {
1095                let len: usize =
1096                    read_num_bytes::<u32>(4, data.slice(decoder.start..).as_ref()) as usize;
1097                decoder.start += std::mem::size_of::<u32>() + len;
1098            }
1099            decoder.num_values -= num_values;
1100
1101            Ok(num_values)
1102        }
1103
1104        #[inline]
1105        fn dict_encoding_size(&self) -> (usize, usize) {
1106            (std::mem::size_of::<u32>(), self.len())
1107        }
1108
1109        #[inline]
1110        fn as_any(&self) -> &dyn std::any::Any {
1111            self
1112        }
1113
1114        #[inline]
1115        fn as_mut_any(&mut self) -> &mut dyn std::any::Any {
1116            self
1117        }
1118
1119        #[inline]
1120        fn set_from_bytes(&mut self, data: Bytes) {
1121            self.set_data(data);
1122        }
1123    }
1124
1125    impl HeapSize for super::ByteArray {
1126        fn heap_size(&self) -> usize {
1127            // note: this is an estimate, not exact, so just return the size
1128            // of the actual data used, don't try to handle the fact that it may
1129            // be shared.
1130            self.data.as_ref().map(|data| data.len()).unwrap_or(0)
1131        }
1132    }
1133
1134    impl ParquetValueType for super::FixedLenByteArray {
1135        const PHYSICAL_TYPE: Type = Type::FIXED_LEN_BYTE_ARRAY;
1136
1137        #[inline]
1138        fn encode<W: std::io::Write>(
1139            values: &[Self],
1140            writer: &mut W,
1141            _: &mut BitWriter,
1142        ) -> Result<()> {
1143            for value in values {
1144                let raw = value.data();
1145                writer.write_all(raw)?;
1146            }
1147            Ok(())
1148        }
1149
1150        #[inline]
1151        fn set_data(decoder: &mut PlainDecoderDetails, data: Bytes, num_values: usize) {
1152            decoder.data.replace(data);
1153            decoder.start = 0;
1154            decoder.num_values = num_values;
1155        }
1156
1157        #[inline]
1158        fn decode(buffer: &mut [Self], decoder: &mut PlainDecoderDetails) -> Result<usize> {
1159            assert!(decoder.type_length > 0);
1160
1161            let data = decoder
1162                .data
1163                .as_mut()
1164                .expect("set_data should have been called");
1165            let num_values = std::cmp::min(buffer.len(), decoder.num_values);
1166
1167            for item in buffer.iter_mut().take(num_values) {
1168                let len = decoder.type_length as usize;
1169
1170                if data.len() < decoder.start + len {
1171                    return Err(eof_err!("Not enough bytes to decode"));
1172                }
1173
1174                item.set_data(data.slice(decoder.start..decoder.start + len));
1175                decoder.start += len;
1176            }
1177            decoder.num_values -= num_values;
1178
1179            Ok(num_values)
1180        }
1181
1182        fn skip(decoder: &mut PlainDecoderDetails, num_values: usize) -> Result<usize> {
1183            assert!(decoder.type_length > 0);
1184
1185            let data = decoder
1186                .data
1187                .as_mut()
1188                .expect("set_data should have been called");
1189            let num_values = std::cmp::min(num_values, decoder.num_values);
1190            for _ in 0..num_values {
1191                let len = decoder.type_length as usize;
1192
1193                if data.len() < decoder.start + len {
1194                    return Err(eof_err!("Not enough bytes to skip"));
1195                }
1196
1197                decoder.start += len;
1198            }
1199            decoder.num_values -= num_values;
1200
1201            Ok(num_values)
1202        }
1203
1204        #[inline]
1205        fn dict_encoding_size(&self) -> (usize, usize) {
1206            (std::mem::size_of::<u32>(), self.len())
1207        }
1208
1209        #[inline]
1210        fn as_any(&self) -> &dyn std::any::Any {
1211            self
1212        }
1213
1214        #[inline]
1215        fn as_mut_any(&mut self) -> &mut dyn std::any::Any {
1216            self
1217        }
1218
1219        #[inline]
1220        fn set_from_bytes(&mut self, data: Bytes) {
1221            self.set_data(data);
1222        }
1223    }
1224
1225    impl HeapSize for super::FixedLenByteArray {
1226        fn heap_size(&self) -> usize {
1227            self.0.heap_size()
1228        }
1229    }
1230}
1231
1232/// Contains the Parquet physical type information as well as the Rust primitive type
1233/// presentation.
1234pub trait DataType: 'static + Send {
1235    /// The physical type of the Parquet data type.
1236    type T: private::ParquetValueType;
1237
1238    /// Returns Parquet physical type.
1239    fn get_physical_type() -> Type {
1240        <Self::T as private::ParquetValueType>::PHYSICAL_TYPE
1241    }
1242
1243    /// Returns size in bytes for Rust representation of the physical type.
1244    fn get_type_size() -> usize;
1245
1246    /// Returns the underlying [`ColumnReaderImpl`] for the given [`ColumnReader`].
1247    fn get_column_reader(column_writer: ColumnReader) -> Option<ColumnReaderImpl<Self>>
1248    where
1249        Self: Sized;
1250
1251    /// Returns the underlying [`ColumnWriterImpl`] for the given [`ColumnWriter`].
1252    fn get_column_writer(column_writer: ColumnWriter<'_>) -> Option<ColumnWriterImpl<'_, Self>>
1253    where
1254        Self: Sized;
1255
1256    /// Returns a reference to the underlying [`ColumnWriterImpl`] for the given [`ColumnWriter`].
1257    fn get_column_writer_ref<'a, 'b: 'a>(
1258        column_writer: &'b ColumnWriter<'a>,
1259    ) -> Option<&'b ColumnWriterImpl<'a, Self>>
1260    where
1261        Self: Sized;
1262
1263    /// Returns a mutable reference to the underlying [`ColumnWriterImpl`] for the given
1264    fn get_column_writer_mut<'a, 'b: 'a>(
1265        column_writer: &'a mut ColumnWriter<'b>,
1266    ) -> Option<&'a mut ColumnWriterImpl<'b, Self>>
1267    where
1268        Self: Sized;
1269}
1270
1271macro_rules! make_type {
1272    ($name:ident, $reader_ident: ident, $writer_ident: ident, $native_ty:ty, $size:expr) => {
1273        #[doc = concat!("Parquet physical type: ", stringify!($name))]
1274        #[derive(Clone)]
1275        pub struct $name {}
1276
1277        impl DataType for $name {
1278            type T = $native_ty;
1279
1280            fn get_type_size() -> usize {
1281                $size
1282            }
1283
1284            fn get_column_reader(column_reader: ColumnReader) -> Option<ColumnReaderImpl<Self>> {
1285                match column_reader {
1286                    ColumnReader::$reader_ident(w) => Some(w),
1287                    _ => None,
1288                }
1289            }
1290
1291            fn get_column_writer(
1292                column_writer: ColumnWriter<'_>,
1293            ) -> Option<ColumnWriterImpl<'_, Self>> {
1294                match column_writer {
1295                    ColumnWriter::$writer_ident(w) => Some(w),
1296                    _ => None,
1297                }
1298            }
1299
1300            fn get_column_writer_ref<'a, 'b: 'a>(
1301                column_writer: &'a ColumnWriter<'b>,
1302            ) -> Option<&'a ColumnWriterImpl<'b, Self>> {
1303                match column_writer {
1304                    ColumnWriter::$writer_ident(w) => Some(w),
1305                    _ => None,
1306                }
1307            }
1308
1309            fn get_column_writer_mut<'a, 'b: 'a>(
1310                column_writer: &'a mut ColumnWriter<'b>,
1311            ) -> Option<&'a mut ColumnWriterImpl<'b, Self>> {
1312                match column_writer {
1313                    ColumnWriter::$writer_ident(w) => Some(w),
1314                    _ => None,
1315                }
1316            }
1317        }
1318    };
1319}
1320
1321// Generate struct definitions for all physical types
1322
1323make_type!(BoolType, BoolColumnReader, BoolColumnWriter, bool, 1);
1324make_type!(Int32Type, Int32ColumnReader, Int32ColumnWriter, i32, 4);
1325make_type!(Int64Type, Int64ColumnReader, Int64ColumnWriter, i64, 8);
1326make_type!(
1327    Int96Type,
1328    Int96ColumnReader,
1329    Int96ColumnWriter,
1330    Int96,
1331    mem::size_of::<Int96>()
1332);
1333make_type!(FloatType, FloatColumnReader, FloatColumnWriter, f32, 4);
1334make_type!(DoubleType, DoubleColumnReader, DoubleColumnWriter, f64, 8);
1335make_type!(
1336    ByteArrayType,
1337    ByteArrayColumnReader,
1338    ByteArrayColumnWriter,
1339    ByteArray,
1340    mem::size_of::<ByteArray>()
1341);
1342make_type!(
1343    FixedLenByteArrayType,
1344    FixedLenByteArrayColumnReader,
1345    FixedLenByteArrayColumnWriter,
1346    FixedLenByteArray,
1347    mem::size_of::<FixedLenByteArray>()
1348);
1349
1350impl AsRef<[u8]> for ByteArray {
1351    fn as_ref(&self) -> &[u8] {
1352        self.as_bytes()
1353    }
1354}
1355
1356impl AsRef<[u8]> for FixedLenByteArray {
1357    fn as_ref(&self) -> &[u8] {
1358        self.as_bytes()
1359    }
1360}
1361
1362/// Macro to reduce repetition in making type assertions on the physical type against `T`
1363macro_rules! ensure_phys_ty {
1364    ($($ty:pat_param)|+ , $($arg:tt)*) => {
1365        match T::get_physical_type() {
1366            $($ty => (),)*
1367            _ => panic!($($arg)*),
1368        };
1369    }
1370}
1371
1372#[cfg(test)]
1373mod tests {
1374    use super::*;
1375
1376    #[test]
1377    fn test_as_bytes() {
1378        // Test Int96
1379        let i96 = Int96::from(vec![1, 2, 3]);
1380        assert_eq!(i96.as_bytes(), &[1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0]);
1381
1382        // Test ByteArray
1383        let byte_arr = ByteArray::from(vec![1, 2, 3]);
1384        assert_eq!(byte_arr.as_bytes(), &[1, 2, 3]);
1385
1386        // Test Decimal
1387        let decimal = Decimal::from_i32(123, 5, 2);
1388        assert_eq!(decimal.as_bytes(), &[0, 0, 0, 123]);
1389        let decimal = Decimal::from_i64(123, 5, 2);
1390        assert_eq!(decimal.as_bytes(), &[0, 0, 0, 0, 0, 0, 0, 123]);
1391        let decimal = Decimal::from_bytes(ByteArray::from(vec![1, 2, 3]), 5, 2);
1392        assert_eq!(decimal.as_bytes(), &[1, 2, 3]);
1393    }
1394
1395    #[test]
1396    fn test_int96_from() {
1397        assert_eq!(
1398            Int96::from(vec![1, 12345, 1234567890]).data(),
1399            &[1, 12345, 1234567890]
1400        );
1401    }
1402
1403    #[test]
1404    fn test_byte_array_from() {
1405        assert_eq!(ByteArray::from(b"ABC".to_vec()).data(), b"ABC");
1406        assert_eq!(ByteArray::from("ABC").data(), b"ABC");
1407        assert_eq!(
1408            ByteArray::from(Bytes::from(vec![1u8, 2u8, 3u8, 4u8, 5u8])).data(),
1409            &[1u8, 2u8, 3u8, 4u8, 5u8]
1410        );
1411        let buf = vec![6u8, 7u8, 8u8, 9u8, 10u8];
1412        assert_eq!(ByteArray::from(buf).data(), &[6u8, 7u8, 8u8, 9u8, 10u8]);
1413    }
1414
1415    #[test]
1416    fn test_decimal_partial_eq() {
1417        assert_eq!(Decimal::default(), Decimal::from_i32(0, 0, 0));
1418        assert_eq!(Decimal::from_i32(222, 5, 2), Decimal::from_i32(222, 5, 2));
1419        assert_eq!(
1420            Decimal::from_bytes(ByteArray::from(vec![0, 0, 0, 3]), 5, 2),
1421            Decimal::from_i32(3, 5, 2)
1422        );
1423
1424        assert_ne!(Decimal::from_i32(222, 5, 2), Decimal::from_i32(111, 5, 2));
1425        assert_ne!(Decimal::from_i32(222, 5, 2), Decimal::from_i32(222, 6, 2));
1426        assert_ne!(Decimal::from_i32(222, 5, 2), Decimal::from_i32(222, 5, 3));
1427
1428        assert_ne!(Decimal::from_i64(222, 5, 2), Decimal::from_i32(222, 5, 2));
1429    }
1430
1431    #[test]
1432    fn test_byte_array_ord() {
1433        let byte_arr1 = ByteArray::from(vec![1, 2, 3]);
1434        let byte_arr11 = ByteArray::from(vec![1, 2, 3]);
1435        let byte_arr2 = ByteArray::from(vec![3, 4]);
1436        let byte_arr3 = ByteArray::from(vec![1, 2, 4]);
1437        let byte_arr4 = ByteArray::from(vec![]);
1438        let byte_arr5 = ByteArray::from(vec![2, 2, 3]);
1439
1440        assert!(byte_arr1 < byte_arr2);
1441        assert!(byte_arr3 > byte_arr1);
1442        assert!(byte_arr1 > byte_arr4);
1443        assert_eq!(byte_arr1, byte_arr11);
1444        assert!(byte_arr5 > byte_arr1);
1445    }
1446}