arrow_json/reader/
decimal_array.rs1use std::marker::PhantomData;
19use std::sync::Arc;
20
21use arrow_array::ArrayRef;
22use arrow_array::builder::PrimitiveBuilder;
23use arrow_array::types::DecimalType;
24use arrow_cast::parse::parse_decimal;
25use arrow_schema::ArrowError;
26
27use crate::reader::tape::{Tape, TapeElement};
28use crate::reader::{ArrayDecoder, DecoderContext};
29
30pub struct DecimalArrayDecoder<D: DecimalType> {
31 precision: u8,
32 scale: i8,
33 ignore_type_conflicts: bool,
34 phantom: PhantomData<fn(D) -> D>,
36}
37
38impl<D: DecimalType> DecimalArrayDecoder<D> {
39 pub fn new(ctx: &DecoderContext, precision: u8, scale: i8) -> Self {
40 Self {
41 precision,
42 scale,
43 ignore_type_conflicts: ctx.ignore_type_conflicts(),
44 phantom: PhantomData,
45 }
46 }
47}
48
49impl<D> ArrayDecoder for DecimalArrayDecoder<D>
50where
51 D: DecimalType,
52{
53 fn decode(&mut self, tape: &Tape<'_>, pos: &[u32]) -> Result<ArrayRef, ArrowError> {
54 let mut builder = PrimitiveBuilder::<D>::with_capacity(pos.len());
55
56 #[allow(unused)] let mut anchor = String::default();
58 for p in pos {
59 let value = match tape.get(*p) {
60 TapeElement::Null => {
61 builder.append_null();
62 continue;
63 }
64 TapeElement::String(idx) | TapeElement::Number(idx) => tape.get_string(idx),
65 TapeElement::I64(high) => match tape.get(*p + 1) {
66 TapeElement::I32(low) => {
67 anchor = (((high as i64) << 32) | (low as u32) as i64).to_string();
68 anchor.as_str()
69 }
70 _ => unreachable!(),
71 },
72 TapeElement::I32(val) => {
73 anchor = val.to_string();
74 anchor.as_str()
75 }
76 TapeElement::F64(high) => match tape.get(*p + 1) {
77 TapeElement::F32(low) => {
78 anchor = f64::from_bits(((high as u64) << 32) | low as u64).to_string();
79 anchor.as_str()
80 }
81 _ => unreachable!(),
82 },
83 TapeElement::F32(val) => {
84 anchor = f32::from_bits(val).to_string();
85 anchor.as_str()
86 }
87 _ if self.ignore_type_conflicts => {
88 builder.append_null();
89 continue;
90 }
91 _ => return Err(tape.error(*p, "decimal")),
92 };
93
94 match parse_decimal::<D>(value, self.precision, self.scale) {
95 Ok(value) => builder.append_value(value),
96 Err(_) if self.ignore_type_conflicts => builder.append_null(),
97 Err(e) => return Err(e),
98 }
99 }
100
101 Ok(Arc::new(
102 builder
103 .finish()
104 .with_precision_and_scale(self.precision, self.scale)?,
105 ))
106 }
107}