Skip to content
14 changes: 12 additions & 2 deletions arrow-json/src/reader/boolean_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,20 @@ use arrow_array::builder::BooleanBuilder;
use arrow_data::ArrayData;
use arrow_schema::ArrowError;

use crate::reader::ArrayDecoder;
use crate::reader::tape::{Tape, TapeElement};
use crate::reader::{ArrayDecoder, DecoderContext};

#[derive(Default)]
pub struct BooleanArrayDecoder {}
pub struct BooleanArrayDecoder {
ignore_type_conflicts: bool,
}
impl BooleanArrayDecoder {
pub fn new(ctx: &DecoderContext) -> Self {
Self {
ignore_type_conflicts: ctx.ignore_type_conflicts(),
}
}
}

impl ArrayDecoder for BooleanArrayDecoder {
fn decode(&mut self, tape: &Tape<'_>, pos: &[u32]) -> Result<ArrayData, ArrowError> {
Expand All @@ -34,6 +43,7 @@ impl ArrayDecoder for BooleanArrayDecoder {
TapeElement::Null => builder.append_null(),
TapeElement::True => builder.append_value(true),
TapeElement::False => builder.append_value(false),
_ if self.ignore_type_conflicts => builder.append_null(),
_ => return Err(tape.error(*p, "boolean")),
}
}
Expand Down
54 changes: 29 additions & 25 deletions arrow-json/src/reader/decimal_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,23 @@ use arrow_cast::parse::parse_decimal;
use arrow_data::ArrayData;
use arrow_schema::ArrowError;

use crate::reader::ArrayDecoder;
use crate::reader::tape::{Tape, TapeElement};
use crate::reader::{ArrayDecoder, DecoderContext};

pub struct DecimalArrayDecoder<D: DecimalType> {
precision: u8,
scale: i8,
ignore_type_conflicts: bool,
// Invariant and Send
phantom: PhantomData<fn(D) -> D>,
}

impl<D: DecimalType> DecimalArrayDecoder<D> {
pub fn new(precision: u8, scale: i8) -> Self {
pub fn new(ctx: &DecoderContext, precision: u8, scale: i8) -> Self {
Self {
precision,
scale,
ignore_type_conflicts: ctx.ignore_type_conflicts(),
phantom: PhantomData,
}
}
Expand All @@ -51,46 +53,48 @@ where
fn decode(&mut self, tape: &Tape<'_>, pos: &[u32]) -> Result<ArrayData, ArrowError> {
let mut builder = PrimitiveBuilder::<D>::with_capacity(pos.len());

#[allow(unused)] // initial value overwritten without ever being read
let mut anchor = String::default();
for p in pos {
match tape.get(*p) {
TapeElement::Null => builder.append_null(),
TapeElement::String(idx) => {
let s = tape.get_string(idx);
let value = parse_decimal::<D>(s, self.precision, self.scale)?;
builder.append_value(value)
}
TapeElement::Number(idx) => {
let s = tape.get_string(idx);
let value = parse_decimal::<D>(s, self.precision, self.scale)?;
builder.append_value(value)
let value = match tape.get(*p) {
TapeElement::Null => {
builder.append_null();
continue;
}
TapeElement::String(idx) | TapeElement::Number(idx) => tape.get_string(idx),
TapeElement::I64(high) => match tape.get(*p + 1) {
TapeElement::I32(low) => {
let val = (((high as i64) << 32) | (low as u32) as i64).to_string();
let value = parse_decimal::<D>(&val, self.precision, self.scale)?;
builder.append_value(value)
anchor = (((high as i64) << 32) | (low as u32) as i64).to_string();
anchor.as_str()
}
_ => unreachable!(),
},
TapeElement::I32(val) => {
let s = val.to_string();
let value = parse_decimal::<D>(&s, self.precision, self.scale)?;
builder.append_value(value)
anchor = val.to_string();
anchor.as_str()
}
TapeElement::F64(high) => match tape.get(*p + 1) {
TapeElement::F32(low) => {
let val = f64::from_bits(((high as u64) << 32) | low as u64).to_string();
let value = parse_decimal::<D>(&val, self.precision, self.scale)?;
builder.append_value(value)
anchor = f64::from_bits(((high as u64) << 32) | low as u64).to_string();
anchor.as_str()
}
_ => unreachable!(),
},
TapeElement::F32(val) => {
let s = f32::from_bits(val).to_string();
let value = parse_decimal::<D>(&s, self.precision, self.scale)?;
builder.append_value(value)
anchor = f32::from_bits(val).to_string();
anchor.as_str()
}
_ if self.ignore_type_conflicts => {
builder.append_null();
continue;
}
_ => return Err(tape.error(*p, "decimal")),
};

match parse_decimal::<D>(value, self.precision, self.scale) {
Ok(value) => builder.append_value(value),
Err(_) if self.ignore_type_conflicts => builder.append_null(),
Err(e) => return Err(e),
}
}

Expand Down
6 changes: 6 additions & 0 deletions arrow-json/src/reader/list_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub struct ListArrayDecoder<O> {
data_type: DataType,
decoder: Box<dyn ArrayDecoder>,
phantom: PhantomData<O>,
ignore_type_conflicts: bool,
is_nullable: bool,
}

Expand All @@ -48,6 +49,7 @@ impl<O: OffsetSizeTrait> ListArrayDecoder<O> {
data_type: data_type.clone(),
decoder,
phantom: Default::default(),
ignore_type_conflicts: ctx.ignore_type_conflicts(),
is_nullable,
})
}
Expand All @@ -74,6 +76,10 @@ impl<O: OffsetSizeTrait> ArrayDecoder for ListArrayDecoder<O> {
nulls.append(false);
*p + 1
}
(_, Some(nulls)) if self.ignore_type_conflicts => {
nulls.append(false);
*p + 1
}
_ => return Err(tape.error(*p, "[")),
};

Expand Down
6 changes: 6 additions & 0 deletions arrow-json/src/reader/map_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub struct MapArrayDecoder {
data_type: DataType,
keys: Box<dyn ArrayDecoder>,
values: Box<dyn ArrayDecoder>,
ignore_type_conflicts: bool,
is_nullable: bool,
}

Expand Down Expand Up @@ -60,6 +61,7 @@ impl MapArrayDecoder {
data_type: data_type.clone(),
keys,
values,
ignore_type_conflicts: ctx.ignore_type_conflicts(),
is_nullable,
})
}
Expand Down Expand Up @@ -96,6 +98,10 @@ impl ArrayDecoder for MapArrayDecoder {
nulls.append(false);
p + 1
}
(_, Some(nulls)) if self.ignore_type_conflicts => {
nulls.append(false);
p + 1
}
_ => return Err(tape.error(p, "{")),
};

Expand Down
Loading
Loading