typed_arrow/bridge/
decimals.rs

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