typed_arrow/bridge/
decimals.rs

1//! Decimal128/Decimal256 bindings.
2
3use arrow_array::{
4    Array, Decimal128Array, Decimal256Array,
5    builder::{Decimal128Builder, Decimal256Builder},
6};
7use arrow_buffer::i256;
8use arrow_schema::DataType;
9
10use super::ArrowBinding;
11#[cfg(feature = "views")]
12use super::ArrowBindingView;
13
14/// Fixed-precision decimal stored in 128 bits.
15/// The value is represented as a scaled integer of type `i128`.
16pub struct Decimal128<const P: u8, const S: i8>(i128);
17impl<const P: u8, const S: i8> Decimal128<P, S> {
18    /// Construct a new `Decimal128<P,S>` from a scaled integer value.
19    #[inline]
20    #[must_use]
21    pub fn new(value: i128) -> Self {
22        Self(value)
23    }
24    /// Return the scaled integer value.
25    #[inline]
26    #[must_use]
27    pub fn value(&self) -> i128 {
28        self.0
29    }
30    /// Consume and return the scaled integer value.
31    #[inline]
32    #[must_use]
33    pub fn into_value(self) -> i128 {
34        self.0
35    }
36}
37
38impl<const P: u8, const S: i8> ArrowBinding for Decimal128<P, S> {
39    type Builder = Decimal128Builder;
40    type Array = Decimal128Array;
41
42    fn data_type() -> DataType {
43        DataType::Decimal128(P, S)
44    }
45
46    fn new_builder(capacity: usize) -> Self::Builder {
47        Decimal128Builder::with_capacity(capacity).with_data_type(DataType::Decimal128(P, S))
48    }
49
50    fn append_value(b: &mut Self::Builder, v: &Self) {
51        b.append_value(v.0);
52    }
53
54    fn append_null(b: &mut Self::Builder) {
55        b.append_null();
56    }
57
58    fn finish(mut b: Self::Builder) -> Self::Array {
59        b.finish()
60    }
61}
62
63#[cfg(feature = "views")]
64impl<const P: u8, const S: i8> ArrowBindingView for Decimal128<P, S> {
65    type Array = Decimal128Array;
66    type View<'a> = Decimal128<P, S>;
67
68    fn get_view(
69        array: &Self::Array,
70        index: usize,
71    ) -> Result<Self::View<'_>, crate::schema::ViewAccessError> {
72        if index >= array.len() {
73            return Err(crate::schema::ViewAccessError::OutOfBounds {
74                index,
75                len: array.len(),
76                field_name: None,
77            });
78        }
79        if array.is_null(index) {
80            return Err(crate::schema::ViewAccessError::UnexpectedNull {
81                index,
82                field_name: None,
83            });
84        }
85        Ok(Decimal128::new(array.value(index)))
86    }
87}
88
89/// Fixed-precision decimal stored in 256 bits.
90/// The value is represented as a scaled integer of type `i256`.
91pub struct Decimal256<const P: u8, const S: i8>(i256);
92impl<const P: u8, const S: i8> Decimal256<P, S> {
93    /// Construct a new `Decimal256<P,S>` from a scaled integer value.
94    #[inline]
95    #[must_use]
96    pub fn new(value: i256) -> Self {
97        Self(value)
98    }
99    /// Return the scaled integer value.
100    #[inline]
101    #[must_use]
102    pub fn value(&self) -> i256 {
103        self.0
104    }
105    /// Consume and return the scaled integer value.
106    #[inline]
107    #[must_use]
108    pub fn into_value(self) -> i256 {
109        self.0
110    }
111}
112
113impl<const P: u8, const S: i8> ArrowBinding for Decimal256<P, S> {
114    type Builder = Decimal256Builder;
115    type Array = Decimal256Array;
116
117    fn data_type() -> DataType {
118        DataType::Decimal256(P, S)
119    }
120
121    fn new_builder(capacity: usize) -> Self::Builder {
122        Decimal256Builder::with_capacity(capacity).with_data_type(DataType::Decimal256(P, S))
123    }
124
125    fn append_value(b: &mut Self::Builder, v: &Self) {
126        b.append_value(v.0);
127    }
128
129    fn append_null(b: &mut Self::Builder) {
130        b.append_null();
131    }
132
133    fn finish(mut b: Self::Builder) -> Self::Array {
134        b.finish()
135    }
136}
137
138#[cfg(feature = "views")]
139impl<const P: u8, const S: i8> ArrowBindingView for Decimal256<P, S> {
140    type Array = Decimal256Array;
141    type View<'a> = Decimal256<P, S>;
142
143    fn get_view(
144        array: &Self::Array,
145        index: usize,
146    ) -> Result<Self::View<'_>, crate::schema::ViewAccessError> {
147        if index >= array.len() {
148            return Err(crate::schema::ViewAccessError::OutOfBounds {
149                index,
150                len: array.len(),
151                field_name: None,
152            });
153        }
154        if array.is_null(index) {
155            return Err(crate::schema::ViewAccessError::UnexpectedNull {
156                index,
157                field_name: None,
158            });
159        }
160        Ok(Decimal256::new(array.value(index)))
161    }
162}