1use crate::codec::{
21 AvroDataType, AvroLiteral, Codec, EnumMapping, Promotion, ResolutionInfo, ResolvedField,
22 ResolvedRecord, ResolvedUnion, Tz,
23};
24use crate::errors::AvroError;
25use crate::reader::cursor::AvroCursor;
26use crate::schema::Nullability;
27#[cfg(feature = "small_decimals")]
28use arrow_array::builder::{Decimal32Builder, Decimal64Builder};
29use arrow_array::builder::{Decimal128Builder, Decimal256Builder, IntervalMonthDayNanoBuilder};
30use arrow_array::types::*;
31use arrow_array::*;
32use arrow_buffer::*;
33#[cfg(feature = "small_decimals")]
34use arrow_schema::{DECIMAL32_MAX_PRECISION, DECIMAL64_MAX_PRECISION};
35use arrow_schema::{
36 DECIMAL128_MAX_PRECISION, DECIMAL256_MAX_PRECISION, DataType, Field as ArrowField, FieldRef,
37 Fields, Schema as ArrowSchema, SchemaRef, UnionFields, UnionMode,
38};
39#[cfg(feature = "avro_custom_types")]
40use arrow_select::take::{TakeOptions, take};
41use strum_macros::AsRefStr;
42use uuid::Uuid;
43
44use std::cmp::Ordering;
45use std::mem;
46use std::sync::Arc;
47
48const DEFAULT_CAPACITY: usize = 1024;
49
50macro_rules! decode_decimal {
52 ($size:expr, $buf:expr, $builder:expr, $N:expr, $Int:ty) => {{
53 let bytes = read_decimal_bytes_be::<{ $N }>($buf, *$size)?;
54 $builder.append_value(<$Int>::from_be_bytes(bytes));
55 }};
56}
57
58macro_rules! flush_decimal {
60 ($builder:expr, $precision:expr, $scale:expr, $nulls:expr, $ArrayTy:ty) => {{
61 let (_, vals, _) = $builder.finish().into_parts();
62 let dec = <$ArrayTy>::try_new(vals, $nulls)?
63 .with_precision_and_scale(*$precision as u8, $scale.unwrap_or(0) as i8)?;
64 Arc::new(dec) as ArrayRef
65 }};
66}
67
68macro_rules! append_decimal_default {
71 ($lit:expr, $builder:expr, $N:literal, $Int:ty, $name:literal) => {{
72 match $lit {
73 AvroLiteral::Bytes(b) => {
74 let ext = sign_cast_to::<$N>(b)?;
75 let val = <$Int>::from_be_bytes(ext);
76 $builder.append_value(val);
77 Ok(())
78 }
79 _ => Err(AvroError::InvalidArgument(
80 concat!(
81 "Default for ",
82 $name,
83 " must be bytes (two's-complement big-endian)"
84 )
85 .to_string(),
86 )),
87 }
88 }};
89}
90
91#[derive(Debug)]
93pub(crate) struct RecordDecoder {
94 schema: SchemaRef,
95 fields: Vec<Decoder>,
96 projector: Option<Projector>,
97 row_count: usize,
98}
99
100impl RecordDecoder {
101 pub(crate) fn try_new_with_options(data_type: &AvroDataType) -> Result<Self, AvroError> {
112 match data_type.codec() {
113 Codec::Struct(reader_fields) => {
114 let mut arrow_fields = Vec::with_capacity(reader_fields.len());
116 let mut encodings = Vec::with_capacity(reader_fields.len());
117 let mut field_defaults = Vec::with_capacity(reader_fields.len());
118 for avro_field in reader_fields.iter() {
119 arrow_fields.push(avro_field.field());
120 encodings.push(Decoder::try_new(avro_field.data_type())?);
121
122 if let Some(ResolutionInfo::DefaultValue(lit)) =
123 avro_field.data_type().resolution.as_ref()
124 {
125 field_defaults.push(Some(lit.clone()));
126 } else {
127 field_defaults.push(None);
128 }
129 }
130 let projector = match data_type.resolution.as_ref() {
131 Some(ResolutionInfo::Record(rec)) => {
132 Some(ProjectorBuilder::try_new(rec, &field_defaults).build()?)
133 }
134 _ => None,
135 };
136 Ok(Self {
137 schema: Arc::new(ArrowSchema::new(arrow_fields)),
138 fields: encodings,
139 projector,
140 row_count: 0,
141 })
142 }
143 other => Err(AvroError::ParseError(format!(
144 "Expected record got {other:?}"
145 ))),
146 }
147 }
148
149 pub(crate) fn schema(&self) -> &SchemaRef {
151 &self.schema
152 }
153
154 pub(crate) fn decode(&mut self, buf: &[u8], count: usize) -> Result<usize, AvroError> {
156 let mut cursor = AvroCursor::new(buf);
157 match self.projector.as_mut() {
158 Some(proj) => {
159 for _ in 0..count {
160 proj.project_record(&mut cursor, &mut self.fields)?;
161 }
162 }
163 None => {
164 for _ in 0..count {
165 for field in &mut self.fields {
166 field.decode(&mut cursor)?;
167 }
168 }
169 }
170 }
171 self.row_count += count;
172 Ok(cursor.position())
173 }
174
175 pub(crate) fn flush(&mut self) -> Result<RecordBatch, AvroError> {
177 let arrays = self
178 .fields
179 .iter_mut()
180 .map(|x| x.flush(None))
181 .collect::<Result<Vec<_>, _>>()?;
182 let batch_options = RecordBatchOptions::new().with_row_count(Some(self.row_count));
183 self.row_count = 0;
184 RecordBatch::try_new_with_options(self.schema.clone(), arrays, &batch_options)
185 .map_err(Into::into)
186 }
187}
188
189#[derive(Debug, AsRefStr)]
190enum Decoder {
191 Null(usize),
192 Boolean(BooleanBufferBuilder),
193 Int32(Vec<i32>),
194 Int64(Vec<i64>),
195 #[cfg(feature = "avro_custom_types")]
196 DurationSecond(Vec<i64>),
197 #[cfg(feature = "avro_custom_types")]
198 DurationMillisecond(Vec<i64>),
199 #[cfg(feature = "avro_custom_types")]
200 DurationMicrosecond(Vec<i64>),
201 #[cfg(feature = "avro_custom_types")]
202 DurationNanosecond(Vec<i64>),
203 #[cfg(feature = "avro_custom_types")]
204 Int8(Vec<i8>),
205 #[cfg(feature = "avro_custom_types")]
206 Int16(Vec<i16>),
207 #[cfg(feature = "avro_custom_types")]
208 UInt8(Vec<u8>),
209 #[cfg(feature = "avro_custom_types")]
210 UInt16(Vec<u16>),
211 #[cfg(feature = "avro_custom_types")]
212 UInt32(Vec<u32>),
213 #[cfg(feature = "avro_custom_types")]
214 UInt64(Vec<u64>),
215 #[cfg(feature = "avro_custom_types")]
216 Float16(Vec<u16>), #[cfg(feature = "avro_custom_types")]
218 Date64(Vec<i64>),
219 #[cfg(feature = "avro_custom_types")]
220 TimeNanos(Vec<i64>),
221 #[cfg(feature = "avro_custom_types")]
222 Time32Secs(Vec<i32>),
223 #[cfg(feature = "avro_custom_types")]
224 TimestampSecs(bool, Vec<i64>),
225 #[cfg(feature = "avro_custom_types")]
226 IntervalYearMonth(Vec<i32>),
227 #[cfg(feature = "avro_custom_types")]
228 IntervalMonthDayNano(Vec<IntervalMonthDayNano>),
229 #[cfg(feature = "avro_custom_types")]
230 IntervalDayTime(Vec<IntervalDayTime>),
231 Float32(Vec<f32>),
232 Float64(Vec<f64>),
233 Date32(Vec<i32>),
234 TimeMillis(Vec<i32>),
235 TimeMicros(Vec<i64>),
236 TimestampMillis(Option<Tz>, Vec<i64>),
237 TimestampMicros(Option<Tz>, Vec<i64>),
238 TimestampNanos(Option<Tz>, Vec<i64>),
239 Int32ToInt64(Vec<i64>),
240 Int32ToFloat32(Vec<f32>),
241 Int32ToFloat64(Vec<f64>),
242 Int64ToFloat32(Vec<f32>),
243 Int64ToFloat64(Vec<f64>),
244 Float32ToFloat64(Vec<f64>),
245 BytesToString(OffsetBufferBuilder<i32>, Vec<u8>),
246 StringToBytes(OffsetBufferBuilder<i32>, Vec<u8>),
247 Binary(OffsetBufferBuilder<i32>, Vec<u8>),
248 String(OffsetBufferBuilder<i32>, Vec<u8>),
250 StringView(OffsetBufferBuilder<i32>, Vec<u8>),
252 Array(FieldRef, OffsetBufferBuilder<i32>, Box<Decoder>),
253 Record {
254 fields: Fields,
255 decoders: Vec<Decoder>,
256 defaults: Vec<Option<AvroLiteral>>,
257 projector: Option<Projector>,
258 row_count: usize,
262 },
263 Map(
264 FieldRef,
265 OffsetBufferBuilder<i32>,
266 OffsetBufferBuilder<i32>,
267 Vec<u8>,
268 Box<Decoder>,
269 ),
270 Fixed(i32, Vec<u8>),
271 Enum(Vec<i32>, Arc<[String]>, Option<EnumResolution>),
272 Duration(IntervalMonthDayNanoBuilder),
273 Uuid(Vec<u8>),
274 #[cfg(feature = "small_decimals")]
275 Decimal32(usize, Option<usize>, Option<usize>, Decimal32Builder),
276 #[cfg(feature = "small_decimals")]
277 Decimal64(usize, Option<usize>, Option<usize>, Decimal64Builder),
278 Decimal128(usize, Option<usize>, Option<usize>, Decimal128Builder),
279 Decimal256(usize, Option<usize>, Option<usize>, Decimal256Builder),
280 #[cfg(feature = "avro_custom_types")]
281 RunEndEncoded(u8, usize, Box<Decoder>),
282 Union(UnionDecoder),
283 Nullable(NullableDecoder),
285}
286
287#[derive(Debug)]
288struct NullableDecoder {
289 plan: NullablePlan,
290 validity: NullBufferBuilder,
291 values: Box<Decoder>,
292 pending_nulls: usize,
293}
294
295impl NullableDecoder {
296 fn new(plan: NullablePlan, values: Decoder) -> Self {
297 Self {
298 plan,
299 validity: NullBufferBuilder::new(DEFAULT_CAPACITY),
300 values: Box::new(values),
301 pending_nulls: 0,
302 }
303 }
304
305 #[inline]
306 fn materialize_pending(&mut self) -> Result<(), AvroError> {
307 if self.pending_nulls == 0 {
308 return Ok(());
309 }
310
311 self.values.append_nulls(self.pending_nulls)?;
312 self.validity.append_n_nulls(self.pending_nulls);
313 self.pending_nulls = 0;
314 Ok(())
315 }
316}
317
318impl Decoder {
319 fn try_new(data_type: &AvroDataType) -> Result<Self, AvroError> {
320 if let Some(ResolutionInfo::Union(info)) = data_type.resolution.as_ref()
321 && info.writer_is_union
322 && !info.reader_is_union
323 {
324 let mut clone = data_type.clone();
325 clone.resolution = None; let target = Self::try_new_internal(&clone)?;
327 let decoder = Self::Union(
328 UnionDecoderBuilder::new()
329 .with_resolved_union(info.clone())
330 .with_target(target)
331 .build()?,
332 );
333 return Ok(decoder);
334 }
335 Self::try_new_internal(data_type)
336 }
337
338 fn try_new_internal(data_type: &AvroDataType) -> Result<Self, AvroError> {
339 let promotion = match data_type.resolution.as_ref() {
341 Some(ResolutionInfo::Promotion(p)) => Some(*p),
342 _ => None,
343 };
344 let decoder = match (data_type.codec(), promotion) {
345 (Codec::Int64, Some(Promotion::IntToLong)) => {
346 Self::Int32ToInt64(Vec::with_capacity(DEFAULT_CAPACITY))
347 }
348 (Codec::Float32, Some(Promotion::IntToFloat)) => {
349 Self::Int32ToFloat32(Vec::with_capacity(DEFAULT_CAPACITY))
350 }
351 (Codec::Float64, Some(Promotion::IntToDouble)) => {
352 Self::Int32ToFloat64(Vec::with_capacity(DEFAULT_CAPACITY))
353 }
354 (Codec::Float32, Some(Promotion::LongToFloat)) => {
355 Self::Int64ToFloat32(Vec::with_capacity(DEFAULT_CAPACITY))
356 }
357 (Codec::Float64, Some(Promotion::LongToDouble)) => {
358 Self::Int64ToFloat64(Vec::with_capacity(DEFAULT_CAPACITY))
359 }
360 (Codec::Float64, Some(Promotion::FloatToDouble)) => {
361 Self::Float32ToFloat64(Vec::with_capacity(DEFAULT_CAPACITY))
362 }
363 (Codec::Utf8 | Codec::Utf8View, Some(Promotion::BytesToString)) => Self::BytesToString(
364 OffsetBufferBuilder::new(DEFAULT_CAPACITY),
365 Vec::with_capacity(DEFAULT_CAPACITY),
366 ),
367 (Codec::Binary, Some(Promotion::StringToBytes)) => Self::StringToBytes(
368 OffsetBufferBuilder::new(DEFAULT_CAPACITY),
369 Vec::with_capacity(DEFAULT_CAPACITY),
370 ),
371 (Codec::Null, _) => Self::Null(0),
372 (Codec::Boolean, _) => Self::Boolean(BooleanBufferBuilder::new(DEFAULT_CAPACITY)),
373 (Codec::Int32, _) => Self::Int32(Vec::with_capacity(DEFAULT_CAPACITY)),
374 (Codec::Int64, _) => Self::Int64(Vec::with_capacity(DEFAULT_CAPACITY)),
375 (Codec::Float32, _) => Self::Float32(Vec::with_capacity(DEFAULT_CAPACITY)),
376 (Codec::Float64, _) => Self::Float64(Vec::with_capacity(DEFAULT_CAPACITY)),
377 (Codec::Binary, _) => Self::Binary(
378 OffsetBufferBuilder::new(DEFAULT_CAPACITY),
379 Vec::with_capacity(DEFAULT_CAPACITY),
380 ),
381 (Codec::Utf8, _) => Self::String(
382 OffsetBufferBuilder::new(DEFAULT_CAPACITY),
383 Vec::with_capacity(DEFAULT_CAPACITY),
384 ),
385 (Codec::Utf8View, _) => Self::StringView(
386 OffsetBufferBuilder::new(DEFAULT_CAPACITY),
387 Vec::with_capacity(DEFAULT_CAPACITY),
388 ),
389 (Codec::Date32, _) => Self::Date32(Vec::with_capacity(DEFAULT_CAPACITY)),
390 (Codec::TimeMillis, _) => Self::TimeMillis(Vec::with_capacity(DEFAULT_CAPACITY)),
391 (Codec::TimeMicros, _) => Self::TimeMicros(Vec::with_capacity(DEFAULT_CAPACITY)),
392 (Codec::TimestampMillis(tz), _) => {
393 Self::TimestampMillis(*tz, Vec::with_capacity(DEFAULT_CAPACITY))
394 }
395 (Codec::TimestampMicros(tz), _) => {
396 Self::TimestampMicros(*tz, Vec::with_capacity(DEFAULT_CAPACITY))
397 }
398 (Codec::TimestampNanos(tz), _) => {
399 Self::TimestampNanos(*tz, Vec::with_capacity(DEFAULT_CAPACITY))
400 }
401 #[cfg(feature = "avro_custom_types")]
402 (Codec::DurationNanos, _) => {
403 Self::DurationNanosecond(Vec::with_capacity(DEFAULT_CAPACITY))
404 }
405 #[cfg(feature = "avro_custom_types")]
406 (Codec::DurationMicros, _) => {
407 Self::DurationMicrosecond(Vec::with_capacity(DEFAULT_CAPACITY))
408 }
409 #[cfg(feature = "avro_custom_types")]
410 (Codec::DurationMillis, _) => {
411 Self::DurationMillisecond(Vec::with_capacity(DEFAULT_CAPACITY))
412 }
413 #[cfg(feature = "avro_custom_types")]
414 (Codec::DurationSeconds, _) => {
415 Self::DurationSecond(Vec::with_capacity(DEFAULT_CAPACITY))
416 }
417 #[cfg(feature = "avro_custom_types")]
418 (Codec::Int8, _) => Self::Int8(Vec::with_capacity(DEFAULT_CAPACITY)),
419 #[cfg(feature = "avro_custom_types")]
420 (Codec::Int16, _) => Self::Int16(Vec::with_capacity(DEFAULT_CAPACITY)),
421 #[cfg(feature = "avro_custom_types")]
422 (Codec::UInt8, _) => Self::UInt8(Vec::with_capacity(DEFAULT_CAPACITY)),
423 #[cfg(feature = "avro_custom_types")]
424 (Codec::UInt16, _) => Self::UInt16(Vec::with_capacity(DEFAULT_CAPACITY)),
425 #[cfg(feature = "avro_custom_types")]
426 (Codec::UInt32, _) => Self::UInt32(Vec::with_capacity(DEFAULT_CAPACITY)),
427 #[cfg(feature = "avro_custom_types")]
428 (Codec::UInt64, _) => Self::UInt64(Vec::with_capacity(DEFAULT_CAPACITY)),
429 #[cfg(feature = "avro_custom_types")]
430 (Codec::Float16, _) => Self::Float16(Vec::with_capacity(DEFAULT_CAPACITY)),
431 #[cfg(feature = "avro_custom_types")]
432 (Codec::Date64, _) => Self::Date64(Vec::with_capacity(DEFAULT_CAPACITY)),
433 #[cfg(feature = "avro_custom_types")]
434 (Codec::TimeNanos, _) => Self::TimeNanos(Vec::with_capacity(DEFAULT_CAPACITY)),
435 #[cfg(feature = "avro_custom_types")]
436 (Codec::Time32Secs, _) => Self::Time32Secs(Vec::with_capacity(DEFAULT_CAPACITY)),
437 #[cfg(feature = "avro_custom_types")]
438 (Codec::TimestampSecs(is_utc), _) => {
439 Self::TimestampSecs(*is_utc, Vec::with_capacity(DEFAULT_CAPACITY))
440 }
441 #[cfg(feature = "avro_custom_types")]
442 (Codec::IntervalYearMonth, _) => {
443 Self::IntervalYearMonth(Vec::with_capacity(DEFAULT_CAPACITY))
444 }
445 #[cfg(feature = "avro_custom_types")]
446 (Codec::IntervalMonthDayNano, _) => {
447 Self::IntervalMonthDayNano(Vec::with_capacity(DEFAULT_CAPACITY))
448 }
449 #[cfg(feature = "avro_custom_types")]
450 (Codec::IntervalDayTime, _) => {
451 Self::IntervalDayTime(Vec::with_capacity(DEFAULT_CAPACITY))
452 }
453 (Codec::Fixed(sz), _) => Self::Fixed(*sz, Vec::with_capacity(DEFAULT_CAPACITY)),
454 (Codec::Decimal(precision, scale, size), _) => {
455 let p = *precision;
456 let s = *scale;
457 let prec = p as u8;
458 let scl = s.unwrap_or(0) as i8;
459 #[cfg(feature = "small_decimals")]
460 {
461 if p <= DECIMAL32_MAX_PRECISION as usize {
462 let builder = Decimal32Builder::with_capacity(DEFAULT_CAPACITY)
463 .with_precision_and_scale(prec, scl)?;
464 Self::Decimal32(p, s, *size, builder)
465 } else if p <= DECIMAL64_MAX_PRECISION as usize {
466 let builder = Decimal64Builder::with_capacity(DEFAULT_CAPACITY)
467 .with_precision_and_scale(prec, scl)?;
468 Self::Decimal64(p, s, *size, builder)
469 } else if p <= DECIMAL128_MAX_PRECISION as usize {
470 let builder = Decimal128Builder::with_capacity(DEFAULT_CAPACITY)
471 .with_precision_and_scale(prec, scl)?;
472 Self::Decimal128(p, s, *size, builder)
473 } else if p <= DECIMAL256_MAX_PRECISION as usize {
474 let builder = Decimal256Builder::with_capacity(DEFAULT_CAPACITY)
475 .with_precision_and_scale(prec, scl)?;
476 Self::Decimal256(p, s, *size, builder)
477 } else {
478 return Err(AvroError::ParseError(format!(
479 "Decimal precision {p} exceeds maximum supported"
480 )));
481 }
482 }
483 #[cfg(not(feature = "small_decimals"))]
484 {
485 if p <= DECIMAL128_MAX_PRECISION as usize {
486 let builder = Decimal128Builder::with_capacity(DEFAULT_CAPACITY)
487 .with_precision_and_scale(prec, scl)?;
488 Self::Decimal128(p, s, *size, builder)
489 } else if p <= DECIMAL256_MAX_PRECISION as usize {
490 let builder = Decimal256Builder::with_capacity(DEFAULT_CAPACITY)
491 .with_precision_and_scale(prec, scl)?;
492 Self::Decimal256(p, s, *size, builder)
493 } else {
494 return Err(AvroError::ParseError(format!(
495 "Decimal precision {p} exceeds maximum supported"
496 )));
497 }
498 }
499 }
500 (Codec::Interval, _) => Self::Duration(IntervalMonthDayNanoBuilder::new()),
501 (Codec::List(item), _) => {
502 let decoder = Self::try_new(item)?;
503 Self::Array(
504 Arc::new(item.field_with_name("item")),
505 OffsetBufferBuilder::new(DEFAULT_CAPACITY),
506 Box::new(decoder),
507 )
508 }
509 (Codec::Enum(symbols), _) => {
510 let res = match data_type.resolution.as_ref() {
511 Some(ResolutionInfo::EnumMapping(mapping)) => {
512 Some(EnumResolution::new(mapping))
513 }
514 _ => None,
515 };
516 Self::Enum(Vec::with_capacity(DEFAULT_CAPACITY), symbols.clone(), res)
517 }
518 (Codec::Struct(fields), _) => {
519 let mut arrow_fields = Vec::with_capacity(fields.len());
520 let mut encodings = Vec::with_capacity(fields.len());
521 let mut field_defaults = Vec::with_capacity(fields.len());
522 for avro_field in fields.iter() {
523 let encoding = Self::try_new(avro_field.data_type())?;
524 arrow_fields.push(avro_field.field());
525 encodings.push(encoding);
526
527 if let Some(ResolutionInfo::DefaultValue(lit)) =
528 avro_field.data_type().resolution.as_ref()
529 {
530 field_defaults.push(Some(lit.clone()));
531 } else {
532 field_defaults.push(None);
533 }
534 }
535 let projector =
536 if let Some(ResolutionInfo::Record(rec)) = data_type.resolution.as_ref() {
537 Some(ProjectorBuilder::try_new(rec, &field_defaults).build()?)
538 } else {
539 None
540 };
541 Self::Record {
542 fields: arrow_fields.into(),
543 decoders: encodings,
544 defaults: field_defaults,
545 projector,
546 row_count: 0,
547 }
548 }
549 (Codec::Map(child), _) => {
550 let val_field = child.field_with_name(ArrowField::MAP_VALUE_FIELD_DEFAULT_NAME);
551 let map_field = Arc::new(ArrowField::new(
552 ArrowField::MAP_ENTRIES_FIELD_DEFAULT_NAME,
553 DataType::Struct(Fields::from(vec![
554 ArrowField::new(
555 ArrowField::MAP_KEY_FIELD_DEFAULT_NAME,
556 DataType::Utf8,
557 false,
558 ),
559 val_field,
560 ])),
561 false,
562 ));
563 let val_dec = Self::try_new(child)?;
564 Self::Map(
565 map_field,
566 OffsetBufferBuilder::new(DEFAULT_CAPACITY),
567 OffsetBufferBuilder::new(DEFAULT_CAPACITY),
568 Vec::with_capacity(DEFAULT_CAPACITY),
569 Box::new(val_dec),
570 )
571 }
572 (Codec::Uuid, _) => Self::Uuid(Vec::with_capacity(DEFAULT_CAPACITY)),
573 (Codec::Union(encodings, fields, UnionMode::Dense), _) => {
574 let decoders = encodings
575 .iter()
576 .map(Self::try_new_internal)
577 .collect::<Result<Vec<_>, _>>()?;
578 if fields.len() != decoders.len() {
579 return Err(AvroError::SchemaError(format!(
580 "Union has {} fields but {} decoders",
581 fields.len(),
582 decoders.len()
583 )));
584 }
585 let branch_count = decoders.len();
588 let max_addr = (i32::MAX as usize) + 1;
589 if branch_count > max_addr {
590 return Err(AvroError::SchemaError(format!(
591 "Union has {branch_count} branches, which exceeds the maximum addressable \
592 branches by an Avro int tag ({} + 1).",
593 i32::MAX
594 )));
595 }
596 let mut builder = UnionDecoderBuilder::new()
597 .with_fields(fields.clone())
598 .with_branches(decoders);
599 if let Some(ResolutionInfo::Union(info)) = data_type.resolution.as_ref()
600 && info.reader_is_union
601 {
602 builder = builder.with_resolved_union(info.clone());
603 }
604 Self::Union(builder.build()?)
605 }
606 (Codec::Union(_, _, _), _) => {
607 return Err(AvroError::NYI(
608 "Sparse Arrow unions are not yet supported".to_string(),
609 ));
610 }
611 #[cfg(feature = "avro_custom_types")]
612 (Codec::RunEndEncoded(values_dt, width_bits_or_bytes), _) => {
613 let inner = Self::try_new(values_dt)?;
614 let byte_width: u8 = match *width_bits_or_bytes {
615 2 | 4 | 8 => *width_bits_or_bytes,
616 16 => 2,
617 32 => 4,
618 64 => 8,
619 other => {
620 return Err(AvroError::InvalidArgument(format!(
621 "Unsupported run-end width {other} for RunEndEncoded; \
622 expected 16/32/64 bits or 2/4/8 bytes"
623 )));
624 }
625 };
626 Self::RunEndEncoded(byte_width, 0, Box::new(inner))
627 }
628 };
629 Ok(match data_type.nullability() {
630 Some(nullability) => {
631 let plan = match &data_type.resolution {
633 None => NullablePlan::ReadTag {
634 nullability,
635 resolution: ResolutionPlan::Promotion(Promotion::Direct),
636 },
637 Some(ResolutionInfo::Promotion(_)) => {
638 NullablePlan::FromSingle {
641 resolution: ResolutionPlan::Promotion(Promotion::Direct),
642 }
643 }
644 Some(ResolutionInfo::Union(info)) if !info.writer_is_union => {
645 let Some(Some((_, resolution))) = info.writer_to_reader.first() else {
646 return Err(AvroError::SchemaError(
647 "unexpected union resolution info for non-union writer and union reader type".into(),
648 ));
649 };
650 let resolution = ResolutionPlan::try_new(&decoder, resolution)?;
651 NullablePlan::FromSingle { resolution }
652 }
653 Some(ResolutionInfo::Union(info)) => {
654 let Some((_, resolution)) =
655 info.writer_to_reader[nullability.non_null_index()].as_ref()
656 else {
657 return Err(AvroError::SchemaError(
658 "unexpected union resolution info for nullable writer type".into(),
659 ));
660 };
661 NullablePlan::ReadTag {
662 nullability,
663 resolution: ResolutionPlan::try_new(&decoder, resolution)?,
664 }
665 }
666 Some(resolution) => NullablePlan::FromSingle {
667 resolution: ResolutionPlan::try_new(&decoder, resolution)?,
668 },
669 };
670 Self::Nullable(NullableDecoder::new(plan, decoder))
671 }
672 None => decoder,
673 })
674 }
675
676 fn append_null(&mut self) -> Result<(), AvroError> {
678 self.append_nulls(1)
679 }
680
681 fn append_nulls(&mut self, count: usize) -> Result<(), AvroError> {
684 if count == 0 {
685 return Ok(());
686 }
687 match self {
688 Self::Null(size) => *size += count,
689 Self::Boolean(values) => values.append_n(count, false),
690 Self::Int32(values) | Self::Date32(values) | Self::TimeMillis(values) => {
691 values.resize(values.len() + count, 0)
692 }
693 Self::Int64(values)
694 | Self::Int32ToInt64(values)
695 | Self::TimeMicros(values)
696 | Self::TimestampMillis(_, values)
697 | Self::TimestampMicros(_, values)
698 | Self::TimestampNanos(_, values) => values.resize(values.len() + count, 0),
699 #[cfg(feature = "avro_custom_types")]
700 Self::DurationSecond(values)
701 | Self::DurationMillisecond(values)
702 | Self::DurationMicrosecond(values)
703 | Self::DurationNanosecond(values)
704 | Self::Date64(values)
705 | Self::TimeNanos(values)
706 | Self::TimestampSecs(_, values) => values.resize(values.len() + count, 0),
707 #[cfg(feature = "avro_custom_types")]
708 Self::Int8(values) => values.resize(values.len() + count, 0),
709 #[cfg(feature = "avro_custom_types")]
710 Self::Int16(values) => values.resize(values.len() + count, 0),
711 #[cfg(feature = "avro_custom_types")]
712 Self::UInt8(values) => values.resize(values.len() + count, 0),
713 #[cfg(feature = "avro_custom_types")]
714 Self::UInt16(values) | Self::Float16(values) => values.resize(values.len() + count, 0),
715 #[cfg(feature = "avro_custom_types")]
716 Self::UInt32(values) => values.resize(values.len() + count, 0),
717 #[cfg(feature = "avro_custom_types")]
718 Self::UInt64(values) => values.resize(values.len() + count, 0),
719 #[cfg(feature = "avro_custom_types")]
720 Self::Time32Secs(values) | Self::IntervalYearMonth(values) => {
721 values.resize(values.len() + count, 0)
722 }
723 #[cfg(feature = "avro_custom_types")]
724 Self::IntervalDayTime(values) => {
725 values.resize(values.len() + count, IntervalDayTime::new(0, 0))
726 }
727 #[cfg(feature = "avro_custom_types")]
728 Self::IntervalMonthDayNano(values) => {
729 values.resize(values.len() + count, IntervalMonthDayNano::new(0, 0, 0))
730 }
731 Self::Float32(values) | Self::Int32ToFloat32(values) | Self::Int64ToFloat32(values) => {
732 values.resize(values.len() + count, 0.0)
733 }
734 Self::Float64(values)
735 | Self::Int32ToFloat64(values)
736 | Self::Int64ToFloat64(values)
737 | Self::Float32ToFloat64(values) => values.resize(values.len() + count, 0.0),
738 Self::Binary(offsets, _)
739 | Self::String(offsets, _)
740 | Self::StringView(offsets, _)
741 | Self::BytesToString(offsets, _)
742 | Self::StringToBytes(offsets, _)
743 | Self::Array(_, offsets, _)
744 | Self::Map(_, _, offsets, _, _) => {
745 offsets.reserve(count);
746 for _ in 0..count {
747 offsets.push_length(0);
748 }
749 }
750 Self::Record {
751 decoders,
752 row_count,
753 ..
754 } => {
755 for child in decoders.iter_mut() {
756 child.append_nulls(count)?;
757 }
758 *row_count += count;
759 }
760 Self::Fixed(width, values) => {
761 values.resize(values.len() + (*width as usize) * count, 0)
762 }
763 Self::Enum(values, _, _) => values.resize(values.len() + count, 0),
764 Self::Duration(builder) => builder.append_nulls(count),
765 Self::Uuid(values) => values.resize(values.len() + 16 * count, 0),
766 #[cfg(feature = "small_decimals")]
767 Self::Decimal32(_, _, _, builder) => builder.append_value_n(0, count),
768 #[cfg(feature = "small_decimals")]
769 Self::Decimal64(_, _, _, builder) => builder.append_value_n(0, count),
770 Self::Decimal128(_, _, _, builder) => builder.append_value_n(0, count),
771 Self::Decimal256(_, _, _, builder) => builder.append_value_n(i256::ZERO, count),
772 #[cfg(feature = "avro_custom_types")]
773 Self::RunEndEncoded(_, len, inner) => {
774 inner.append_nulls(count)?;
775 *len += count;
776 }
777 Self::Union(union) => {
778 for _ in 0..count {
779 union.append_null()?;
780 }
781 }
782 Self::Nullable(nullable) => nullable.pending_nulls += count,
783 }
784 Ok(())
785 }
786
787 fn append_default(&mut self, lit: &AvroLiteral) -> Result<(), AvroError> {
789 match self {
790 Self::Nullable(nullable) => {
791 if matches!(lit, AvroLiteral::Null) {
792 nullable.pending_nulls += 1;
793 } else {
794 nullable.materialize_pending()?;
795 nullable.values.append_default(lit)?;
796 nullable.validity.append_non_null();
797 }
798 Ok(())
799 }
800 Self::Null(count) => match lit {
801 AvroLiteral::Null => {
802 *count += 1;
803 Ok(())
804 }
805 _ => Err(AvroError::InvalidArgument(
806 "Non-null default for null type".to_string(),
807 )),
808 },
809 Self::Boolean(b) => match lit {
810 AvroLiteral::Boolean(v) => {
811 b.append(*v);
812 Ok(())
813 }
814 _ => Err(AvroError::InvalidArgument(
815 "Default for boolean must be boolean".to_string(),
816 )),
817 },
818 Self::Int32(v) | Self::Date32(v) | Self::TimeMillis(v) => match lit {
819 AvroLiteral::Int(i) => {
820 v.push(*i);
821 Ok(())
822 }
823 _ => Err(AvroError::InvalidArgument(
824 "Default for int32/date32/time-millis must be int".to_string(),
825 )),
826 },
827 #[cfg(feature = "avro_custom_types")]
828 Self::DurationSecond(v)
829 | Self::DurationMillisecond(v)
830 | Self::DurationMicrosecond(v)
831 | Self::DurationNanosecond(v) => match lit {
832 AvroLiteral::Long(i) => {
833 v.push(*i);
834 Ok(())
835 }
836 _ => Err(AvroError::InvalidArgument(
837 "Default for duration long must be long".to_string(),
838 )),
839 },
840 #[cfg(feature = "avro_custom_types")]
841 Self::Int8(v) => match lit {
842 AvroLiteral::Int(i) => {
843 let x = i8::try_from(*i).map_err(|_| {
844 AvroError::InvalidArgument(format!(
845 "Default for int8 out of range for i8: {i}"
846 ))
847 })?;
848 v.push(x);
849 Ok(())
850 }
851 _ => Err(AvroError::InvalidArgument(
852 "Default for int8 must be int".to_string(),
853 )),
854 },
855 #[cfg(feature = "avro_custom_types")]
856 Self::Int16(v) => match lit {
857 AvroLiteral::Int(i) => {
858 let x = i16::try_from(*i).map_err(|_| {
859 AvroError::InvalidArgument(format!(
860 "Default for int16 out of range for i16: {i}"
861 ))
862 })?;
863 v.push(x);
864 Ok(())
865 }
866 _ => Err(AvroError::InvalidArgument(
867 "Default for int16 must be int".to_string(),
868 )),
869 },
870 #[cfg(feature = "avro_custom_types")]
871 Self::UInt8(v) => match lit {
872 AvroLiteral::Int(i) => {
873 let x = u8::try_from(*i).map_err(|_| {
874 AvroError::InvalidArgument(format!(
875 "Default for uint8 out of range for u8: {i}"
876 ))
877 })?;
878 v.push(x);
879 Ok(())
880 }
881 _ => Err(AvroError::InvalidArgument(
882 "Default for uint8 must be int".to_string(),
883 )),
884 },
885 #[cfg(feature = "avro_custom_types")]
886 Self::UInt16(v) => match lit {
887 AvroLiteral::Int(i) => {
888 let x = u16::try_from(*i).map_err(|_| {
889 AvroError::InvalidArgument(format!(
890 "Default for uint16 out of range for u16: {i}"
891 ))
892 })?;
893 v.push(x);
894 Ok(())
895 }
896 _ => Err(AvroError::InvalidArgument(
897 "Default for uint16 must be int".to_string(),
898 )),
899 },
900 #[cfg(feature = "avro_custom_types")]
901 Self::UInt32(v) => match lit {
902 AvroLiteral::Long(i) => {
903 let x = u32::try_from(*i).map_err(|_| {
904 AvroError::InvalidArgument(format!(
905 "Default for uint32 out of range for u32: {i}"
906 ))
907 })?;
908 v.push(x);
909 Ok(())
910 }
911 _ => Err(AvroError::InvalidArgument(
912 "Default for uint32 must be long".to_string(),
913 )),
914 },
915 #[cfg(feature = "avro_custom_types")]
916 Self::UInt64(v) => match lit {
917 AvroLiteral::Bytes(b) => {
918 if b.len() != 8 {
919 return Err(AvroError::InvalidArgument(format!(
920 "uint64 default must be exactly 8 bytes, got {}",
921 b.len()
922 )));
923 }
924 v.push(u64::from_le_bytes([
925 b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
926 ]));
927 Ok(())
928 }
929 _ => Err(AvroError::InvalidArgument(
930 "Default for uint64 must be bytes (8-byte LE)".to_string(),
931 )),
932 },
933 #[cfg(feature = "avro_custom_types")]
934 Self::Float16(v) => match lit {
935 AvroLiteral::Bytes(b) => {
936 if b.len() != 2 {
937 return Err(AvroError::InvalidArgument(format!(
938 "float16 default must be exactly 2 bytes, got {}",
939 b.len()
940 )));
941 }
942 v.push(u16::from_le_bytes([b[0], b[1]]));
943 Ok(())
944 }
945 _ => Err(AvroError::InvalidArgument(
946 "Default for float16 must be bytes (2-byte LE IEEE-754)".to_string(),
947 )),
948 },
949 #[cfg(feature = "avro_custom_types")]
950 Self::Date64(v) | Self::TimeNanos(v) | Self::TimestampSecs(_, v) => match lit {
951 AvroLiteral::Long(i) => {
952 v.push(*i);
953 Ok(())
954 }
955 _ => Err(AvroError::InvalidArgument(
956 "Default for date64/time-nanos/timestamp-secs must be long".to_string(),
957 )),
958 },
959 #[cfg(feature = "avro_custom_types")]
960 Self::Time32Secs(v) => match lit {
961 AvroLiteral::Int(i) => {
962 v.push(*i);
963 Ok(())
964 }
965 _ => Err(AvroError::InvalidArgument(
966 "Default for time32-secs must be int".to_string(),
967 )),
968 },
969 #[cfg(feature = "avro_custom_types")]
970 Self::IntervalYearMonth(v) => match lit {
971 AvroLiteral::Bytes(b) => {
972 if b.len() != 4 {
973 return Err(AvroError::InvalidArgument(format!(
974 "interval-year-month default must be exactly 4 bytes, got {}",
975 b.len()
976 )));
977 }
978 v.push(i32::from_le_bytes([b[0], b[1], b[2], b[3]]));
979 Ok(())
980 }
981 _ => Err(AvroError::InvalidArgument(
982 "Default for interval-year-month must be bytes (4-byte LE)".to_string(),
983 )),
984 },
985 #[cfg(feature = "avro_custom_types")]
986 Self::IntervalMonthDayNano(v) => match lit {
987 AvroLiteral::Bytes(b) => {
988 if b.len() != 16 {
989 return Err(AvroError::InvalidArgument(format!(
990 "interval-month-day-nano default must be exactly 16 bytes, got {}",
991 b.len()
992 )));
993 }
994 let months = i32::from_le_bytes([b[0], b[1], b[2], b[3]]);
995 let days = i32::from_le_bytes([b[4], b[5], b[6], b[7]]);
996 let nanos =
997 i64::from_le_bytes([b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]]);
998 v.push(IntervalMonthDayNano::new(months, days, nanos));
999 Ok(())
1000 }
1001 _ => Err(AvroError::InvalidArgument(
1002 "Default for interval-month-day-nano must be bytes (16-byte LE)".to_string(),
1003 )),
1004 },
1005 #[cfg(feature = "avro_custom_types")]
1006 Self::IntervalDayTime(v) => match lit {
1007 AvroLiteral::Bytes(b) => {
1008 if b.len() != 8 {
1009 return Err(AvroError::InvalidArgument(format!(
1010 "interval-day-time default must be exactly 8 bytes, got {}",
1011 b.len()
1012 )));
1013 }
1014 let days = i32::from_le_bytes([b[0], b[1], b[2], b[3]]);
1015 let milliseconds = i32::from_le_bytes([b[4], b[5], b[6], b[7]]);
1016 v.push(IntervalDayTime::new(days, milliseconds));
1017 Ok(())
1018 }
1019 _ => Err(AvroError::InvalidArgument(
1020 "Default for interval-day-time must be bytes (8-byte LE)".to_string(),
1021 )),
1022 },
1023 Self::Int64(v)
1024 | Self::Int32ToInt64(v)
1025 | Self::TimeMicros(v)
1026 | Self::TimestampMillis(_, v)
1027 | Self::TimestampMicros(_, v)
1028 | Self::TimestampNanos(_, v) => match lit {
1029 AvroLiteral::Long(i) => {
1030 v.push(*i);
1031 Ok(())
1032 }
1033 AvroLiteral::Int(i) => {
1034 v.push(*i as i64);
1035 Ok(())
1036 }
1037 _ => Err(AvroError::InvalidArgument(
1038 "Default for long/time-micros/timestamp must be long or int".to_string(),
1039 )),
1040 },
1041 Self::Float32(v) | Self::Int32ToFloat32(v) | Self::Int64ToFloat32(v) => match lit {
1042 AvroLiteral::Float(f) => {
1043 v.push(*f);
1044 Ok(())
1045 }
1046 _ => Err(AvroError::InvalidArgument(
1047 "Default for float must be float".to_string(),
1048 )),
1049 },
1050 Self::Float64(v)
1051 | Self::Int32ToFloat64(v)
1052 | Self::Int64ToFloat64(v)
1053 | Self::Float32ToFloat64(v) => match lit {
1054 AvroLiteral::Double(f) => {
1055 v.push(*f);
1056 Ok(())
1057 }
1058 _ => Err(AvroError::InvalidArgument(
1059 "Default for double must be double".to_string(),
1060 )),
1061 },
1062 Self::Binary(offsets, values) | Self::StringToBytes(offsets, values) => match lit {
1063 AvroLiteral::Bytes(b) => {
1064 offsets.push_length(b.len());
1065 values.extend_from_slice(b);
1066 Ok(())
1067 }
1068 _ => Err(AvroError::InvalidArgument(
1069 "Default for bytes must be bytes".to_string(),
1070 )),
1071 },
1072 Self::BytesToString(offsets, values)
1073 | Self::String(offsets, values)
1074 | Self::StringView(offsets, values) => match lit {
1075 AvroLiteral::String(s) => {
1076 let b = s.as_bytes();
1077 offsets.push_length(b.len());
1078 values.extend_from_slice(b);
1079 Ok(())
1080 }
1081 _ => Err(AvroError::InvalidArgument(
1082 "Default for string must be string".to_string(),
1083 )),
1084 },
1085 Self::Uuid(values) => match lit {
1086 AvroLiteral::String(s) => {
1087 let uuid = Uuid::try_parse(s).map_err(|e| {
1088 AvroError::InvalidArgument(format!("Invalid UUID default: {s} ({e})"))
1089 })?;
1090 values.extend_from_slice(uuid.as_bytes());
1091 Ok(())
1092 }
1093 _ => Err(AvroError::InvalidArgument(
1094 "Default for uuid must be string".to_string(),
1095 )),
1096 },
1097 Self::Fixed(sz, accum) => match lit {
1098 AvroLiteral::Bytes(b) => {
1099 if b.len() != *sz as usize {
1100 return Err(AvroError::InvalidArgument(format!(
1101 "Fixed default length {} does not match size {sz}",
1102 b.len(),
1103 )));
1104 }
1105 accum.extend_from_slice(b);
1106 Ok(())
1107 }
1108 _ => Err(AvroError::InvalidArgument(
1109 "Default for fixed must be bytes".to_string(),
1110 )),
1111 },
1112 #[cfg(feature = "small_decimals")]
1113 Self::Decimal32(_, _, _, builder) => {
1114 append_decimal_default!(lit, builder, 4, i32, "decimal32")
1115 }
1116 #[cfg(feature = "small_decimals")]
1117 Self::Decimal64(_, _, _, builder) => {
1118 append_decimal_default!(lit, builder, 8, i64, "decimal64")
1119 }
1120 Self::Decimal128(_, _, _, builder) => {
1121 append_decimal_default!(lit, builder, 16, i128, "decimal128")
1122 }
1123 Self::Decimal256(_, _, _, builder) => {
1124 append_decimal_default!(lit, builder, 32, i256, "decimal256")
1125 }
1126 Self::Duration(builder) => match lit {
1127 AvroLiteral::Bytes(b) => {
1128 if b.len() != 12 {
1129 return Err(AvroError::InvalidArgument(format!(
1130 "Duration default must be exactly 12 bytes, got {}",
1131 b.len()
1132 )));
1133 }
1134 let months = u32::from_le_bytes([b[0], b[1], b[2], b[3]]);
1135 let days = u32::from_le_bytes([b[4], b[5], b[6], b[7]]);
1136 let millis = u32::from_le_bytes([b[8], b[9], b[10], b[11]]);
1137 let nanos = (millis as i64) * 1_000_000;
1138 builder.append_value(IntervalMonthDayNano::new(
1139 months as i32,
1140 days as i32,
1141 nanos,
1142 ));
1143 Ok(())
1144 }
1145 _ => Err(AvroError::InvalidArgument(
1146 "Default for duration must be 12-byte little-endian months/days/millis"
1147 .to_string(),
1148 )),
1149 },
1150 Self::Array(_, offsets, inner) => match lit {
1151 AvroLiteral::Array(items) => {
1152 offsets.push_length(items.len());
1153 for item in items {
1154 inner.append_default(item)?;
1155 }
1156 Ok(())
1157 }
1158 _ => Err(AvroError::InvalidArgument(
1159 "Default for array must be an array literal".to_string(),
1160 )),
1161 },
1162 Self::Map(_, koff, moff, kdata, valdec) => match lit {
1163 AvroLiteral::Map(entries) => {
1164 moff.push_length(entries.len());
1165 for (k, v) in entries {
1166 let kb = k.as_bytes();
1167 koff.push_length(kb.len());
1168 kdata.extend_from_slice(kb);
1169 valdec.append_default(v)?;
1170 }
1171 Ok(())
1172 }
1173 _ => Err(AvroError::InvalidArgument(
1174 "Default for map must be a map/object literal".to_string(),
1175 )),
1176 },
1177 Self::Enum(indices, symbols, _) => match lit {
1178 AvroLiteral::Enum(sym) => {
1179 let pos = symbols.iter().position(|s| s == sym).ok_or_else(|| {
1180 AvroError::InvalidArgument(format!(
1181 "Enum default symbol {sym:?} not in reader symbols"
1182 ))
1183 })?;
1184 indices.push(pos as i32);
1185 Ok(())
1186 }
1187 _ => Err(AvroError::InvalidArgument(
1188 "Default for enum must be a symbol".to_string(),
1189 )),
1190 },
1191 #[cfg(feature = "avro_custom_types")]
1192 Self::RunEndEncoded(_, len, inner) => {
1193 *len += 1;
1194 inner.append_default(lit)
1195 }
1196 Self::Union(u) => u.append_default(lit),
1197 Self::Record {
1198 fields: field_meta,
1199 decoders,
1200 defaults: field_defaults,
1201 row_count,
1202 ..
1203 } => match lit {
1204 AvroLiteral::Map(entries) => {
1205 for (i, dec) in decoders.iter_mut().enumerate() {
1206 let name = field_meta[i].name();
1207 if let Some(sub) = entries.get(name) {
1208 dec.append_default(sub)?;
1209 } else if let Some(default_literal) = field_defaults[i].as_ref() {
1210 dec.append_default(default_literal)?;
1211 } else {
1212 dec.append_null()?;
1213 }
1214 }
1215 *row_count += 1;
1216 Ok(())
1217 }
1218 AvroLiteral::Null => {
1219 for (i, dec) in decoders.iter_mut().enumerate() {
1220 if let Some(default_literal) = field_defaults[i].as_ref() {
1221 dec.append_default(default_literal)?;
1222 } else {
1223 dec.append_null()?;
1224 }
1225 }
1226 *row_count += 1;
1227 Ok(())
1228 }
1229 _ => Err(AvroError::InvalidArgument(
1230 "Default for record must be a map/object or null".to_string(),
1231 )),
1232 },
1233 }
1234 }
1235
1236 fn decode(&mut self, buf: &mut AvroCursor<'_>) -> Result<(), AvroError> {
1238 match self {
1239 Self::Null(x) => *x += 1,
1240 Self::Boolean(values) => values.append(buf.get_bool()?),
1241 Self::Int32(values) | Self::Date32(values) | Self::TimeMillis(values) => {
1242 values.push(buf.get_int()?)
1243 }
1244 Self::Int64(values)
1245 | Self::TimeMicros(values)
1246 | Self::TimestampMillis(_, values)
1247 | Self::TimestampMicros(_, values)
1248 | Self::TimestampNanos(_, values) => values.push(buf.get_long()?),
1249 #[cfg(feature = "avro_custom_types")]
1250 Self::DurationSecond(values)
1251 | Self::DurationMillisecond(values)
1252 | Self::DurationMicrosecond(values)
1253 | Self::DurationNanosecond(values) => values.push(buf.get_long()?),
1254 #[cfg(feature = "avro_custom_types")]
1255 Self::Int8(values) => {
1256 let raw = buf.get_int()?;
1257 let x = i8::try_from(raw).map_err(|_| {
1258 AvroError::ParseError(format!("int8 value {raw} out of range for i8"))
1259 })?;
1260 values.push(x);
1261 }
1262 #[cfg(feature = "avro_custom_types")]
1263 Self::Int16(values) => {
1264 let raw = buf.get_int()?;
1265 let x = i16::try_from(raw).map_err(|_| {
1266 AvroError::ParseError(format!("int16 value {raw} out of range for i16"))
1267 })?;
1268 values.push(x);
1269 }
1270 #[cfg(feature = "avro_custom_types")]
1271 Self::UInt8(values) => {
1272 let raw = buf.get_int()?;
1273 let x = u8::try_from(raw).map_err(|_| {
1274 AvroError::ParseError(format!("uint8 value {raw} out of range for u8"))
1275 })?;
1276 values.push(x);
1277 }
1278 #[cfg(feature = "avro_custom_types")]
1279 Self::UInt16(values) => {
1280 let raw = buf.get_int()?;
1281 let x = u16::try_from(raw).map_err(|_| {
1282 AvroError::ParseError(format!("uint16 value {raw} out of range for u16"))
1283 })?;
1284 values.push(x);
1285 }
1286 #[cfg(feature = "avro_custom_types")]
1287 Self::UInt32(values) => {
1288 let raw = buf.get_long()?;
1289 let x = u32::try_from(raw).map_err(|_| {
1290 AvroError::ParseError(format!("uint32 value {raw} out of range for u32"))
1291 })?;
1292 values.push(x);
1293 }
1294 #[cfg(feature = "avro_custom_types")]
1295 Self::UInt64(values) => {
1296 let b = buf.get_fixed(8)?;
1297 values.push(u64::from_le_bytes([
1298 b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
1299 ]));
1300 }
1301 #[cfg(feature = "avro_custom_types")]
1302 Self::Float16(values) => {
1303 let b = buf.get_fixed(2)?;
1304 values.push(u16::from_le_bytes([b[0], b[1]]));
1305 }
1306 #[cfg(feature = "avro_custom_types")]
1307 Self::Date64(values) | Self::TimeNanos(values) | Self::TimestampSecs(_, values) => {
1308 values.push(buf.get_long()?)
1309 }
1310 #[cfg(feature = "avro_custom_types")]
1311 Self::Time32Secs(values) => values.push(buf.get_int()?),
1312 #[cfg(feature = "avro_custom_types")]
1313 Self::IntervalYearMonth(values) => {
1314 let b = buf.get_fixed(4)?;
1315 values.push(i32::from_le_bytes([b[0], b[1], b[2], b[3]]));
1316 }
1317 #[cfg(feature = "avro_custom_types")]
1318 Self::IntervalMonthDayNano(values) => {
1319 let b = buf.get_fixed(16)?;
1320 let months = i32::from_le_bytes([b[0], b[1], b[2], b[3]]);
1321 let days = i32::from_le_bytes([b[4], b[5], b[6], b[7]]);
1322 let nanos =
1323 i64::from_le_bytes([b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]]);
1324 values.push(IntervalMonthDayNano::new(months, days, nanos));
1325 }
1326 #[cfg(feature = "avro_custom_types")]
1327 Self::IntervalDayTime(values) => {
1328 let b = buf.get_fixed(8)?;
1329 let days = i32::from_le_bytes([b[0], b[1], b[2], b[3]]);
1331 let milliseconds = i32::from_le_bytes([b[4], b[5], b[6], b[7]]);
1332 values.push(IntervalDayTime::new(days, milliseconds));
1333 }
1334 Self::Float32(values) => values.push(buf.get_float()?),
1335 Self::Float64(values) => values.push(buf.get_double()?),
1336 Self::Int32ToInt64(values) => values.push(buf.get_int()? as i64),
1337 Self::Int32ToFloat32(values) => values.push(buf.get_int()? as f32),
1338 Self::Int32ToFloat64(values) => values.push(buf.get_int()? as f64),
1339 Self::Int64ToFloat32(values) => values.push(buf.get_long()? as f32),
1340 Self::Int64ToFloat64(values) => values.push(buf.get_long()? as f64),
1341 Self::Float32ToFloat64(values) => values.push(buf.get_float()? as f64),
1342 Self::StringToBytes(offsets, values)
1343 | Self::BytesToString(offsets, values)
1344 | Self::Binary(offsets, values)
1345 | Self::String(offsets, values)
1346 | Self::StringView(offsets, values) => {
1347 let data = buf.get_bytes()?;
1348 offsets.push_length(data.len());
1349 values.extend_from_slice(data);
1350 }
1351 Self::Uuid(values) => {
1352 let s_bytes = buf.get_bytes()?;
1353 let s = std::str::from_utf8(s_bytes).map_err(|e| {
1354 AvroError::ParseError(format!("UUID bytes are not valid UTF-8: {e}"))
1355 })?;
1356 let uuid = Uuid::try_parse(s)
1357 .map_err(|e| AvroError::ParseError(format!("Failed to parse uuid: {e}")))?;
1358 values.extend_from_slice(uuid.as_bytes());
1359 }
1360 Self::Array(_, off, encoding) => {
1361 let total_items = read_blocks(buf, |cursor| encoding.decode(cursor))?;
1362 off.push_length(total_items);
1363 }
1364 Self::Record {
1365 decoders,
1366 projector: None,
1367 row_count,
1368 ..
1369 } => {
1370 for encoding in decoders {
1371 encoding.decode(buf)?;
1372 }
1373 *row_count += 1;
1374 }
1375 Self::Record {
1376 decoders,
1377 projector: Some(proj),
1378 row_count,
1379 ..
1380 } => {
1381 proj.project_record(buf, decoders)?;
1382 *row_count += 1;
1383 }
1384 Self::Map(_, koff, moff, kdata, valdec) => {
1385 let newly_added = read_blocks(buf, |cur| {
1386 let kb = cur.get_bytes()?;
1387 koff.push_length(kb.len());
1388 kdata.extend_from_slice(kb);
1389 valdec.decode(cur)
1390 })?;
1391 moff.push_length(newly_added);
1392 }
1393 Self::Fixed(sz, accum) => {
1394 let fx = buf.get_fixed(*sz as usize)?;
1395 accum.extend_from_slice(fx);
1396 }
1397 #[cfg(feature = "small_decimals")]
1398 Self::Decimal32(_, _, size, builder) => {
1399 decode_decimal!(size, buf, builder, 4, i32);
1400 }
1401 #[cfg(feature = "small_decimals")]
1402 Self::Decimal64(_, _, size, builder) => {
1403 decode_decimal!(size, buf, builder, 8, i64);
1404 }
1405 Self::Decimal128(_, _, size, builder) => {
1406 decode_decimal!(size, buf, builder, 16, i128);
1407 }
1408 Self::Decimal256(_, _, size, builder) => {
1409 decode_decimal!(size, buf, builder, 32, i256);
1410 }
1411 Self::Enum(indices, _, None) => {
1412 indices.push(buf.get_int()?);
1413 }
1414 Self::Enum(indices, _, Some(res)) => {
1415 let raw = buf.get_int()?;
1416 let resolved = res.resolve(raw)?;
1417 indices.push(resolved);
1418 }
1419 Self::Duration(builder) => {
1420 let b = buf.get_fixed(12)?;
1421 let months = u32::from_le_bytes([b[0], b[1], b[2], b[3]]);
1422 let days = u32::from_le_bytes([b[4], b[5], b[6], b[7]]);
1423 let millis = u32::from_le_bytes([b[8], b[9], b[10], b[11]]);
1424 let nanos = (millis as i64) * 1_000_000;
1425 builder.append_value(IntervalMonthDayNano::new(months as i32, days as i32, nanos));
1426 }
1427 #[cfg(feature = "avro_custom_types")]
1428 Self::RunEndEncoded(_, len, inner) => {
1429 *len += 1;
1430 inner.decode(buf)?;
1431 }
1432 Self::Union(u) => u.decode(buf)?,
1433 Self::Nullable(nullable) => {
1434 let is_not_null = match &nullable.plan {
1435 NullablePlan::FromSingle { .. } => true,
1436 NullablePlan::ReadTag { nullability, .. } => {
1437 let branch = buf.read_vlq()?;
1438 match *nullability {
1439 Nullability::NullFirst => branch != 0,
1440 Nullability::NullSecond => branch == 0,
1441 }
1442 }
1443 };
1444
1445 if is_not_null {
1446 nullable.materialize_pending()?;
1447 let resolution = match &nullable.plan {
1448 NullablePlan::FromSingle { resolution }
1449 | NullablePlan::ReadTag { resolution, .. } => resolution,
1450 };
1451 nullable.values.decode_with_resolution(buf, resolution)?;
1453 nullable.validity.append_non_null();
1454 } else {
1455 nullable.pending_nulls += 1;
1456 }
1457 }
1458 }
1459 Ok(())
1460 }
1461
1462 fn decode_with_promotion(
1463 &mut self,
1464 buf: &mut AvroCursor<'_>,
1465 promotion: Promotion,
1466 ) -> Result<(), AvroError> {
1467 #[cfg(feature = "avro_custom_types")]
1468 if let Self::RunEndEncoded(_, len, inner) = self {
1469 *len += 1;
1470 return inner.decode_with_promotion(buf, promotion);
1471 }
1472
1473 macro_rules! promote_numeric_to {
1474 ($variant:ident, $getter:ident, $to:ty) => {{
1475 match self {
1476 Self::$variant(v) => {
1477 let x = buf.$getter()?;
1478 v.push(x as $to);
1479 Ok(())
1480 }
1481 other => Err(AvroError::ParseError(format!(
1482 "Promotion {promotion} target mismatch: expected {}, got {}",
1483 stringify!($variant),
1484 <Self as ::std::convert::AsRef<str>>::as_ref(other)
1485 ))),
1486 }
1487 }};
1488 }
1489 match promotion {
1490 Promotion::Direct => self.decode(buf),
1491 Promotion::IntToLong => promote_numeric_to!(Int64, get_int, i64),
1492 Promotion::IntToFloat => promote_numeric_to!(Float32, get_int, f32),
1493 Promotion::IntToDouble => promote_numeric_to!(Float64, get_int, f64),
1494 Promotion::LongToFloat => promote_numeric_to!(Float32, get_long, f32),
1495 Promotion::LongToDouble => promote_numeric_to!(Float64, get_long, f64),
1496 Promotion::FloatToDouble => promote_numeric_to!(Float64, get_float, f64),
1497 Promotion::StringToBytes => match self {
1498 Self::Binary(offsets, values) | Self::StringToBytes(offsets, values) => {
1499 let data = buf.get_bytes()?;
1500 offsets.push_length(data.len());
1501 values.extend_from_slice(data);
1502 Ok(())
1503 }
1504 other => Err(AvroError::ParseError(format!(
1505 "Promotion {promotion} target mismatch: expected bytes (Binary/StringToBytes), got {}",
1506 <Self as AsRef<str>>::as_ref(other)
1507 ))),
1508 },
1509 Promotion::BytesToString => match self {
1510 Self::String(offsets, values)
1511 | Self::StringView(offsets, values)
1512 | Self::BytesToString(offsets, values) => {
1513 let data = buf.get_bytes()?;
1514 offsets.push_length(data.len());
1515 values.extend_from_slice(data);
1516 Ok(())
1517 }
1518 other => Err(AvroError::ParseError(format!(
1519 "Promotion {promotion} target mismatch: expected string (String/StringView/BytesToString), got {}",
1520 <Self as AsRef<str>>::as_ref(other)
1521 ))),
1522 },
1523 }
1524 }
1525
1526 fn decode_with_resolution<'d>(
1527 &'d mut self,
1528 buf: &mut AvroCursor<'_>,
1529 resolution: &'d ResolutionPlan,
1530 ) -> Result<(), AvroError> {
1531 #[cfg(feature = "avro_custom_types")]
1532 if let Self::RunEndEncoded(_, len, inner) = self {
1533 *len += 1;
1534 return inner.decode_with_resolution(buf, resolution);
1535 }
1536
1537 match resolution {
1538 ResolutionPlan::Promotion(promotion) => {
1539 let promotion = *promotion;
1540 self.decode_with_promotion(buf, promotion)
1541 }
1542 ResolutionPlan::DefaultValue(lit) => self.append_default(lit),
1543 ResolutionPlan::EnumMapping(res) => {
1544 let Self::Enum(indices, _, _) = self else {
1545 return Err(AvroError::SchemaError(
1546 "enum mapping resolution provided for non-enum decoder".into(),
1547 ));
1548 };
1549 let raw = buf.get_int()?;
1550 let resolved = res.resolve(raw)?;
1551 indices.push(resolved);
1552 Ok(())
1553 }
1554 ResolutionPlan::Record(proj) => {
1555 let Self::Record {
1556 decoders,
1557 row_count,
1558 ..
1559 } = self
1560 else {
1561 return Err(AvroError::SchemaError(
1562 "record projection provided for non-record decoder".into(),
1563 ));
1564 };
1565 proj.project_record(buf, decoders)?;
1566 *row_count += 1;
1567 Ok(())
1568 }
1569 }
1570 }
1571
1572 fn flush(&mut self, nulls: Option<NullBuffer>) -> Result<ArrayRef, AvroError> {
1574 Ok(match self {
1575 Self::Nullable(nullable) => {
1576 nullable.materialize_pending()?;
1577 nullable.values.flush(nullable.validity.finish())?
1578 }
1579 Self::Null(size) => Arc::new(NullArray::new(std::mem::replace(size, 0))),
1580 Self::Boolean(b) => Arc::new(BooleanArray::new(b.finish(), nulls)),
1581 Self::Int32(values) => Arc::new(flush_primitive::<Int32Type>(values, nulls)),
1582 Self::Date32(values) => Arc::new(flush_primitive::<Date32Type>(values, nulls)),
1583 Self::Int64(values) => Arc::new(flush_primitive::<Int64Type>(values, nulls)),
1584 Self::TimeMillis(values) => {
1585 Arc::new(flush_primitive::<Time32MillisecondType>(values, nulls))
1586 }
1587 Self::TimeMicros(values) => {
1588 Arc::new(flush_primitive::<Time64MicrosecondType>(values, nulls))
1589 }
1590 Self::TimestampMillis(tz, values) => Arc::new(
1591 flush_primitive::<TimestampMillisecondType>(values, nulls)
1592 .with_timezone_opt(tz.as_ref().map(|tz| tz.to_string())),
1593 ),
1594 Self::TimestampMicros(tz, values) => Arc::new(
1595 flush_primitive::<TimestampMicrosecondType>(values, nulls)
1596 .with_timezone_opt(tz.as_ref().map(|tz| tz.to_string())),
1597 ),
1598 Self::TimestampNanos(tz, values) => Arc::new(
1599 flush_primitive::<TimestampNanosecondType>(values, nulls)
1600 .with_timezone_opt(tz.as_ref().map(|tz| tz.to_string())),
1601 ),
1602 #[cfg(feature = "avro_custom_types")]
1603 Self::DurationSecond(values) => {
1604 Arc::new(flush_primitive::<DurationSecondType>(values, nulls))
1605 }
1606 #[cfg(feature = "avro_custom_types")]
1607 Self::DurationMillisecond(values) => {
1608 Arc::new(flush_primitive::<DurationMillisecondType>(values, nulls))
1609 }
1610 #[cfg(feature = "avro_custom_types")]
1611 Self::DurationMicrosecond(values) => {
1612 Arc::new(flush_primitive::<DurationMicrosecondType>(values, nulls))
1613 }
1614 #[cfg(feature = "avro_custom_types")]
1615 Self::DurationNanosecond(values) => {
1616 Arc::new(flush_primitive::<DurationNanosecondType>(values, nulls))
1617 }
1618 #[cfg(feature = "avro_custom_types")]
1619 Self::Int8(values) => Arc::new(flush_primitive::<Int8Type>(values, nulls)),
1620 #[cfg(feature = "avro_custom_types")]
1621 Self::Int16(values) => Arc::new(flush_primitive::<Int16Type>(values, nulls)),
1622 #[cfg(feature = "avro_custom_types")]
1623 Self::UInt8(values) => Arc::new(flush_primitive::<UInt8Type>(values, nulls)),
1624 #[cfg(feature = "avro_custom_types")]
1625 Self::UInt16(values) => Arc::new(flush_primitive::<UInt16Type>(values, nulls)),
1626 #[cfg(feature = "avro_custom_types")]
1627 Self::UInt32(values) => Arc::new(flush_primitive::<UInt32Type>(values, nulls)),
1628 #[cfg(feature = "avro_custom_types")]
1629 Self::UInt64(values) => Arc::new(flush_primitive::<UInt64Type>(values, nulls)),
1630 #[cfg(feature = "avro_custom_types")]
1631 Self::Float16(values) => {
1632 let len = values.len();
1635 let buf: Buffer = std::mem::take(values).into();
1636 let scalar_buf = ScalarBuffer::new(buf, 0, len);
1637 Arc::new(Float16Array::new(scalar_buf, nulls))
1638 }
1639 #[cfg(feature = "avro_custom_types")]
1640 Self::Date64(values) => Arc::new(flush_primitive::<Date64Type>(values, nulls)),
1641 #[cfg(feature = "avro_custom_types")]
1642 Self::TimeNanos(values) => {
1643 Arc::new(flush_primitive::<Time64NanosecondType>(values, nulls))
1644 }
1645 #[cfg(feature = "avro_custom_types")]
1646 Self::Time32Secs(values) => {
1647 Arc::new(flush_primitive::<Time32SecondType>(values, nulls))
1648 }
1649 #[cfg(feature = "avro_custom_types")]
1650 Self::TimestampSecs(is_utc, values) => Arc::new(
1651 flush_primitive::<TimestampSecondType>(values, nulls)
1652 .with_timezone_opt(is_utc.then(|| "+00:00")),
1653 ),
1654 #[cfg(feature = "avro_custom_types")]
1655 Self::IntervalYearMonth(values) => {
1656 Arc::new(flush_primitive::<IntervalYearMonthType>(values, nulls))
1657 }
1658 #[cfg(feature = "avro_custom_types")]
1659 Self::IntervalMonthDayNano(values) => {
1660 Arc::new(flush_primitive::<IntervalMonthDayNanoType>(values, nulls))
1661 }
1662 #[cfg(feature = "avro_custom_types")]
1663 Self::IntervalDayTime(values) => {
1664 Arc::new(flush_primitive::<IntervalDayTimeType>(values, nulls))
1665 }
1666 Self::Float32(values) => Arc::new(flush_primitive::<Float32Type>(values, nulls)),
1667 Self::Float64(values) => Arc::new(flush_primitive::<Float64Type>(values, nulls)),
1668 Self::Int32ToInt64(values) => Arc::new(flush_primitive::<Int64Type>(values, nulls)),
1669 Self::Int32ToFloat32(values) | Self::Int64ToFloat32(values) => {
1670 Arc::new(flush_primitive::<Float32Type>(values, nulls))
1671 }
1672 Self::Int32ToFloat64(values)
1673 | Self::Int64ToFloat64(values)
1674 | Self::Float32ToFloat64(values) => {
1675 Arc::new(flush_primitive::<Float64Type>(values, nulls))
1676 }
1677 Self::StringToBytes(offsets, values) | Self::Binary(offsets, values) => {
1678 let offsets = flush_offsets(offsets);
1679 let values = flush_values(values).into();
1680 Arc::new(BinaryArray::try_new(offsets, values, nulls)?)
1681 }
1682 Self::BytesToString(offsets, values) | Self::String(offsets, values) => {
1683 let offsets = flush_offsets(offsets);
1684 let values = flush_values(values).into();
1685 Arc::new(StringArray::try_new(offsets, values, nulls)?)
1686 }
1687 Self::StringView(offsets, values) => {
1688 let offsets = flush_offsets(offsets);
1689 let values = flush_values(values);
1690 let array = StringArray::try_new(offsets, values.into(), nulls.clone())?;
1691 let values: Vec<&str> = (0..array.len())
1692 .map(|i| {
1693 if array.is_valid(i) {
1694 array.value(i)
1695 } else {
1696 ""
1697 }
1698 })
1699 .collect();
1700 Arc::new(StringViewArray::from(values))
1701 }
1702 Self::Array(field, offsets, values) => {
1703 let values = values.flush(None)?;
1704 let offsets = flush_offsets(offsets);
1705 Arc::new(ListArray::try_new(field.clone(), offsets, values, nulls)?)
1706 }
1707 Self::Record {
1708 fields,
1709 decoders,
1710 row_count,
1711 ..
1712 } => {
1713 let arrays = decoders
1714 .iter_mut()
1715 .map(|x| x.flush(None))
1716 .collect::<Result<Vec<_>, _>>()?;
1717 Arc::new(StructArray::try_new_with_length(
1720 fields.clone(),
1721 arrays,
1722 nulls,
1723 std::mem::replace(row_count, 0),
1724 )?)
1725 }
1726 Self::Map(map_field, k_off, m_off, kdata, valdec) => {
1727 let moff = flush_offsets(m_off);
1728 let koff = flush_offsets(k_off);
1729 let kd = flush_values(kdata).into();
1730 let val_arr = valdec.flush(None)?;
1731 let key_arr = StringArray::try_new(koff, kd, None)?;
1732 if key_arr.len() != val_arr.len() {
1733 return Err(AvroError::InvalidArgument(format!(
1734 "Map keys length ({}) != map values length ({})",
1735 key_arr.len(),
1736 val_arr.len()
1737 )));
1738 }
1739 let final_len = moff.len() - 1;
1740 if let Some(n) = &nulls
1741 && n.len() != final_len
1742 {
1743 return Err(AvroError::InvalidArgument(format!(
1744 "Map array null buffer length {} != final map length {final_len}",
1745 n.len()
1746 )));
1747 }
1748 let entries_fields = match map_field.data_type() {
1749 DataType::Struct(fields) => fields.clone(),
1750 other => {
1751 return Err(AvroError::InvalidArgument(format!(
1752 "Map entries field must be a Struct, got {other:?}"
1753 )));
1754 }
1755 };
1756 let entries_struct =
1757 StructArray::try_new(entries_fields, vec![Arc::new(key_arr), val_arr], None)?;
1758 let map_arr =
1759 MapArray::try_new(map_field.clone(), moff, entries_struct, nulls, false)?;
1760 Arc::new(map_arr)
1761 }
1762 Self::Fixed(sz, accum) => {
1763 let b: Buffer = flush_values(accum).into();
1764 let arr = FixedSizeBinaryArray::try_new(*sz, b, nulls)
1765 .map_err(|e| AvroError::ParseError(e.to_string()))?;
1766 Arc::new(arr)
1767 }
1768 Self::Uuid(values) => {
1769 let arr = FixedSizeBinaryArray::try_new(16, std::mem::take(values).into(), nulls)
1770 .map_err(|e| AvroError::ParseError(e.to_string()))?;
1771 Arc::new(arr)
1772 }
1773 #[cfg(feature = "small_decimals")]
1774 Self::Decimal32(precision, scale, _, builder) => {
1775 flush_decimal!(builder, precision, scale, nulls, Decimal32Array)
1776 }
1777 #[cfg(feature = "small_decimals")]
1778 Self::Decimal64(precision, scale, _, builder) => {
1779 flush_decimal!(builder, precision, scale, nulls, Decimal64Array)
1780 }
1781 Self::Decimal128(precision, scale, _, builder) => {
1782 flush_decimal!(builder, precision, scale, nulls, Decimal128Array)
1783 }
1784 Self::Decimal256(precision, scale, _, builder) => {
1785 flush_decimal!(builder, precision, scale, nulls, Decimal256Array)
1786 }
1787 Self::Enum(indices, symbols, _) => flush_dict(indices, symbols, nulls)?,
1788 Self::Duration(builder) => {
1789 let (_, vals, _) = builder.finish().into_parts();
1790 let vals = IntervalMonthDayNanoArray::try_new(vals, nulls)
1791 .map_err(|e| AvroError::ParseError(e.to_string()))?;
1792 Arc::new(vals)
1793 }
1794 #[cfg(feature = "avro_custom_types")]
1795 Self::RunEndEncoded(width, len, inner) => {
1796 let values = inner.flush(nulls)?;
1797 let n = *len;
1798 let arr = values.as_ref();
1799 let mut run_starts: Vec<usize> = Vec::with_capacity(n);
1800 if n > 0 {
1801 run_starts.push(0);
1802 for i in 1..n {
1803 if !values_equal_at(arr, i - 1, i) {
1804 run_starts.push(i);
1805 }
1806 }
1807 }
1808 if n > (u32::MAX as usize) {
1809 return Err(AvroError::InvalidArgument(format!(
1810 "RunEndEncoded length {n} exceeds maximum supported by UInt32 indices for take",
1811 )));
1812 }
1813 let run_count = run_starts.len();
1814 let take_idx: PrimitiveArray<UInt32Type> =
1815 run_starts.iter().map(|&s| s as u32).collect();
1816 let per_run_values = if run_count == 0 {
1817 values.slice(0, 0)
1818 } else {
1819 take(arr, &take_idx, Option::from(TakeOptions::default())).map_err(|e| {
1820 AvroError::ParseError(format!("take() for REE values failed: {e}"))
1821 })?
1822 };
1823
1824 macro_rules! build_run_array {
1825 ($Native:ty, $ArrowTy:ty) => {{
1826 let mut ends: Vec<$Native> = Vec::with_capacity(run_count);
1827 for (idx, &_start) in run_starts.iter().enumerate() {
1828 let end = if idx + 1 < run_count {
1829 run_starts[idx + 1]
1830 } else {
1831 n
1832 };
1833 ends.push(end as $Native);
1834 }
1835 let ends: PrimitiveArray<$ArrowTy> = ends.into_iter().collect();
1836 let run_arr = RunArray::<$ArrowTy>::try_new(&ends, per_run_values.as_ref())
1837 .map_err(|e| AvroError::ParseError(e.to_string()))?;
1838 Arc::new(run_arr) as ArrayRef
1839 }};
1840 }
1841 match *width {
1842 2 => {
1843 if n > i16::MAX as usize {
1844 return Err(AvroError::InvalidArgument(format!(
1845 "RunEndEncoded length {n} exceeds i16::MAX for run end width 2"
1846 )));
1847 }
1848 build_run_array!(i16, Int16Type)
1849 }
1850 4 => build_run_array!(i32, Int32Type),
1851 8 => build_run_array!(i64, Int64Type),
1852 other => {
1853 return Err(AvroError::InvalidArgument(format!(
1854 "Unsupported run-end width {other} for RunEndEncoded"
1855 )));
1856 }
1857 }
1858 }
1859 Self::Union(u) => u.flush(nulls)?,
1860 })
1861 }
1862}
1863
1864#[derive(Debug)]
1866enum NullablePlan {
1867 ReadTag {
1869 nullability: Nullability,
1870 resolution: ResolutionPlan,
1871 },
1872 FromSingle { resolution: ResolutionPlan },
1875}
1876
1877#[derive(Debug)]
1879enum ResolutionPlan {
1880 Promotion(Promotion),
1882 DefaultValue(AvroLiteral),
1884 EnumMapping(EnumResolution),
1886 Record(Projector),
1888}
1889
1890impl ResolutionPlan {
1891 fn try_new(decoder: &Decoder, resolution: &ResolutionInfo) -> Result<Self, AvroError> {
1892 match (decoder, resolution) {
1893 (_, ResolutionInfo::Promotion(p)) => Ok(ResolutionPlan::Promotion(*p)),
1894 (_, ResolutionInfo::DefaultValue(lit)) => Ok(ResolutionPlan::DefaultValue(lit.clone())),
1895 (_, ResolutionInfo::EnumMapping(m)) => {
1896 Ok(ResolutionPlan::EnumMapping(EnumResolution::new(m)))
1897 }
1898 (
1899 Decoder::Record {
1900 defaults: field_defaults,
1901 ..
1902 },
1903 ResolutionInfo::Record(r),
1904 ) => Ok(ResolutionPlan::Record(
1905 ProjectorBuilder::try_new(r, field_defaults).build()?,
1906 )),
1907 (_, ResolutionInfo::Record(_)) => Err(AvroError::SchemaError(
1908 "record resolution on non-record decoder".into(),
1909 )),
1910 (_, ResolutionInfo::Union(_)) => Err(AvroError::SchemaError(
1911 "union variant cannot be resolved to a union type".into(),
1912 )),
1913 }
1914 }
1915}
1916
1917#[derive(Debug)]
1918struct EnumResolution {
1919 mapping: Arc<[i32]>,
1920 default_index: i32,
1921}
1922
1923impl EnumResolution {
1924 fn new(mapping: &EnumMapping) -> Self {
1925 EnumResolution {
1926 mapping: mapping.mapping.clone(),
1927 default_index: mapping.default_index,
1928 }
1929 }
1930
1931 fn resolve(&self, index: i32) -> Result<i32, AvroError> {
1932 let resolved = usize::try_from(index)
1933 .ok()
1934 .and_then(|idx| self.mapping.get(idx).copied())
1935 .filter(|&idx| idx >= 0)
1936 .unwrap_or(self.default_index);
1937 if resolved >= 0 {
1938 Ok(resolved)
1939 } else {
1940 Err(AvroError::ParseError(format!(
1941 "Enum symbol index {index} not resolvable and no default provided",
1942 )))
1943 }
1944 }
1945}
1946
1947#[derive(Debug)]
1949struct DispatchLookupTable {
1950 to_reader: Box<[i8]>,
1966 resolution: Box<[ResolutionPlan]>,
1971}
1972
1973const NO_SOURCE: i8 = -1;
1976
1977impl DispatchLookupTable {
1978 fn from_writer_to_reader(
1979 reader_branches: &[Decoder],
1980 resolution_map: &[Option<(usize, ResolutionInfo)>],
1981 ) -> Result<Self, AvroError> {
1982 let mut to_reader = Vec::with_capacity(resolution_map.len());
1983 let mut resolution = Vec::with_capacity(resolution_map.len());
1984 for map in resolution_map {
1985 match map {
1986 Some((idx, res)) => {
1987 let idx = *idx;
1988 let idx_i8 = i8::try_from(idx).map_err(|_| {
1989 AvroError::SchemaError(format!(
1990 "Reader branch index {idx} exceeds i8 range (max {})",
1991 i8::MAX
1992 ))
1993 })?;
1994 let plan = ResolutionPlan::try_new(&reader_branches[idx], res)?;
1995 to_reader.push(idx_i8);
1996 resolution.push(plan);
1997 }
1998 None => {
1999 to_reader.push(NO_SOURCE);
2000 resolution.push(ResolutionPlan::DefaultValue(AvroLiteral::Null));
2001 }
2002 }
2003 }
2004 Ok(Self {
2005 to_reader: to_reader.into_boxed_slice(),
2006 resolution: resolution.into_boxed_slice(),
2007 })
2008 }
2009
2010 #[inline]
2012 fn resolve(&self, writer_index: usize) -> Option<(usize, &ResolutionPlan)> {
2013 let reader_index = *self.to_reader.get(writer_index)?;
2014 (reader_index >= 0).then(|| (reader_index as usize, &self.resolution[writer_index]))
2015 }
2016}
2017
2018#[derive(Debug)]
2019struct UnionDecoder {
2020 fields: UnionFields,
2021 branches: UnionDecoderBranches,
2022 default_emit_idx: usize,
2023 null_emit_idx: usize,
2024 plan: UnionReadPlan,
2025}
2026
2027#[derive(Debug, Default)]
2028struct UnionDecoderBranches {
2029 decoders: Vec<Decoder>,
2030 reader_type_codes: Vec<i8>,
2031 type_ids: Vec<i8>,
2032 offsets: Vec<i32>,
2033 counts: Vec<i32>,
2034}
2035
2036impl UnionDecoderBranches {
2037 fn new(decoders: Vec<Decoder>, reader_type_codes: Vec<i8>) -> Self {
2038 let branch_len = decoders.len().max(reader_type_codes.len());
2039 Self {
2040 decoders,
2041 reader_type_codes,
2042 type_ids: Vec::with_capacity(DEFAULT_CAPACITY),
2043 offsets: Vec::with_capacity(DEFAULT_CAPACITY),
2044 counts: vec![0; branch_len],
2045 }
2046 }
2047
2048 fn emit_to(&mut self, reader_idx: usize) -> Result<&mut Decoder, AvroError> {
2049 let branches_len = self.decoders.len();
2050 let Some(reader_branch) = self.decoders.get_mut(reader_idx) else {
2051 return Err(AvroError::ParseError(format!(
2052 "Union branch index {reader_idx} out of range ({branches_len} branches)"
2053 )));
2054 };
2055 self.type_ids.push(self.reader_type_codes[reader_idx]);
2056 self.offsets.push(self.counts[reader_idx]);
2057 self.counts[reader_idx] += 1;
2058 Ok(reader_branch)
2059 }
2060}
2061
2062impl Default for UnionDecoder {
2063 fn default() -> Self {
2064 Self {
2065 fields: UnionFields::empty(),
2066 branches: Default::default(),
2067 default_emit_idx: 0,
2068 null_emit_idx: 0,
2069 plan: UnionReadPlan::Passthrough,
2070 }
2071 }
2072}
2073
2074#[derive(Debug)]
2075enum UnionReadPlan {
2076 ReaderUnion {
2077 lookup_table: DispatchLookupTable,
2078 },
2079 FromSingle {
2080 reader_idx: usize,
2081 resolution: ResolutionPlan,
2082 },
2083 ToSingle {
2084 target: Box<Decoder>,
2085 lookup_table: DispatchLookupTable,
2086 },
2087 Passthrough,
2088}
2089
2090impl UnionReadPlan {
2091 fn from_resolved(
2092 reader_branches: &[Decoder],
2093 resolved: Option<ResolvedUnion>,
2094 ) -> Result<Self, AvroError> {
2095 let Some(info) = resolved else {
2096 return Ok(Self::Passthrough);
2097 };
2098 match (info.writer_is_union, info.reader_is_union) {
2099 (true, true) => {
2100 let lookup_table =
2101 DispatchLookupTable::from_writer_to_reader(reader_branches, &info.writer_to_reader)?;
2102 Ok(Self::ReaderUnion { lookup_table })
2103 }
2104 (false, true) => {
2105 let Some((idx, resolution)) =
2106 info.writer_to_reader.first().and_then(Option::as_ref)
2107 else {
2108 return Err(AvroError::SchemaError(
2109 "Writer type does not match any reader union branch".to_string(),
2110 ));
2111 };
2112 let reader_idx = *idx;
2113 Ok(Self::FromSingle {
2114 reader_idx,
2115 resolution: ResolutionPlan::try_new(&reader_branches[reader_idx], resolution)?,
2116 })
2117 }
2118 (true, false) => Err(AvroError::InvalidArgument(
2119 "UnionDecoder::try_new cannot build writer-union to single; use UnionDecoderBuilder with a target"
2120 .to_string(),
2121 )),
2122 _ => Err(AvroError::SchemaError(
2124 "ResolvedUnion constructed for non-union sides; resolver should return None"
2125 .to_string(),
2126 )),
2127 }
2128 }
2129}
2130
2131impl UnionDecoder {
2132 fn try_new(
2133 fields: UnionFields,
2134 branches: Vec<Decoder>,
2135 resolved: Option<ResolvedUnion>,
2136 ) -> Result<Self, AvroError> {
2137 let reader_type_codes = fields.iter().map(|(tid, _)| tid).collect::<Vec<i8>>();
2138 let null_branch = branches.iter().position(|b| matches!(b, Decoder::Null(_)));
2139 let default_emit_idx = 0;
2140 let null_emit_idx = null_branch.unwrap_or(default_emit_idx);
2141 let max_addr = (i32::MAX as usize) + 1;
2143 if branches.len() > max_addr {
2144 return Err(AvroError::SchemaError(format!(
2145 "Reader union has {} branches, which exceeds the maximum addressable \
2146 branches by an Avro int tag ({} + 1).",
2147 branches.len(),
2148 i32::MAX
2149 )));
2150 }
2151 let plan = UnionReadPlan::from_resolved(&branches, resolved)?;
2152 Ok(Self {
2153 fields,
2154 branches: UnionDecoderBranches::new(branches, reader_type_codes),
2155 default_emit_idx,
2156 null_emit_idx,
2157 plan,
2158 })
2159 }
2160
2161 fn with_single_target(target: Decoder, info: ResolvedUnion) -> Result<Self, AvroError> {
2162 debug_assert!(info.writer_is_union && !info.reader_is_union);
2164 let mut reader_branches = [target];
2165 let lookup_table =
2166 DispatchLookupTable::from_writer_to_reader(&reader_branches, &info.writer_to_reader)?;
2167 let target = Box::new(mem::replace(&mut reader_branches[0], Decoder::Null(0)));
2168 Ok(Self {
2169 plan: UnionReadPlan::ToSingle {
2170 target,
2171 lookup_table,
2172 },
2173 ..Self::default()
2174 })
2175 }
2176
2177 #[inline]
2178 fn read_tag(buf: &mut AvroCursor<'_>) -> Result<usize, AvroError> {
2179 let raw = buf.get_long()?;
2184 if raw < 0 {
2185 return Err(AvroError::ParseError(format!(
2186 "Negative union branch index {raw}"
2187 )));
2188 }
2189 usize::try_from(raw).map_err(|_| {
2190 AvroError::ParseError(format!(
2191 "Union branch index {raw} does not fit into usize on this platform ({}-bit)",
2192 (usize::BITS as usize)
2193 ))
2194 })
2195 }
2196
2197 #[inline]
2198 fn on_decoder<F>(&mut self, fallback_idx: usize, action: F) -> Result<(), AvroError>
2199 where
2200 F: FnOnce(&mut Decoder) -> Result<(), AvroError>,
2201 {
2202 if let UnionReadPlan::ToSingle { target, .. } = &mut self.plan {
2203 return action(target);
2204 }
2205 let reader_idx = match &self.plan {
2206 UnionReadPlan::FromSingle { reader_idx, .. } => *reader_idx,
2207 _ => fallback_idx,
2208 };
2209 self.branches.emit_to(reader_idx).and_then(action)
2210 }
2211
2212 fn append_null(&mut self) -> Result<(), AvroError> {
2213 self.on_decoder(self.null_emit_idx, |decoder| decoder.append_null())
2214 }
2215
2216 fn append_default(&mut self, lit: &AvroLiteral) -> Result<(), AvroError> {
2217 self.on_decoder(self.default_emit_idx, |decoder| decoder.append_default(lit))
2218 }
2219
2220 fn decode(&mut self, buf: &mut AvroCursor<'_>) -> Result<(), AvroError> {
2221 match &mut self.plan {
2222 UnionReadPlan::Passthrough => {
2223 let reader_idx = Self::read_tag(buf)?;
2224 let decoder = self.branches.emit_to(reader_idx)?;
2225 decoder.decode(buf)
2226 }
2227 UnionReadPlan::ReaderUnion { lookup_table } => {
2228 let idx = Self::read_tag(buf)?;
2229 let Some((reader_idx, resolution)) = lookup_table.resolve(idx) else {
2230 return Err(AvroError::ParseError(format!(
2231 "Union branch index {idx} not resolvable by reader schema"
2232 )));
2233 };
2234 let decoder = self.branches.emit_to(reader_idx)?;
2235 decoder.decode_with_resolution(buf, resolution)
2236 }
2237 UnionReadPlan::FromSingle {
2238 reader_idx,
2239 resolution,
2240 } => {
2241 let decoder = self.branches.emit_to(*reader_idx)?;
2242 decoder.decode_with_resolution(buf, resolution)
2243 }
2244 UnionReadPlan::ToSingle {
2245 target,
2246 lookup_table,
2247 } => {
2248 let idx = Self::read_tag(buf)?;
2249 let Some((_, resolution)) = lookup_table.resolve(idx) else {
2250 return Err(AvroError::ParseError(format!(
2251 "Writer union branch index {idx} not resolvable by reader schema"
2252 )));
2253 };
2254 target.decode_with_resolution(buf, resolution)
2255 }
2256 }
2257 }
2258
2259 fn flush(&mut self, nulls: Option<NullBuffer>) -> Result<ArrayRef, AvroError> {
2260 if let UnionReadPlan::ToSingle { target, .. } = &mut self.plan {
2261 return target.flush(nulls);
2262 }
2263 debug_assert!(
2264 nulls.is_none(),
2265 "UnionArray does not accept a validity bitmap; \
2266 nulls should have been materialized as a Null child during decode"
2267 );
2268 let children = self
2269 .branches
2270 .decoders
2271 .iter_mut()
2272 .map(|d| d.flush(None))
2273 .collect::<Result<Vec<_>, _>>()?;
2274 let arr = UnionArray::try_new(
2275 self.fields.clone(),
2276 flush_values(&mut self.branches.type_ids)
2277 .into_iter()
2278 .collect(),
2279 Some(
2280 flush_values(&mut self.branches.offsets)
2281 .into_iter()
2282 .collect(),
2283 ),
2284 children,
2285 )
2286 .map_err(|e| AvroError::ParseError(e.to_string()))?;
2287 self.branches.counts.fill(0);
2288 Ok(Arc::new(arr))
2289 }
2290}
2291
2292#[derive(Debug, Default)]
2293struct UnionDecoderBuilder {
2294 fields: Option<UnionFields>,
2295 branches: Option<Vec<Decoder>>,
2296 resolved: Option<ResolvedUnion>,
2297 target: Option<Decoder>,
2298}
2299
2300impl UnionDecoderBuilder {
2301 fn new() -> Self {
2302 Self::default()
2303 }
2304
2305 fn with_fields(mut self, fields: UnionFields) -> Self {
2306 self.fields = Some(fields);
2307 self
2308 }
2309
2310 fn with_branches(mut self, branches: Vec<Decoder>) -> Self {
2311 self.branches = Some(branches);
2312 self
2313 }
2314
2315 fn with_resolved_union(mut self, resolved_union: ResolvedUnion) -> Self {
2316 self.resolved = Some(resolved_union);
2317 self
2318 }
2319
2320 fn with_target(mut self, target: Decoder) -> Self {
2321 self.target = Some(target);
2322 self
2323 }
2324
2325 fn build(self) -> Result<UnionDecoder, AvroError> {
2326 match (self.resolved, self.fields, self.branches, self.target) {
2327 (resolved, Some(fields), Some(branches), None) => {
2328 UnionDecoder::try_new(fields, branches, resolved)
2329 }
2330 (Some(info), None, None, Some(target))
2331 if info.writer_is_union && !info.reader_is_union =>
2332 {
2333 UnionDecoder::with_single_target(target, info)
2334 }
2335 _ => Err(AvroError::InvalidArgument(
2336 "Invalid UnionDecoderBuilder configuration: expected either \
2337 (fields + branches + resolved) with no target for reader-unions, or \
2338 (resolved + target) with no fields/branches for writer-union to single."
2339 .to_string(),
2340 )),
2341 }
2342 }
2343}
2344
2345#[derive(Debug, Copy, Clone)]
2346enum NegativeBlockBehavior {
2347 ProcessItems,
2348 SkipBySize,
2349}
2350
2351#[inline]
2352fn skip_blocks(
2353 buf: &mut AvroCursor,
2354 mut skip_item: impl FnMut(&mut AvroCursor) -> Result<(), AvroError>,
2355) -> Result<usize, AvroError> {
2356 process_blockwise(
2357 buf,
2358 move |c| skip_item(c),
2359 NegativeBlockBehavior::SkipBySize,
2360 )
2361}
2362
2363#[inline]
2364fn flush_dict(
2365 indices: &mut Vec<i32>,
2366 symbols: &[String],
2367 nulls: Option<NullBuffer>,
2368) -> Result<ArrayRef, AvroError> {
2369 let keys = flush_primitive::<Int32Type>(indices, nulls);
2370 let values = Arc::new(StringArray::from_iter_values(
2371 symbols.iter().map(|s| s.as_str()),
2372 ));
2373 DictionaryArray::try_new(keys, values)
2374 .map_err(Into::into)
2375 .map(|arr| Arc::new(arr) as ArrayRef)
2376}
2377
2378#[inline]
2379fn read_blocks(
2380 buf: &mut AvroCursor,
2381 decode_entry: impl FnMut(&mut AvroCursor) -> Result<(), AvroError>,
2382) -> Result<usize, AvroError> {
2383 process_blockwise(buf, decode_entry, NegativeBlockBehavior::ProcessItems)
2384}
2385
2386#[inline]
2387fn process_blockwise(
2388 buf: &mut AvroCursor,
2389 mut on_item: impl FnMut(&mut AvroCursor) -> Result<(), AvroError>,
2390 negative_behavior: NegativeBlockBehavior,
2391) -> Result<usize, AvroError> {
2392 let mut total = 0usize;
2393 loop {
2394 let block_count = buf.get_long()?;
2399 match block_count.cmp(&0) {
2400 Ordering::Equal => break,
2401 Ordering::Less => {
2402 let count = block_count.unsigned_abs() as usize;
2404 let raw_size = buf.get_long()?;
2406 let size_in_bytes = usize::try_from(raw_size).map_err(|_| {
2407 AvroError::ParseError(format!("Block size cannot be negative, got {raw_size}"))
2408 })?;
2409 match negative_behavior {
2410 NegativeBlockBehavior::ProcessItems => {
2411 total = process_block_items(buf, count, total, &mut on_item)?;
2413 }
2414 NegativeBlockBehavior::SkipBySize => {
2415 let _ = buf.get_fixed(size_in_bytes)?;
2417 total = total.saturating_add(count);
2418 }
2419 }
2420 }
2421 Ordering::Greater => {
2422 let count = block_count as usize;
2423 total = process_block_items(buf, count, total, &mut on_item)?;
2424 }
2425 }
2426 }
2427 Ok(total)
2428}
2429
2430#[inline]
2435fn process_block_items(
2436 buf: &mut AvroCursor,
2437 count: usize,
2438 total: usize,
2439 on_item: &mut impl FnMut(&mut AvroCursor) -> Result<(), AvroError>,
2440) -> Result<usize, AvroError> {
2441 let Some(new_total) = total
2442 .checked_add(count)
2443 .filter(|&t| i32::try_from(t).is_ok())
2444 else {
2445 return Err(AvroError::ParseError(
2446 "Capacity overflow when decoding array/map item blocks".to_string(),
2447 ));
2448 };
2449 for _ in 0..count {
2450 on_item(buf)?;
2451 }
2452 Ok(new_total)
2453}
2454
2455#[inline]
2456fn flush_values<T>(values: &mut Vec<T>) -> Vec<T> {
2457 std::mem::replace(values, Vec::with_capacity(DEFAULT_CAPACITY))
2458}
2459
2460#[inline]
2461fn flush_offsets(offsets: &mut OffsetBufferBuilder<i32>) -> OffsetBuffer<i32> {
2462 std::mem::replace(offsets, OffsetBufferBuilder::new(DEFAULT_CAPACITY)).finish()
2463}
2464
2465#[inline]
2466fn flush_primitive<T: ArrowPrimitiveType>(
2467 values: &mut Vec<T::Native>,
2468 nulls: Option<NullBuffer>,
2469) -> PrimitiveArray<T> {
2470 PrimitiveArray::new(flush_values(values).into(), nulls)
2471}
2472
2473#[inline]
2474fn read_decimal_bytes_be<const N: usize>(
2475 buf: &mut AvroCursor<'_>,
2476 size: Option<usize>,
2477) -> Result<[u8; N], AvroError> {
2478 match size {
2479 Some(n) if n == N => {
2480 let raw = buf.get_fixed(N)?;
2481 let mut arr = [0u8; N];
2482 arr.copy_from_slice(raw);
2483 Ok(arr)
2484 }
2485 Some(n) => {
2486 let raw = buf.get_fixed(n)?;
2487 sign_cast_to::<N>(raw)
2488 }
2489 None => {
2490 let raw = buf.get_bytes()?;
2491 sign_cast_to::<N>(raw)
2492 }
2493 }
2494}
2495
2496#[inline]
2505fn sign_cast_to<const N: usize>(raw: &[u8]) -> Result<[u8; N], AvroError> {
2506 let len = raw.len();
2507 if len == N {
2509 let mut out = [0u8; N];
2510 out.copy_from_slice(raw);
2511 return Ok(out);
2512 }
2513 let first = raw.first().copied().unwrap_or(0u8);
2515 let sign_byte = if (first & 0x80) == 0 { 0x00 } else { 0xFF };
2516 let mut out = [sign_byte; N];
2518 if len > N {
2519 let extra = len - N;
2522 if raw[..extra].iter().any(|&b| b != sign_byte) {
2524 return Err(AvroError::ParseError(format!(
2525 "Decimal value with {len} bytes cannot be represented in {N} bytes without overflow"
2526 )));
2527 }
2528 if N > 0 {
2529 let first_kept = raw[extra];
2530 let sign_bit_mismatch = ((first_kept ^ sign_byte) & 0x80) != 0;
2531 if sign_bit_mismatch {
2532 return Err(AvroError::ParseError(format!(
2533 "Decimal value with {len} bytes cannot be represented in {N} bytes without overflow"
2534 )));
2535 }
2536 }
2537 out.copy_from_slice(&raw[extra..]);
2538 return Ok(out);
2539 }
2540 out[N - len..].copy_from_slice(raw);
2541 Ok(out)
2542}
2543
2544#[cfg(feature = "avro_custom_types")]
2545#[inline]
2546fn values_equal_at(arr: &dyn Array, i: usize, j: usize) -> bool {
2547 match (arr.is_null(i), arr.is_null(j)) {
2548 (true, true) => true,
2549 (true, false) | (false, true) => false,
2550 (false, false) => {
2551 let a = arr.slice(i, 1);
2552 let b = arr.slice(j, 1);
2553 a == b
2554 }
2555 }
2556}
2557
2558#[derive(Debug)]
2559struct Projector {
2560 writer_projections: Vec<FieldProjection>,
2561 default_injections: Arc<[(usize, AvroLiteral)]>,
2562}
2563
2564#[derive(Debug)]
2565enum FieldProjection {
2566 ToReader(usize),
2567 Skip(Skipper),
2568}
2569
2570#[derive(Debug)]
2571struct ProjectorBuilder<'a> {
2572 rec: &'a ResolvedRecord,
2573 field_defaults: &'a [Option<AvroLiteral>],
2574}
2575
2576impl<'a> ProjectorBuilder<'a> {
2577 #[inline]
2578 fn try_new(rec: &'a ResolvedRecord, field_defaults: &'a [Option<AvroLiteral>]) -> Self {
2579 Self {
2580 rec,
2581 field_defaults,
2582 }
2583 }
2584
2585 #[inline]
2586 fn build(self) -> Result<Projector, AvroError> {
2587 let mut default_injections: Vec<(usize, AvroLiteral)> =
2588 Vec::with_capacity(self.rec.default_fields.len());
2589 for &idx in self.rec.default_fields.as_ref() {
2590 let lit = self
2591 .field_defaults
2592 .get(idx)
2593 .and_then(|lit| lit.clone())
2594 .unwrap_or(AvroLiteral::Null);
2595 default_injections.push((idx, lit));
2596 }
2597 let writer_projections = self
2598 .rec
2599 .writer_fields
2600 .iter()
2601 .map(|field| match field {
2602 ResolvedField::ToReader(index, _) => Ok(FieldProjection::ToReader(*index)),
2603 ResolvedField::Skip(datatype) => {
2604 let skipper = Skipper::from_avro(datatype)?;
2605 Ok(FieldProjection::Skip(skipper))
2606 }
2607 })
2608 .collect::<Result<_, AvroError>>()?;
2609 Ok(Projector {
2610 writer_projections,
2611 default_injections: default_injections.into(),
2612 })
2613 }
2614}
2615
2616impl Projector {
2617 #[inline]
2618 fn project_record(
2619 &self,
2620 buf: &mut AvroCursor<'_>,
2621 encodings: &mut [Decoder],
2622 ) -> Result<(), AvroError> {
2623 for field_proj in &self.writer_projections {
2624 match field_proj {
2625 FieldProjection::ToReader(index) => encodings[*index].decode(buf)?,
2626 FieldProjection::Skip(skipper) => skipper.skip(buf)?,
2627 }
2628 }
2629 for (reader_index, lit) in self.default_injections.as_ref() {
2630 encodings[*reader_index].append_default(lit)?;
2631 }
2632 Ok(())
2633 }
2634}
2635
2636#[derive(Debug)]
2642enum Skipper {
2643 Null,
2644 Boolean,
2645 Int32,
2646 Int64,
2647 Float32,
2648 Float64,
2649 Bytes,
2650 String,
2651 TimeMicros,
2652 TimestampMillis,
2653 TimestampMicros,
2654 TimestampNanos,
2655 Fixed(usize),
2656 Decimal(Option<usize>),
2657 UuidString,
2658 Enum,
2659 DurationFixed12,
2660 List(Box<Skipper>),
2661 Map(Box<Skipper>),
2662 Struct(Vec<Skipper>),
2663 Union(Vec<Skipper>),
2664 Nullable(Nullability, Box<Skipper>),
2665 #[cfg(feature = "avro_custom_types")]
2666 RunEndEncoded(Box<Skipper>),
2667}
2668
2669impl Skipper {
2670 fn from_avro(dt: &AvroDataType) -> Result<Self, AvroError> {
2671 let mut base = match dt.codec() {
2672 Codec::Null => Self::Null,
2673 Codec::Boolean => Self::Boolean,
2674 Codec::Int32 | Codec::Date32 | Codec::TimeMillis => Self::Int32,
2675 Codec::Int64 => Self::Int64,
2676 Codec::TimeMicros => Self::TimeMicros,
2677 Codec::TimestampMillis(_) => Self::TimestampMillis,
2678 Codec::TimestampMicros(_) => Self::TimestampMicros,
2679 Codec::TimestampNanos(_) => Self::TimestampNanos,
2680 #[cfg(feature = "avro_custom_types")]
2681 Codec::DurationNanos
2682 | Codec::DurationMicros
2683 | Codec::DurationMillis
2684 | Codec::DurationSeconds => Self::Int64,
2685 #[cfg(feature = "avro_custom_types")]
2686 Codec::Int8 | Codec::Int16 | Codec::UInt8 | Codec::UInt16 | Codec::Time32Secs => {
2687 Self::Int32
2688 }
2689 #[cfg(feature = "avro_custom_types")]
2690 Codec::UInt32 | Codec::Date64 | Codec::TimeNanos | Codec::TimestampSecs(_) => {
2691 Self::Int64
2692 }
2693 #[cfg(feature = "avro_custom_types")]
2694 Codec::UInt64 => Self::Fixed(8),
2695 #[cfg(feature = "avro_custom_types")]
2696 Codec::Float16 => Self::Fixed(2),
2697 #[cfg(feature = "avro_custom_types")]
2698 Codec::IntervalYearMonth => Self::Fixed(4),
2699 #[cfg(feature = "avro_custom_types")]
2700 Codec::IntervalMonthDayNano => Self::Fixed(16),
2701 #[cfg(feature = "avro_custom_types")]
2702 Codec::IntervalDayTime => Self::Fixed(8),
2703 Codec::Float32 => Self::Float32,
2704 Codec::Float64 => Self::Float64,
2705 Codec::Binary => Self::Bytes,
2706 Codec::Utf8 | Codec::Utf8View => Self::String,
2707 Codec::Fixed(sz) => Self::Fixed(*sz as usize),
2708 Codec::Decimal(_, _, size) => Self::Decimal(*size),
2709 Codec::Uuid => Self::UuidString, Codec::Enum(_) => Self::Enum,
2711 Codec::List(item) => Self::List(Box::new(Skipper::from_avro(item)?)),
2712 Codec::Struct(fields) => {
2713 if let Some(ResolutionInfo::Record(rec)) = dt.resolution.as_ref() {
2714 Self::Struct(
2715 rec.writer_fields
2716 .iter()
2717 .map(|wf| match wf {
2718 ResolvedField::ToReader(_, wdt) | ResolvedField::Skip(wdt) => {
2719 Skipper::from_avro(wdt)
2720 }
2721 })
2722 .collect::<Result<_, _>>()?,
2723 )
2724 } else {
2725 Self::Struct(
2726 fields
2727 .iter()
2728 .map(|f| Skipper::from_avro(f.data_type()))
2729 .collect::<Result<_, _>>()?,
2730 )
2731 }
2732 }
2733 Codec::Map(values) => Self::Map(Box::new(Skipper::from_avro(values)?)),
2734 Codec::Interval => Self::DurationFixed12,
2735 Codec::Union(encodings, _, _) => {
2736 let max_addr = (i32::MAX as usize) + 1;
2737 if encodings.len() > max_addr {
2738 return Err(AvroError::SchemaError(format!(
2739 "Writer union has {} branches, which exceeds the maximum addressable \
2740 branches by an Avro int tag ({} + 1).",
2741 encodings.len(),
2742 i32::MAX
2743 )));
2744 }
2745 Self::Union(
2746 encodings
2747 .iter()
2748 .map(Skipper::from_avro)
2749 .collect::<Result<_, _>>()?,
2750 )
2751 }
2752 #[cfg(feature = "avro_custom_types")]
2753 Codec::RunEndEncoded(inner, _w) => {
2754 Self::RunEndEncoded(Box::new(Skipper::from_avro(inner)?))
2755 }
2756 };
2757 if let Some(n) = dt.nullability() {
2758 base = Self::Nullable(n, Box::new(base));
2759 }
2760 Ok(base)
2761 }
2762
2763 fn skip(&self, buf: &mut AvroCursor<'_>) -> Result<(), AvroError> {
2764 match self {
2765 Self::Null => Ok(()),
2766 Self::Boolean => {
2767 buf.get_bool()?;
2768 Ok(())
2769 }
2770 Self::Int32 => {
2771 buf.skip_int()?;
2772 Ok(())
2773 }
2774 Self::Int64
2775 | Self::TimeMicros
2776 | Self::TimestampMillis
2777 | Self::TimestampMicros
2778 | Self::TimestampNanos => {
2779 buf.skip_long()?;
2780 Ok(())
2781 }
2782 Self::Float32 => {
2783 buf.get_float()?;
2784 Ok(())
2785 }
2786 Self::Float64 => {
2787 buf.get_double()?;
2788 Ok(())
2789 }
2790 Self::Bytes | Self::String | Self::UuidString => {
2791 buf.get_bytes()?;
2792 Ok(())
2793 }
2794 Self::Fixed(sz) => {
2795 buf.get_fixed(*sz)?;
2796 Ok(())
2797 }
2798 Self::Decimal(size) => {
2799 if let Some(s) = size {
2800 buf.get_fixed(*s)
2801 } else {
2802 buf.get_bytes()
2803 }?;
2804 Ok(())
2805 }
2806 Self::Enum => {
2807 buf.skip_int()?;
2808 Ok(())
2809 }
2810 Self::DurationFixed12 => {
2811 buf.get_fixed(12)?;
2812 Ok(())
2813 }
2814 Self::List(item) => {
2815 skip_blocks(buf, |c| item.skip(c))?;
2816 Ok(())
2817 }
2818 Self::Map(value) => {
2819 skip_blocks(buf, |c| {
2820 c.get_bytes()?; value.skip(c)
2822 })?;
2823 Ok(())
2824 }
2825 Self::Struct(fields) => {
2826 for f in fields {
2827 f.skip(buf)?
2828 }
2829 Ok(())
2830 }
2831 Self::Union(encodings) => {
2832 let raw = buf.get_long()?;
2834 if raw < 0 {
2835 return Err(AvroError::ParseError(format!(
2836 "Negative union branch index {raw}"
2837 )));
2838 }
2839 let idx: usize = usize::try_from(raw).map_err(|_| {
2840 AvroError::ParseError(format!(
2841 "Union branch index {raw} does not fit into usize on this platform ({}-bit)",
2842 (usize::BITS as usize)
2843 ))
2844 })?;
2845 let Some(encoding) = encodings.get(idx) else {
2846 return Err(AvroError::ParseError(format!(
2847 "Union branch index {idx} out of range for skipper ({} branches)",
2848 encodings.len()
2849 )));
2850 };
2851 encoding.skip(buf)
2852 }
2853 Self::Nullable(order, inner) => {
2854 let branch = buf.read_vlq()?;
2855 let is_not_null = match *order {
2856 Nullability::NullFirst => branch != 0,
2857 Nullability::NullSecond => branch == 0,
2858 };
2859 if is_not_null {
2860 inner.skip(buf)?;
2861 }
2862 Ok(())
2863 }
2864 #[cfg(feature = "avro_custom_types")]
2865 Self::RunEndEncoded(inner) => inner.skip(buf),
2866 }
2867 }
2868}
2869
2870#[cfg(test)]
2871mod tests {
2872 use super::*;
2873 use crate::codec::AvroFieldBuilder;
2874 use crate::schema::{Attributes, ComplexType, Field, PrimitiveType, Record, Schema, TypeName};
2875 use arrow_array::cast::AsArray;
2876 use indexmap::IndexMap;
2877 use std::collections::HashMap;
2878
2879 fn encode_avro_int(value: i32) -> Vec<u8> {
2880 let mut buf = Vec::new();
2881 let mut v = (value << 1) ^ (value >> 31);
2882 while v & !0x7F != 0 {
2883 buf.push(((v & 0x7F) | 0x80) as u8);
2884 v >>= 7;
2885 }
2886 buf.push(v as u8);
2887 buf
2888 }
2889
2890 fn encode_avro_long(value: i64) -> Vec<u8> {
2891 let mut buf = Vec::new();
2892 let mut v = (value << 1) ^ (value >> 63);
2893 while v & !0x7F != 0 {
2894 buf.push(((v & 0x7F) | 0x80) as u8);
2895 v >>= 7;
2896 }
2897 buf.push(v as u8);
2898 buf
2899 }
2900
2901 fn encode_avro_bytes(bytes: &[u8]) -> Vec<u8> {
2902 let mut buf = encode_avro_long(bytes.len() as i64);
2903 buf.extend_from_slice(bytes);
2904 buf
2905 }
2906
2907 fn avro_from_codec(codec: Codec) -> AvroDataType {
2908 AvroDataType::new(codec, Default::default(), None)
2909 }
2910
2911 fn resolved_root_datatype(
2912 writer: Schema<'static>,
2913 reader: Schema<'static>,
2914 use_utf8view: bool,
2915 strict_mode: bool,
2916 ) -> AvroDataType {
2917 let writer_record = Schema::Complex(ComplexType::Record(Record {
2919 name: "Root",
2920 namespace: None,
2921 doc: None,
2922 aliases: vec![],
2923 fields: vec![Field {
2924 name: "v",
2925 r#type: writer,
2926 default: None,
2927 doc: None,
2928 aliases: vec![],
2929 }],
2930 attributes: Attributes::default(),
2931 }));
2932
2933 let reader_record = Schema::Complex(ComplexType::Record(Record {
2935 name: "Root",
2936 namespace: None,
2937 doc: None,
2938 aliases: vec![],
2939 fields: vec![Field {
2940 name: "v",
2941 r#type: reader,
2942 default: None,
2943 doc: None,
2944 aliases: vec![],
2945 }],
2946 attributes: Attributes::default(),
2947 }));
2948
2949 let field = AvroFieldBuilder::new(&writer_record)
2951 .with_reader_schema(&reader_record)
2952 .with_utf8view(use_utf8view)
2953 .with_strict_mode(strict_mode)
2954 .build()
2955 .expect("schema resolution should succeed");
2956
2957 match field.data_type().codec() {
2958 Codec::Struct(fields) => fields[0].data_type().clone(),
2959 other => panic!("expected wrapper struct, got {other:?}"),
2960 }
2961 }
2962
2963 fn decoder_for_promotion(
2964 writer: PrimitiveType,
2965 reader: PrimitiveType,
2966 use_utf8view: bool,
2967 ) -> Decoder {
2968 let ws = Schema::TypeName(TypeName::Primitive(writer));
2969 let rs = Schema::TypeName(TypeName::Primitive(reader));
2970 let dt = resolved_root_datatype(ws, rs, use_utf8view, false);
2971 Decoder::try_new(&dt).unwrap()
2972 }
2973
2974 fn make_avro_dt(codec: Codec, nullability: Option<Nullability>) -> AvroDataType {
2975 AvroDataType::new(codec, HashMap::new(), nullability)
2976 }
2977
2978 #[cfg(feature = "avro_custom_types")]
2979 fn encode_vlq_u64(mut x: u64) -> Vec<u8> {
2980 let mut out = Vec::with_capacity(10);
2981 while x >= 0x80 {
2982 out.push((x as u8) | 0x80);
2983 x >>= 7;
2984 }
2985 out.push(x as u8);
2986 out
2987 }
2988
2989 #[test]
2990 fn test_union_resolution_writer_union_reader_union_reorder_and_promotion_dense() {
2991 let ws = Schema::Union(vec![
2992 Schema::TypeName(TypeName::Primitive(PrimitiveType::Int)),
2993 Schema::TypeName(TypeName::Primitive(PrimitiveType::String)),
2994 ]);
2995 let rs = Schema::Union(vec![
2996 Schema::TypeName(TypeName::Primitive(PrimitiveType::String)),
2997 Schema::TypeName(TypeName::Primitive(PrimitiveType::Long)),
2998 ]);
2999
3000 let dt = resolved_root_datatype(ws, rs, false, false);
3001 let mut dec = Decoder::try_new(&dt).unwrap();
3002
3003 let mut rec1 = encode_avro_long(0);
3004 rec1.extend(encode_avro_int(7));
3005 let mut cur1 = AvroCursor::new(&rec1);
3006 dec.decode(&mut cur1).unwrap();
3007
3008 let mut rec2 = encode_avro_long(1);
3009 rec2.extend(encode_avro_bytes(b"abc"));
3010 let mut cur2 = AvroCursor::new(&rec2);
3011 dec.decode(&mut cur2).unwrap();
3012
3013 let arr = dec.flush(None).unwrap();
3014 let ua = arr
3015 .as_any()
3016 .downcast_ref::<UnionArray>()
3017 .expect("dense union output");
3018
3019 assert_eq!(
3020 ua.type_id(0),
3021 1,
3022 "first value must select reader 'long' branch"
3023 );
3024 assert_eq!(ua.value_offset(0), 0);
3025
3026 assert_eq!(
3027 ua.type_id(1),
3028 0,
3029 "second value must select reader 'string' branch"
3030 );
3031 assert_eq!(ua.value_offset(1), 0);
3032
3033 let long_child = ua.child(1).as_any().downcast_ref::<Int64Array>().unwrap();
3034 assert_eq!(long_child.len(), 1);
3035 assert_eq!(long_child.value(0), 7);
3036
3037 let str_child = ua.child(0).as_any().downcast_ref::<StringArray>().unwrap();
3038 assert_eq!(str_child.len(), 1);
3039 assert_eq!(str_child.value(0), "abc");
3040 }
3041
3042 #[test]
3043 fn test_union_resolution_writer_union_reader_nonunion_promotion_int_to_long() {
3044 let ws = Schema::Union(vec![
3045 Schema::TypeName(TypeName::Primitive(PrimitiveType::Int)),
3046 Schema::TypeName(TypeName::Primitive(PrimitiveType::String)),
3047 ]);
3048 let rs = Schema::TypeName(TypeName::Primitive(PrimitiveType::Long));
3049
3050 let dt = resolved_root_datatype(ws, rs, false, false);
3051 let mut dec = Decoder::try_new(&dt).unwrap();
3052
3053 let mut data = encode_avro_long(0);
3054 data.extend(encode_avro_int(5));
3055 let mut cur = AvroCursor::new(&data);
3056 dec.decode(&mut cur).unwrap();
3057
3058 let arr = dec.flush(None).unwrap();
3059 let out = arr.as_any().downcast_ref::<Int64Array>().unwrap();
3060 assert_eq!(out.len(), 1);
3061 assert_eq!(out.value(0), 5);
3062 }
3063
3064 #[test]
3065 fn test_union_resolution_writer_union_reader_nonunion_mismatch_errors() {
3066 let ws = Schema::Union(vec![
3067 Schema::TypeName(TypeName::Primitive(PrimitiveType::Int)),
3068 Schema::TypeName(TypeName::Primitive(PrimitiveType::String)),
3069 ]);
3070 let rs = Schema::TypeName(TypeName::Primitive(PrimitiveType::Long));
3071
3072 let dt = resolved_root_datatype(ws, rs, false, false);
3073 let mut dec = Decoder::try_new(&dt).unwrap();
3074
3075 let mut data = encode_avro_long(1);
3076 data.extend(encode_avro_bytes(b"z"));
3077 let mut cur = AvroCursor::new(&data);
3078 let res = dec.decode(&mut cur);
3079 assert!(
3080 res.is_err(),
3081 "expected error when writer union branch does not resolve to reader non-union type"
3082 );
3083 }
3084
3085 #[test]
3086 fn test_union_resolution_writer_nonunion_reader_union_selects_matching_branch() {
3087 let ws = Schema::TypeName(TypeName::Primitive(PrimitiveType::Int));
3088 let rs = Schema::Union(vec![
3089 Schema::TypeName(TypeName::Primitive(PrimitiveType::String)),
3090 Schema::TypeName(TypeName::Primitive(PrimitiveType::Long)),
3091 ]);
3092
3093 let dt = resolved_root_datatype(ws, rs, false, false);
3094 let mut dec = Decoder::try_new(&dt).unwrap();
3095
3096 let data = encode_avro_int(6);
3097 let mut cur = AvroCursor::new(&data);
3098 dec.decode(&mut cur).unwrap();
3099
3100 let arr = dec.flush(None).unwrap();
3101 let ua = arr
3102 .as_any()
3103 .downcast_ref::<UnionArray>()
3104 .expect("dense union output");
3105 assert_eq!(ua.len(), 1);
3106 assert_eq!(
3107 ua.type_id(0),
3108 1,
3109 "must resolve to reader 'long' branch (type_id 1)"
3110 );
3111 assert_eq!(ua.value_offset(0), 0);
3112
3113 let long_child = ua.child(1).as_any().downcast_ref::<Int64Array>().unwrap();
3114 assert_eq!(long_child.len(), 1);
3115 assert_eq!(long_child.value(0), 6);
3116
3117 let str_child = ua.child(0).as_any().downcast_ref::<StringArray>().unwrap();
3118 assert_eq!(str_child.len(), 0, "string branch must be empty");
3119 }
3120
3121 #[test]
3122 fn test_union_resolution_writer_union_reader_union_unmapped_branch_errors() {
3123 let ws = Schema::Union(vec![
3124 Schema::TypeName(TypeName::Primitive(PrimitiveType::Int)),
3125 Schema::TypeName(TypeName::Primitive(PrimitiveType::Boolean)),
3126 ]);
3127 let rs = Schema::Union(vec![
3128 Schema::TypeName(TypeName::Primitive(PrimitiveType::String)),
3129 Schema::TypeName(TypeName::Primitive(PrimitiveType::Long)),
3130 ]);
3131
3132 let dt = resolved_root_datatype(ws, rs, false, false);
3133 let mut dec = Decoder::try_new(&dt).unwrap();
3134
3135 let mut data = encode_avro_long(1);
3136 data.push(1);
3137 let mut cur = AvroCursor::new(&data);
3138 let res = dec.decode(&mut cur);
3139 assert!(
3140 res.is_err(),
3141 "expected error for unmapped writer 'boolean' branch"
3142 );
3143 }
3144
3145 #[test]
3146 fn test_schema_resolution_promotion_int_to_long() {
3147 let mut dec = decoder_for_promotion(PrimitiveType::Int, PrimitiveType::Long, false);
3148 assert!(matches!(dec, Decoder::Int32ToInt64(_)));
3149 for v in [0, 1, -2, 123456] {
3150 let data = encode_avro_int(v);
3151 let mut cur = AvroCursor::new(&data);
3152 dec.decode(&mut cur).unwrap();
3153 }
3154 let arr = dec.flush(None).unwrap();
3155 let a = arr.as_any().downcast_ref::<Int64Array>().unwrap();
3156 assert_eq!(a.value(0), 0);
3157 assert_eq!(a.value(1), 1);
3158 assert_eq!(a.value(2), -2);
3159 assert_eq!(a.value(3), 123456);
3160 }
3161
3162 #[test]
3163 fn test_schema_resolution_promotion_int_to_float() {
3164 let mut dec = decoder_for_promotion(PrimitiveType::Int, PrimitiveType::Float, false);
3165 assert!(matches!(dec, Decoder::Int32ToFloat32(_)));
3166 for v in [0, 42, -7] {
3167 let data = encode_avro_int(v);
3168 let mut cur = AvroCursor::new(&data);
3169 dec.decode(&mut cur).unwrap();
3170 }
3171 let arr = dec.flush(None).unwrap();
3172 let a = arr.as_any().downcast_ref::<Float32Array>().unwrap();
3173 assert_eq!(a.value(0), 0.0);
3174 assert_eq!(a.value(1), 42.0);
3175 assert_eq!(a.value(2), -7.0);
3176 }
3177
3178 #[test]
3179 fn test_schema_resolution_promotion_int_to_double() {
3180 let mut dec = decoder_for_promotion(PrimitiveType::Int, PrimitiveType::Double, false);
3181 assert!(matches!(dec, Decoder::Int32ToFloat64(_)));
3182 for v in [1, -1, 10_000] {
3183 let data = encode_avro_int(v);
3184 let mut cur = AvroCursor::new(&data);
3185 dec.decode(&mut cur).unwrap();
3186 }
3187 let arr = dec.flush(None).unwrap();
3188 let a = arr.as_any().downcast_ref::<Float64Array>().unwrap();
3189 assert_eq!(a.value(0), 1.0);
3190 assert_eq!(a.value(1), -1.0);
3191 assert_eq!(a.value(2), 10_000.0);
3192 }
3193
3194 #[test]
3195 fn test_schema_resolution_promotion_long_to_float() {
3196 let mut dec = decoder_for_promotion(PrimitiveType::Long, PrimitiveType::Float, false);
3197 assert!(matches!(dec, Decoder::Int64ToFloat32(_)));
3198 for v in [0_i64, 1_000_000_i64, -123_i64] {
3199 let data = encode_avro_long(v);
3200 let mut cur = AvroCursor::new(&data);
3201 dec.decode(&mut cur).unwrap();
3202 }
3203 let arr = dec.flush(None).unwrap();
3204 let a = arr.as_any().downcast_ref::<Float32Array>().unwrap();
3205 assert_eq!(a.value(0), 0.0);
3206 assert_eq!(a.value(1), 1_000_000.0);
3207 assert_eq!(a.value(2), -123.0);
3208 }
3209
3210 #[test]
3211 fn test_schema_resolution_promotion_long_to_double() {
3212 let mut dec = decoder_for_promotion(PrimitiveType::Long, PrimitiveType::Double, false);
3213 assert!(matches!(dec, Decoder::Int64ToFloat64(_)));
3214 for v in [2_i64, -2_i64, 9_223_372_i64] {
3215 let data = encode_avro_long(v);
3216 let mut cur = AvroCursor::new(&data);
3217 dec.decode(&mut cur).unwrap();
3218 }
3219 let arr = dec.flush(None).unwrap();
3220 let a = arr.as_any().downcast_ref::<Float64Array>().unwrap();
3221 assert_eq!(a.value(0), 2.0);
3222 assert_eq!(a.value(1), -2.0);
3223 assert_eq!(a.value(2), 9_223_372.0);
3224 }
3225
3226 #[test]
3227 fn test_schema_resolution_promotion_float_to_double() {
3228 let mut dec = decoder_for_promotion(PrimitiveType::Float, PrimitiveType::Double, false);
3229 assert!(matches!(dec, Decoder::Float32ToFloat64(_)));
3230 for v in [0.5_f32, -3.25_f32, 1.0e6_f32] {
3231 let data = v.to_le_bytes().to_vec();
3232 let mut cur = AvroCursor::new(&data);
3233 dec.decode(&mut cur).unwrap();
3234 }
3235 let arr = dec.flush(None).unwrap();
3236 let a = arr.as_any().downcast_ref::<Float64Array>().unwrap();
3237 assert_eq!(a.value(0), 0.5_f64);
3238 assert_eq!(a.value(1), -3.25_f64);
3239 assert_eq!(a.value(2), 1.0e6_f64);
3240 }
3241
3242 #[test]
3243 fn test_schema_resolution_promotion_bytes_to_string_utf8() {
3244 let mut dec = decoder_for_promotion(PrimitiveType::Bytes, PrimitiveType::String, false);
3245 assert!(matches!(dec, Decoder::BytesToString(_, _)));
3246 for s in ["hello", "world", "héllo"] {
3247 let data = encode_avro_bytes(s.as_bytes());
3248 let mut cur = AvroCursor::new(&data);
3249 dec.decode(&mut cur).unwrap();
3250 }
3251 let arr = dec.flush(None).unwrap();
3252 let a = arr.as_any().downcast_ref::<StringArray>().unwrap();
3253 assert_eq!(a.value(0), "hello");
3254 assert_eq!(a.value(1), "world");
3255 assert_eq!(a.value(2), "héllo");
3256 }
3257
3258 #[test]
3259 fn test_schema_resolution_promotion_bytes_to_string_utf8view_enabled() {
3260 let mut dec = decoder_for_promotion(PrimitiveType::Bytes, PrimitiveType::String, true);
3261 assert!(matches!(dec, Decoder::BytesToString(_, _)));
3262 let data = encode_avro_bytes(b"abc");
3263 let mut cur = AvroCursor::new(&data);
3264 dec.decode(&mut cur).unwrap();
3265 let arr = dec.flush(None).unwrap();
3266 let a = arr.as_any().downcast_ref::<StringArray>().unwrap();
3267 assert_eq!(a.value(0), "abc");
3268 }
3269
3270 #[test]
3271 fn test_schema_resolution_promotion_string_to_bytes() {
3272 let mut dec = decoder_for_promotion(PrimitiveType::String, PrimitiveType::Bytes, false);
3273 assert!(matches!(dec, Decoder::StringToBytes(_, _)));
3274 for s in ["", "abc", "data"] {
3275 let data = encode_avro_bytes(s.as_bytes());
3276 let mut cur = AvroCursor::new(&data);
3277 dec.decode(&mut cur).unwrap();
3278 }
3279 let arr = dec.flush(None).unwrap();
3280 let a = arr.as_any().downcast_ref::<BinaryArray>().unwrap();
3281 assert_eq!(a.value(0), b"");
3282 assert_eq!(a.value(1), b"abc");
3283 assert_eq!(a.value(2), b"data");
3284 }
3285
3286 #[test]
3287 fn test_schema_resolution_no_promotion_passthrough_int() {
3288 let ws = Schema::TypeName(TypeName::Primitive(PrimitiveType::Int));
3289 let rs = Schema::TypeName(TypeName::Primitive(PrimitiveType::Int));
3290 let writer_record = Schema::Complex(ComplexType::Record(Record {
3292 name: "Root",
3293 namespace: None,
3294 doc: None,
3295 aliases: vec![],
3296 fields: vec![Field {
3297 name: "v",
3298 r#type: ws,
3299 default: None,
3300 doc: None,
3301 aliases: vec![],
3302 }],
3303 attributes: Attributes::default(),
3304 }));
3305 let reader_record = Schema::Complex(ComplexType::Record(Record {
3306 name: "Root",
3307 namespace: None,
3308 doc: None,
3309 aliases: vec![],
3310 fields: vec![Field {
3311 name: "v",
3312 r#type: rs,
3313 default: None,
3314 doc: None,
3315 aliases: vec![],
3316 }],
3317 attributes: Attributes::default(),
3318 }));
3319 let field = AvroFieldBuilder::new(&writer_record)
3320 .with_reader_schema(&reader_record)
3321 .with_utf8view(false)
3322 .with_strict_mode(false)
3323 .build()
3324 .unwrap();
3325 let dt = match field.data_type().codec() {
3327 Codec::Struct(fields) => fields[0].data_type().clone(),
3328 other => panic!("expected wrapper struct, got {other:?}"),
3329 };
3330 let mut dec = Decoder::try_new(&dt).unwrap();
3331 assert!(matches!(dec, Decoder::Int32(_)));
3332 for v in [7, -9] {
3333 let data = encode_avro_int(v);
3334 let mut cur = AvroCursor::new(&data);
3335 dec.decode(&mut cur).unwrap();
3336 }
3337 let arr = dec.flush(None).unwrap();
3338 let a = arr.as_any().downcast_ref::<Int32Array>().unwrap();
3339 assert_eq!(a.value(0), 7);
3340 assert_eq!(a.value(1), -9);
3341 }
3342
3343 #[test]
3344 fn test_schema_resolution_illegal_promotion_int_to_boolean_errors() {
3345 let ws = Schema::TypeName(TypeName::Primitive(PrimitiveType::Int));
3346 let rs = Schema::TypeName(TypeName::Primitive(PrimitiveType::Boolean));
3347 let writer_record = Schema::Complex(ComplexType::Record(Record {
3348 name: "Root",
3349 namespace: None,
3350 doc: None,
3351 aliases: vec![],
3352 fields: vec![Field {
3353 name: "v",
3354 r#type: ws,
3355 default: None,
3356 doc: None,
3357 aliases: vec![],
3358 }],
3359 attributes: Attributes::default(),
3360 }));
3361 let reader_record = Schema::Complex(ComplexType::Record(Record {
3362 name: "Root",
3363 namespace: None,
3364 doc: None,
3365 aliases: vec![],
3366 fields: vec![Field {
3367 name: "v",
3368 r#type: rs,
3369 default: None,
3370 doc: None,
3371 aliases: vec![],
3372 }],
3373 attributes: Attributes::default(),
3374 }));
3375 let res = AvroFieldBuilder::new(&writer_record)
3376 .with_reader_schema(&reader_record)
3377 .with_utf8view(false)
3378 .with_strict_mode(false)
3379 .build();
3380 assert!(res.is_err(), "expected error for illegal promotion");
3381 }
3382
3383 #[test]
3384 fn test_map_decoding_one_entry() {
3385 let value_type = avro_from_codec(Codec::Utf8);
3386 let map_type = avro_from_codec(Codec::Map(Arc::new(value_type)));
3387 let mut decoder = Decoder::try_new(&map_type).unwrap();
3388 let mut data = Vec::new();
3390 data.extend_from_slice(&encode_avro_long(1));
3391 data.extend_from_slice(&encode_avro_bytes(b"hello")); data.extend_from_slice(&encode_avro_bytes(b"world")); data.extend_from_slice(&encode_avro_long(0));
3394 let mut cursor = AvroCursor::new(&data);
3395 decoder.decode(&mut cursor).unwrap();
3396 let array = decoder.flush(None).unwrap();
3397 let map_arr = array.as_any().downcast_ref::<MapArray>().unwrap();
3398 assert_eq!(map_arr.len(), 1); assert_eq!(map_arr.value_length(0), 1);
3400 let entries = map_arr.value(0);
3401 let struct_entries = entries.as_any().downcast_ref::<StructArray>().unwrap();
3402 assert_eq!(struct_entries.len(), 1);
3403 let key_arr = struct_entries
3404 .column_by_name("key")
3405 .unwrap()
3406 .as_any()
3407 .downcast_ref::<StringArray>()
3408 .unwrap();
3409 let val_arr = struct_entries
3410 .column_by_name("value")
3411 .unwrap()
3412 .as_any()
3413 .downcast_ref::<StringArray>()
3414 .unwrap();
3415 assert_eq!(key_arr.value(0), "hello");
3416 assert_eq!(val_arr.value(0), "world");
3417 }
3418
3419 #[test]
3420 fn test_map_decoding_empty() {
3421 let value_type = avro_from_codec(Codec::Utf8);
3422 let map_type = avro_from_codec(Codec::Map(Arc::new(value_type)));
3423 let mut decoder = Decoder::try_new(&map_type).unwrap();
3424 let data = encode_avro_long(0);
3425 decoder.decode(&mut AvroCursor::new(&data)).unwrap();
3426 let array = decoder.flush(None).unwrap();
3427 let map_arr = array.as_any().downcast_ref::<MapArray>().unwrap();
3428 assert_eq!(map_arr.len(), 1);
3429 assert_eq!(map_arr.value_length(0), 0);
3430 }
3431
3432 #[test]
3433 fn test_fixed_decoding() {
3434 let avro_type = avro_from_codec(Codec::Fixed(3));
3435 let mut decoder = Decoder::try_new(&avro_type).expect("Failed to create decoder");
3436
3437 let data1 = [1u8, 2, 3];
3438 let mut cursor1 = AvroCursor::new(&data1);
3439 decoder
3440 .decode(&mut cursor1)
3441 .expect("Failed to decode data1");
3442 assert_eq!(cursor1.position(), 3, "Cursor should advance by fixed size");
3443 let data2 = [4u8, 5, 6];
3444 let mut cursor2 = AvroCursor::new(&data2);
3445 decoder
3446 .decode(&mut cursor2)
3447 .expect("Failed to decode data2");
3448 assert_eq!(cursor2.position(), 3, "Cursor should advance by fixed size");
3449 let array = decoder.flush(None).expect("Failed to flush decoder");
3450 assert_eq!(array.len(), 2, "Array should contain two items");
3451 let fixed_size_binary_array = array
3452 .as_any()
3453 .downcast_ref::<FixedSizeBinaryArray>()
3454 .expect("Failed to downcast to FixedSizeBinaryArray");
3455 assert_eq!(
3456 fixed_size_binary_array.value_length(),
3457 3,
3458 "Fixed size of binary values should be 3"
3459 );
3460 assert_eq!(
3461 fixed_size_binary_array.value(0),
3462 &[1, 2, 3],
3463 "First item mismatch"
3464 );
3465 assert_eq!(
3466 fixed_size_binary_array.value(1),
3467 &[4, 5, 6],
3468 "Second item mismatch"
3469 );
3470 }
3471
3472 #[test]
3473 fn test_fixed_decoding_empty() {
3474 let avro_type = avro_from_codec(Codec::Fixed(5));
3475 let mut decoder = Decoder::try_new(&avro_type).expect("Failed to create decoder");
3476
3477 let array = decoder
3478 .flush(None)
3479 .expect("Failed to flush decoder for empty input");
3480
3481 assert_eq!(array.len(), 0, "Array should be empty");
3482 let fixed_size_binary_array = array
3483 .as_any()
3484 .downcast_ref::<FixedSizeBinaryArray>()
3485 .expect("Failed to downcast to FixedSizeBinaryArray for empty array");
3486
3487 assert_eq!(
3488 fixed_size_binary_array.value_length(),
3489 5,
3490 "Fixed size of binary values should be 5 as per type"
3491 );
3492 }
3493
3494 #[test]
3495 fn test_uuid_decoding() {
3496 let avro_type = avro_from_codec(Codec::Uuid);
3497 let mut decoder = Decoder::try_new(&avro_type).expect("Failed to create decoder");
3498 let uuid_str = "f81d4fae-7dec-11d0-a765-00a0c91e6bf6";
3499 let data = encode_avro_bytes(uuid_str.as_bytes());
3500 let mut cursor = AvroCursor::new(&data);
3501 decoder.decode(&mut cursor).expect("Failed to decode data");
3502 assert_eq!(
3503 cursor.position(),
3504 data.len(),
3505 "Cursor should advance by varint size + data size"
3506 );
3507 let array = decoder.flush(None).expect("Failed to flush decoder");
3508 let fixed_size_binary_array = array
3509 .as_any()
3510 .downcast_ref::<FixedSizeBinaryArray>()
3511 .expect("Array should be a FixedSizeBinaryArray");
3512 assert_eq!(fixed_size_binary_array.len(), 1);
3513 assert_eq!(fixed_size_binary_array.value_length(), 16);
3514 let expected_bytes = [
3515 0xf8, 0x1d, 0x4f, 0xae, 0x7d, 0xec, 0x11, 0xd0, 0xa7, 0x65, 0x00, 0xa0, 0xc9, 0x1e,
3516 0x6b, 0xf6,
3517 ];
3518 assert_eq!(fixed_size_binary_array.value(0), &expected_bytes);
3519 }
3520
3521 #[test]
3522 fn test_array_decoding() {
3523 let item_dt = avro_from_codec(Codec::Int32);
3524 let list_dt = avro_from_codec(Codec::List(Arc::new(item_dt)));
3525 let mut decoder = Decoder::try_new(&list_dt).unwrap();
3526 let mut row1 = Vec::new();
3527 row1.extend_from_slice(&encode_avro_long(2));
3528 row1.extend_from_slice(&encode_avro_int(10));
3529 row1.extend_from_slice(&encode_avro_int(20));
3530 row1.extend_from_slice(&encode_avro_long(0));
3531 let row2 = encode_avro_long(0);
3532 let mut cursor = AvroCursor::new(&row1);
3533 decoder.decode(&mut cursor).unwrap();
3534 let mut cursor2 = AvroCursor::new(&row2);
3535 decoder.decode(&mut cursor2).unwrap();
3536 let array = decoder.flush(None).unwrap();
3537 let list_arr = array.as_any().downcast_ref::<ListArray>().unwrap();
3538 assert_eq!(list_arr.len(), 2);
3539 let offsets = list_arr.value_offsets();
3540 assert_eq!(offsets, &[0, 2, 2]);
3541 let values = list_arr.values();
3542 let int_arr = values.as_primitive::<Int32Type>();
3543 assert_eq!(int_arr.len(), 2);
3544 assert_eq!(int_arr.value(0), 10);
3545 assert_eq!(int_arr.value(1), 20);
3546 }
3547
3548 #[test]
3549 fn test_array_decoding_with_negative_block_count() {
3550 let item_dt = avro_from_codec(Codec::Int32);
3551 let list_dt = avro_from_codec(Codec::List(Arc::new(item_dt)));
3552 let mut decoder = Decoder::try_new(&list_dt).unwrap();
3553 let mut data = encode_avro_long(-3);
3554 data.extend_from_slice(&encode_avro_long(12));
3555 data.extend_from_slice(&encode_avro_int(1));
3556 data.extend_from_slice(&encode_avro_int(2));
3557 data.extend_from_slice(&encode_avro_int(3));
3558 data.extend_from_slice(&encode_avro_long(0));
3559 let mut cursor = AvroCursor::new(&data);
3560 decoder.decode(&mut cursor).unwrap();
3561 let array = decoder.flush(None).unwrap();
3562 let list_arr = array.as_any().downcast_ref::<ListArray>().unwrap();
3563 assert_eq!(list_arr.len(), 1);
3564 assert_eq!(list_arr.value_length(0), 3);
3565 let values = list_arr.values().as_primitive::<Int32Type>();
3566 assert_eq!(values.len(), 3);
3567 assert_eq!(values.value(0), 1);
3568 assert_eq!(values.value(1), 2);
3569 assert_eq!(values.value(2), 3);
3570 }
3571
3572 fn encode_avro_long_extreme(value: i64) -> Vec<u8> {
3575 let mut n = ((value << 1) ^ (value >> 63)) as u64;
3576 let mut out = Vec::new();
3577 while n >= 0x80 {
3578 out.push((n as u8) | 0x80);
3579 n >>= 7;
3580 }
3581 out.push(n as u8);
3582 out
3583 }
3584
3585 fn array_of_null_decoder() -> Decoder {
3588 let list_dt = avro_from_codec(Codec::List(Arc::new(avro_from_codec(Codec::Null))));
3589 Decoder::try_new(&list_dt).unwrap()
3590 }
3591
3592 #[test]
3593 fn test_array_of_null_decodes() {
3594 let mut decoder = array_of_null_decoder();
3595 let mut data = encode_avro_long(3); data.extend_from_slice(&encode_avro_long(0)); decoder.decode(&mut AvroCursor::new(&data)).unwrap();
3598 }
3599
3600 #[test]
3601 fn test_array_block_count_i64_max_errors() {
3602 let mut decoder = array_of_null_decoder();
3604 let mut data = encode_avro_long_extreme(i64::MAX); data.extend_from_slice(&encode_avro_long(0)); let err = decoder.decode(&mut AvroCursor::new(&data)).unwrap_err();
3607 assert!(
3608 err.to_string().contains("Capacity overflow"),
3609 "unexpected error: {err}",
3610 );
3611 }
3612
3613 #[test]
3614 fn test_array_block_count_i64_min_errors() {
3615 let mut decoder = array_of_null_decoder();
3617 let mut data = encode_avro_long_extreme(i64::MIN); data.extend_from_slice(&encode_avro_long(0)); let err = decoder.decode(&mut AvroCursor::new(&data)).unwrap_err();
3620 assert!(
3621 err.to_string().contains("Capacity overflow"),
3622 "unexpected error: {err}",
3623 );
3624 }
3625
3626 #[test]
3627 fn test_nested_array_decoding() {
3628 let inner_ty = avro_from_codec(Codec::List(Arc::new(avro_from_codec(Codec::Int32))));
3629 let nested_ty = avro_from_codec(Codec::List(Arc::new(inner_ty.clone())));
3630 let mut decoder = Decoder::try_new(&nested_ty).unwrap();
3631 let mut buf = Vec::new();
3632 buf.extend(encode_avro_long(1));
3633 buf.extend(encode_avro_long(2));
3634 buf.extend(encode_avro_int(5));
3635 buf.extend(encode_avro_int(6));
3636 buf.extend(encode_avro_long(0));
3637 buf.extend(encode_avro_long(0));
3638 let mut cursor = AvroCursor::new(&buf);
3639 decoder.decode(&mut cursor).unwrap();
3640 let arr = decoder.flush(None).unwrap();
3641 let outer = arr.as_any().downcast_ref::<ListArray>().unwrap();
3642 assert_eq!(outer.len(), 1);
3643 assert_eq!(outer.value_length(0), 1);
3644 let inner = outer.values().as_any().downcast_ref::<ListArray>().unwrap();
3645 assert_eq!(inner.len(), 1);
3646 assert_eq!(inner.value_length(0), 2);
3647 let values = inner
3648 .values()
3649 .as_any()
3650 .downcast_ref::<Int32Array>()
3651 .unwrap();
3652 assert_eq!(values.values(), &[5, 6]);
3653 }
3654
3655 #[test]
3656 fn test_array_decoding_empty_array() {
3657 let value_type = avro_from_codec(Codec::Utf8);
3658 let map_type = avro_from_codec(Codec::List(Arc::new(value_type)));
3659 let mut decoder = Decoder::try_new(&map_type).unwrap();
3660 let data = encode_avro_long(0);
3661 decoder.decode(&mut AvroCursor::new(&data)).unwrap();
3662 let array = decoder.flush(None).unwrap();
3663 let list_arr = array.as_any().downcast_ref::<ListArray>().unwrap();
3664 assert_eq!(list_arr.len(), 1);
3665 assert_eq!(list_arr.value_length(0), 0);
3666 }
3667
3668 #[test]
3669 fn test_array_decoding_writer_nonunion_items_reader_nullable_items() {
3670 use crate::schema::Array;
3671 let writer_schema = Schema::Complex(ComplexType::Array(Array {
3672 items: Box::new(Schema::TypeName(TypeName::Primitive(PrimitiveType::Int))),
3673 attributes: Attributes::default(),
3674 }));
3675 let reader_schema = Schema::Complex(ComplexType::Array(Array {
3676 items: Box::new(Schema::Union(vec![
3677 Schema::TypeName(TypeName::Primitive(PrimitiveType::Null)),
3678 Schema::TypeName(TypeName::Primitive(PrimitiveType::Int)),
3679 ])),
3680 attributes: Attributes::default(),
3681 }));
3682 let dt = resolved_root_datatype(writer_schema, reader_schema, false, false);
3683 if let Codec::List(inner) = dt.codec() {
3684 assert_eq!(
3685 inner.nullability(),
3686 Some(Nullability::NullFirst),
3687 "items should be nullable"
3688 );
3689 } else {
3690 panic!("expected List codec");
3691 }
3692 let mut decoder = Decoder::try_new(&dt).unwrap();
3693 let mut data = encode_avro_long(2);
3694 data.extend(encode_avro_int(10));
3695 data.extend(encode_avro_int(20));
3696 data.extend(encode_avro_long(0));
3697 let mut cursor = AvroCursor::new(&data);
3698 decoder.decode(&mut cursor).unwrap();
3699 assert_eq!(
3700 cursor.position(),
3701 data.len(),
3702 "all bytes should be consumed"
3703 );
3704 let array = decoder.flush(None).unwrap();
3705 let list_arr = array.as_any().downcast_ref::<ListArray>().unwrap();
3706 assert_eq!(list_arr.len(), 1, "one list/row");
3707 assert_eq!(list_arr.value_length(0), 2, "two items in the list");
3708 let values = list_arr.values().as_primitive::<Int32Type>();
3709 assert_eq!(values.len(), 2);
3710 assert_eq!(values.value(0), 10);
3711 assert_eq!(values.value(1), 20);
3712 assert!(!values.is_null(0));
3713 assert!(!values.is_null(1));
3714 }
3715
3716 #[test]
3717 fn test_decimal_decoding_fixed256() {
3718 let dt = avro_from_codec(Codec::Decimal(50, Some(2), Some(32)));
3719 let mut decoder = Decoder::try_new(&dt).unwrap();
3720 let row1 = [
3721 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3722 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3723 0x00, 0x00, 0x30, 0x39,
3724 ];
3725 let row2 = [
3726 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
3727 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
3728 0xFF, 0xFF, 0xFF, 0x85,
3729 ];
3730 let mut data = Vec::new();
3731 data.extend_from_slice(&row1);
3732 data.extend_from_slice(&row2);
3733 let mut cursor = AvroCursor::new(&data);
3734 decoder.decode(&mut cursor).unwrap();
3735 decoder.decode(&mut cursor).unwrap();
3736 let arr = decoder.flush(None).unwrap();
3737 let dec = arr.as_any().downcast_ref::<Decimal256Array>().unwrap();
3738 assert_eq!(dec.len(), 2);
3739 assert_eq!(dec.value_as_string(0), "123.45");
3740 assert_eq!(dec.value_as_string(1), "-1.23");
3741 }
3742
3743 #[test]
3744 fn test_decimal_decoding_fixed128() {
3745 let dt = avro_from_codec(Codec::Decimal(28, Some(2), Some(16)));
3746 let mut decoder = Decoder::try_new(&dt).unwrap();
3747 let row1 = [
3748 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3749 0x30, 0x39,
3750 ];
3751 let row2 = [
3752 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
3753 0xFF, 0x85,
3754 ];
3755 let mut data = Vec::new();
3756 data.extend_from_slice(&row1);
3757 data.extend_from_slice(&row2);
3758 let mut cursor = AvroCursor::new(&data);
3759 decoder.decode(&mut cursor).unwrap();
3760 decoder.decode(&mut cursor).unwrap();
3761 let arr = decoder.flush(None).unwrap();
3762 let dec = arr.as_any().downcast_ref::<Decimal128Array>().unwrap();
3763 assert_eq!(dec.len(), 2);
3764 assert_eq!(dec.value_as_string(0), "123.45");
3765 assert_eq!(dec.value_as_string(1), "-1.23");
3766 }
3767
3768 #[test]
3769 fn test_decimal_decoding_fixed32_from_32byte_fixed_storage() {
3770 let dt = avro_from_codec(Codec::Decimal(5, Some(2), Some(32)));
3771 let mut decoder = Decoder::try_new(&dt).unwrap();
3772 let row1 = [
3773 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3774 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3775 0x00, 0x00, 0x30, 0x39,
3776 ];
3777 let row2 = [
3778 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
3779 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
3780 0xFF, 0xFF, 0xFF, 0x85,
3781 ];
3782 let mut data = Vec::new();
3783 data.extend_from_slice(&row1);
3784 data.extend_from_slice(&row2);
3785 let mut cursor = AvroCursor::new(&data);
3786 decoder.decode(&mut cursor).unwrap();
3787 decoder.decode(&mut cursor).unwrap();
3788 let arr = decoder.flush(None).unwrap();
3789 #[cfg(feature = "small_decimals")]
3790 {
3791 let dec = arr.as_any().downcast_ref::<Decimal32Array>().unwrap();
3792 assert_eq!(dec.len(), 2);
3793 assert_eq!(dec.value_as_string(0), "123.45");
3794 assert_eq!(dec.value_as_string(1), "-1.23");
3795 }
3796 #[cfg(not(feature = "small_decimals"))]
3797 {
3798 let dec = arr.as_any().downcast_ref::<Decimal128Array>().unwrap();
3799 assert_eq!(dec.len(), 2);
3800 assert_eq!(dec.value_as_string(0), "123.45");
3801 assert_eq!(dec.value_as_string(1), "-1.23");
3802 }
3803 }
3804
3805 #[test]
3806 fn test_decimal_decoding_fixed32_from_16byte_fixed_storage() {
3807 let dt = avro_from_codec(Codec::Decimal(5, Some(2), Some(16)));
3808 let mut decoder = Decoder::try_new(&dt).unwrap();
3809 let row1 = [
3810 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3811 0x30, 0x39,
3812 ];
3813 let row2 = [
3814 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
3815 0xFF, 0x85,
3816 ];
3817 let mut data = Vec::new();
3818 data.extend_from_slice(&row1);
3819 data.extend_from_slice(&row2);
3820 let mut cursor = AvroCursor::new(&data);
3821 decoder.decode(&mut cursor).unwrap();
3822 decoder.decode(&mut cursor).unwrap();
3823
3824 let arr = decoder.flush(None).unwrap();
3825 #[cfg(feature = "small_decimals")]
3826 {
3827 let dec = arr.as_any().downcast_ref::<Decimal32Array>().unwrap();
3828 assert_eq!(dec.len(), 2);
3829 assert_eq!(dec.value_as_string(0), "123.45");
3830 assert_eq!(dec.value_as_string(1), "-1.23");
3831 }
3832 #[cfg(not(feature = "small_decimals"))]
3833 {
3834 let dec = arr.as_any().downcast_ref::<Decimal128Array>().unwrap();
3835 assert_eq!(dec.len(), 2);
3836 assert_eq!(dec.value_as_string(0), "123.45");
3837 assert_eq!(dec.value_as_string(1), "-1.23");
3838 }
3839 }
3840
3841 #[test]
3842 fn test_decimal_decoding_bytes_with_nulls() {
3843 let dt = avro_from_codec(Codec::Decimal(4, Some(1), None));
3844 let inner = Decoder::try_new(&dt).unwrap();
3845 let mut decoder = Decoder::Nullable(NullableDecoder::new(
3846 NullablePlan::ReadTag {
3847 nullability: Nullability::NullSecond,
3848 resolution: ResolutionPlan::Promotion(Promotion::Direct),
3849 },
3850 inner,
3851 ));
3852 let mut data = Vec::new();
3853 data.extend_from_slice(&encode_avro_int(0));
3854 data.extend_from_slice(&encode_avro_bytes(&[0x04, 0xD2]));
3855 data.extend_from_slice(&encode_avro_int(1));
3856 data.extend_from_slice(&encode_avro_int(0));
3857 data.extend_from_slice(&encode_avro_bytes(&[0xFB, 0x2E]));
3858 let mut cursor = AvroCursor::new(&data);
3859 decoder.decode(&mut cursor).unwrap();
3860 decoder.decode(&mut cursor).unwrap();
3861 decoder.decode(&mut cursor).unwrap();
3862 let arr = decoder.flush(None).unwrap();
3863 #[cfg(feature = "small_decimals")]
3864 {
3865 let dec_arr = arr.as_any().downcast_ref::<Decimal32Array>().unwrap();
3866 assert_eq!(dec_arr.len(), 3);
3867 assert!(dec_arr.is_valid(0));
3868 assert!(!dec_arr.is_valid(1));
3869 assert!(dec_arr.is_valid(2));
3870 assert_eq!(dec_arr.value_as_string(0), "123.4");
3871 assert_eq!(dec_arr.value_as_string(2), "-123.4");
3872 }
3873 #[cfg(not(feature = "small_decimals"))]
3874 {
3875 let dec_arr = arr.as_any().downcast_ref::<Decimal128Array>().unwrap();
3876 assert_eq!(dec_arr.len(), 3);
3877 assert!(dec_arr.is_valid(0));
3878 assert!(!dec_arr.is_valid(1));
3879 assert!(dec_arr.is_valid(2));
3880 assert_eq!(dec_arr.value_as_string(0), "123.4");
3881 assert_eq!(dec_arr.value_as_string(2), "-123.4");
3882 }
3883 }
3884
3885 #[test]
3886 fn test_decimal_decoding_bytes_with_nulls_fixed_size_narrow_result() {
3887 let dt = avro_from_codec(Codec::Decimal(6, Some(2), Some(16)));
3888 let inner = Decoder::try_new(&dt).unwrap();
3889 let mut decoder = Decoder::Nullable(NullableDecoder::new(
3890 NullablePlan::ReadTag {
3891 nullability: Nullability::NullSecond,
3892 resolution: ResolutionPlan::Promotion(Promotion::Direct),
3893 },
3894 inner,
3895 ));
3896 let row1 = [
3897 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
3898 0xE2, 0x40,
3899 ];
3900 let row3 = [
3901 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
3902 0x1D, 0xC0,
3903 ];
3904 let mut data = Vec::new();
3905 data.extend_from_slice(&encode_avro_int(0));
3906 data.extend_from_slice(&row1);
3907 data.extend_from_slice(&encode_avro_int(1));
3908 data.extend_from_slice(&encode_avro_int(0));
3909 data.extend_from_slice(&row3);
3910 let mut cursor = AvroCursor::new(&data);
3911 decoder.decode(&mut cursor).unwrap();
3912 decoder.decode(&mut cursor).unwrap();
3913 decoder.decode(&mut cursor).unwrap();
3914 let arr = decoder.flush(None).unwrap();
3915 #[cfg(feature = "small_decimals")]
3916 {
3917 let dec_arr = arr.as_any().downcast_ref::<Decimal32Array>().unwrap();
3918 assert_eq!(dec_arr.len(), 3);
3919 assert!(dec_arr.is_valid(0));
3920 assert!(!dec_arr.is_valid(1));
3921 assert!(dec_arr.is_valid(2));
3922 assert_eq!(dec_arr.value_as_string(0), "1234.56");
3923 assert_eq!(dec_arr.value_as_string(2), "-1234.56");
3924 }
3925 #[cfg(not(feature = "small_decimals"))]
3926 {
3927 let dec_arr = arr.as_any().downcast_ref::<Decimal128Array>().unwrap();
3928 assert_eq!(dec_arr.len(), 3);
3929 assert!(dec_arr.is_valid(0));
3930 assert!(!dec_arr.is_valid(1));
3931 assert!(dec_arr.is_valid(2));
3932 assert_eq!(dec_arr.value_as_string(0), "1234.56");
3933 assert_eq!(dec_arr.value_as_string(2), "-1234.56");
3934 }
3935 }
3936
3937 #[test]
3938 fn test_enum_decoding() {
3939 let symbols: Arc<[String]> = vec!["A", "B", "C"].into_iter().map(String::from).collect();
3940 let avro_type = avro_from_codec(Codec::Enum(symbols.clone()));
3941 let mut decoder = Decoder::try_new(&avro_type).unwrap();
3942 let mut data = Vec::new();
3943 data.extend_from_slice(&encode_avro_int(2));
3944 data.extend_from_slice(&encode_avro_int(0));
3945 data.extend_from_slice(&encode_avro_int(1));
3946 let mut cursor = AvroCursor::new(&data);
3947 decoder.decode(&mut cursor).unwrap();
3948 decoder.decode(&mut cursor).unwrap();
3949 decoder.decode(&mut cursor).unwrap();
3950 let array = decoder.flush(None).unwrap();
3951 let dict_array = array
3952 .as_any()
3953 .downcast_ref::<DictionaryArray<Int32Type>>()
3954 .unwrap();
3955 assert_eq!(dict_array.len(), 3);
3956 let values = dict_array
3957 .values()
3958 .as_any()
3959 .downcast_ref::<StringArray>()
3960 .unwrap();
3961 assert_eq!(values.value(0), "A");
3962 assert_eq!(values.value(1), "B");
3963 assert_eq!(values.value(2), "C");
3964 assert_eq!(dict_array.keys().values(), &[2, 0, 1]);
3965 }
3966
3967 #[test]
3968 fn test_enum_decoding_with_nulls() {
3969 let symbols: Arc<[String]> = vec!["X", "Y"].into_iter().map(String::from).collect();
3970 let enum_codec = Codec::Enum(symbols.clone());
3971 let avro_type =
3972 AvroDataType::new(enum_codec, Default::default(), Some(Nullability::NullFirst));
3973 let mut decoder = Decoder::try_new(&avro_type).unwrap();
3974 let mut data = Vec::new();
3975 data.extend_from_slice(&encode_avro_long(1));
3976 data.extend_from_slice(&encode_avro_int(1));
3977 data.extend_from_slice(&encode_avro_long(0));
3978 data.extend_from_slice(&encode_avro_long(1));
3979 data.extend_from_slice(&encode_avro_int(0));
3980 let mut cursor = AvroCursor::new(&data);
3981 decoder.decode(&mut cursor).unwrap();
3982 decoder.decode(&mut cursor).unwrap();
3983 decoder.decode(&mut cursor).unwrap();
3984 let array = decoder.flush(None).unwrap();
3985 let dict_array = array
3986 .as_any()
3987 .downcast_ref::<DictionaryArray<Int32Type>>()
3988 .unwrap();
3989 assert_eq!(dict_array.len(), 3);
3990 assert!(dict_array.is_valid(0));
3991 assert!(dict_array.is_null(1));
3992 assert!(dict_array.is_valid(2));
3993 let expected_keys = Int32Array::from(vec![Some(1), None, Some(0)]);
3994 assert_eq!(dict_array.keys(), &expected_keys);
3995 let values = dict_array
3996 .values()
3997 .as_any()
3998 .downcast_ref::<StringArray>()
3999 .unwrap();
4000 assert_eq!(values.value(0), "X");
4001 assert_eq!(values.value(1), "Y");
4002 }
4003
4004 #[test]
4005 fn test_duration_decoding_with_nulls() {
4006 let duration_codec = Codec::Interval;
4007 let avro_type = AvroDataType::new(
4008 duration_codec,
4009 Default::default(),
4010 Some(Nullability::NullFirst),
4011 );
4012 let mut decoder = Decoder::try_new(&avro_type).unwrap();
4013 let mut data = Vec::new();
4014 data.extend_from_slice(&encode_avro_long(1)); let mut duration1 = Vec::new();
4017 duration1.extend_from_slice(&1u32.to_le_bytes());
4018 duration1.extend_from_slice(&2u32.to_le_bytes());
4019 duration1.extend_from_slice(&3u32.to_le_bytes());
4020 data.extend_from_slice(&duration1);
4021 data.extend_from_slice(&encode_avro_long(0)); data.extend_from_slice(&encode_avro_long(1)); let mut duration2 = Vec::new();
4025 duration2.extend_from_slice(&4u32.to_le_bytes());
4026 duration2.extend_from_slice(&5u32.to_le_bytes());
4027 duration2.extend_from_slice(&6u32.to_le_bytes());
4028 data.extend_from_slice(&duration2);
4029 let mut cursor = AvroCursor::new(&data);
4030 decoder.decode(&mut cursor).unwrap();
4031 decoder.decode(&mut cursor).unwrap();
4032 decoder.decode(&mut cursor).unwrap();
4033 let array = decoder.flush(None).unwrap();
4034 let interval_array = array
4035 .as_any()
4036 .downcast_ref::<IntervalMonthDayNanoArray>()
4037 .unwrap();
4038 assert_eq!(interval_array.len(), 3);
4039 assert!(interval_array.is_valid(0));
4040 assert!(interval_array.is_null(1));
4041 assert!(interval_array.is_valid(2));
4042 let expected = IntervalMonthDayNanoArray::from(vec![
4043 Some(IntervalMonthDayNano {
4044 months: 1,
4045 days: 2,
4046 nanoseconds: 3_000_000,
4047 }),
4048 None,
4049 Some(IntervalMonthDayNano {
4050 months: 4,
4051 days: 5,
4052 nanoseconds: 6_000_000,
4053 }),
4054 ]);
4055 assert_eq!(interval_array, &expected);
4056 }
4057
4058 #[cfg(feature = "avro_custom_types")]
4059 #[test]
4060 fn test_interval_month_day_nano_custom_decoding_with_nulls() {
4061 let avro_type = AvroDataType::new(
4062 Codec::IntervalMonthDayNano,
4063 Default::default(),
4064 Some(Nullability::NullFirst),
4065 );
4066 let mut decoder = Decoder::try_new(&avro_type).unwrap();
4067 let mut data = Vec::new();
4068 data.extend_from_slice(&encode_avro_long(1));
4070 data.extend_from_slice(&1i32.to_le_bytes());
4071 data.extend_from_slice(&(-2i32).to_le_bytes());
4072 data.extend_from_slice(&3i64.to_le_bytes());
4073 data.extend_from_slice(&encode_avro_long(0));
4075 data.extend_from_slice(&encode_avro_long(1));
4077 data.extend_from_slice(&(-4i32).to_le_bytes());
4078 data.extend_from_slice(&5i32.to_le_bytes());
4079 data.extend_from_slice(&(-6i64).to_le_bytes());
4080 let mut cursor = AvroCursor::new(&data);
4081 decoder.decode(&mut cursor).unwrap();
4082 decoder.decode(&mut cursor).unwrap();
4083 decoder.decode(&mut cursor).unwrap();
4084 let array = decoder.flush(None).unwrap();
4085 let interval_array = array
4086 .as_any()
4087 .downcast_ref::<IntervalMonthDayNanoArray>()
4088 .unwrap();
4089 assert_eq!(interval_array.len(), 3);
4090 let expected = IntervalMonthDayNanoArray::from(vec![
4091 Some(IntervalMonthDayNano::new(1, -2, 3)),
4092 None,
4093 Some(IntervalMonthDayNano::new(-4, 5, -6)),
4094 ]);
4095 assert_eq!(interval_array, &expected);
4096 }
4097
4098 #[test]
4099 fn test_duration_decoding_empty() {
4100 let duration_codec = Codec::Interval;
4101 let avro_type = AvroDataType::new(duration_codec, Default::default(), None);
4102 let mut decoder = Decoder::try_new(&avro_type).unwrap();
4103 let array = decoder.flush(None).unwrap();
4104 assert_eq!(array.len(), 0);
4105 }
4106
4107 #[test]
4108 #[cfg(feature = "avro_custom_types")]
4109 fn test_duration_seconds_decoding() {
4110 let avro_type = AvroDataType::new(Codec::DurationSeconds, Default::default(), None);
4111 let mut decoder = Decoder::try_new(&avro_type).unwrap();
4112 let mut data = Vec::new();
4113 data.extend_from_slice(&encode_avro_long(0));
4115 data.extend_from_slice(&encode_avro_long(-1));
4116 data.extend_from_slice(&encode_avro_long(2));
4117 let mut cursor = AvroCursor::new(&data);
4118 decoder.decode(&mut cursor).unwrap();
4119 decoder.decode(&mut cursor).unwrap();
4120 decoder.decode(&mut cursor).unwrap();
4121 let array = decoder.flush(None).unwrap();
4122 let dur = array
4123 .as_any()
4124 .downcast_ref::<DurationSecondArray>()
4125 .unwrap();
4126 assert_eq!(dur.values(), &[0, -1, 2]);
4127 }
4128
4129 #[test]
4130 #[cfg(feature = "avro_custom_types")]
4131 fn test_duration_milliseconds_decoding() {
4132 let avro_type = AvroDataType::new(Codec::DurationMillis, Default::default(), None);
4133 let mut decoder = Decoder::try_new(&avro_type).unwrap();
4134 let mut data = Vec::new();
4135 for v in [1i64, 0, -2] {
4136 data.extend_from_slice(&encode_avro_long(v));
4137 }
4138 let mut cursor = AvroCursor::new(&data);
4139 for _ in 0..3 {
4140 decoder.decode(&mut cursor).unwrap();
4141 }
4142 let array = decoder.flush(None).unwrap();
4143 let dur = array
4144 .as_any()
4145 .downcast_ref::<DurationMillisecondArray>()
4146 .unwrap();
4147 assert_eq!(dur.values(), &[1, 0, -2]);
4148 }
4149
4150 #[test]
4151 #[cfg(feature = "avro_custom_types")]
4152 fn test_duration_microseconds_decoding() {
4153 let avro_type = AvroDataType::new(Codec::DurationMicros, Default::default(), None);
4154 let mut decoder = Decoder::try_new(&avro_type).unwrap();
4155 let mut data = Vec::new();
4156 for v in [5i64, -6, 7] {
4157 data.extend_from_slice(&encode_avro_long(v));
4158 }
4159 let mut cursor = AvroCursor::new(&data);
4160 for _ in 0..3 {
4161 decoder.decode(&mut cursor).unwrap();
4162 }
4163 let array = decoder.flush(None).unwrap();
4164 let dur = array
4165 .as_any()
4166 .downcast_ref::<DurationMicrosecondArray>()
4167 .unwrap();
4168 assert_eq!(dur.values(), &[5, -6, 7]);
4169 }
4170
4171 #[test]
4172 #[cfg(feature = "avro_custom_types")]
4173 fn test_duration_nanoseconds_decoding() {
4174 let avro_type = AvroDataType::new(Codec::DurationNanos, Default::default(), None);
4175 let mut decoder = Decoder::try_new(&avro_type).unwrap();
4176 let mut data = Vec::new();
4177 for v in [8i64, 9, -10] {
4178 data.extend_from_slice(&encode_avro_long(v));
4179 }
4180 let mut cursor = AvroCursor::new(&data);
4181 for _ in 0..3 {
4182 decoder.decode(&mut cursor).unwrap();
4183 }
4184 let array = decoder.flush(None).unwrap();
4185 let dur = array
4186 .as_any()
4187 .downcast_ref::<DurationNanosecondArray>()
4188 .unwrap();
4189 assert_eq!(dur.values(), &[8, 9, -10]);
4190 }
4191
4192 #[test]
4193 fn test_nullable_decode_error_bitmap_corruption() {
4194 let avro_type = AvroDataType::new(
4196 Codec::Int32,
4197 Default::default(),
4198 Some(Nullability::NullSecond),
4199 );
4200 let mut decoder = Decoder::try_new(&avro_type).unwrap();
4201
4202 let mut row1 = Vec::new();
4204 row1.extend_from_slice(&encode_avro_int(1));
4205
4206 let mut row2 = Vec::new();
4208 row2.extend_from_slice(&encode_avro_int(0)); let mut row3 = Vec::new();
4212 row3.extend_from_slice(&encode_avro_int(0)); row3.extend_from_slice(&encode_avro_int(42)); decoder.decode(&mut AvroCursor::new(&row1)).unwrap();
4216 assert!(decoder.decode(&mut AvroCursor::new(&row2)).is_err()); decoder.decode(&mut AvroCursor::new(&row3)).unwrap();
4218
4219 let array = decoder.flush(None).unwrap();
4220
4221 assert_eq!(array.len(), 2);
4223 let int_array = array.as_any().downcast_ref::<Int32Array>().unwrap();
4224 assert!(int_array.is_null(0)); assert_eq!(int_array.value(1), 42); }
4227
4228 #[test]
4229 fn test_enum_mapping_reordered_symbols() {
4230 let reader_symbols: Arc<[String]> =
4231 vec!["B".to_string(), "C".to_string(), "A".to_string()].into();
4232 let mapping: Arc<[i32]> = Arc::from(vec![2, 0, 1]);
4233 let default_index: i32 = -1;
4234 let mut dec = Decoder::Enum(
4235 Vec::with_capacity(DEFAULT_CAPACITY),
4236 reader_symbols.clone(),
4237 Some(EnumResolution {
4238 mapping,
4239 default_index,
4240 }),
4241 );
4242 let mut data = Vec::new();
4243 data.extend_from_slice(&encode_avro_int(0));
4244 data.extend_from_slice(&encode_avro_int(1));
4245 data.extend_from_slice(&encode_avro_int(2));
4246 let mut cur = AvroCursor::new(&data);
4247 dec.decode(&mut cur).unwrap();
4248 dec.decode(&mut cur).unwrap();
4249 dec.decode(&mut cur).unwrap();
4250 let arr = dec.flush(None).unwrap();
4251 let dict = arr
4252 .as_any()
4253 .downcast_ref::<DictionaryArray<Int32Type>>()
4254 .unwrap();
4255 let expected_keys = Int32Array::from(vec![2, 0, 1]);
4256 assert_eq!(dict.keys(), &expected_keys);
4257 let values = dict
4258 .values()
4259 .as_any()
4260 .downcast_ref::<StringArray>()
4261 .unwrap();
4262 assert_eq!(values.value(0), "B");
4263 assert_eq!(values.value(1), "C");
4264 assert_eq!(values.value(2), "A");
4265 }
4266
4267 #[test]
4268 fn test_enum_mapping_unknown_symbol_and_out_of_range_fall_back_to_default() {
4269 let reader_symbols: Arc<[String]> = vec!["A".to_string(), "B".to_string()].into();
4270 let default_index: i32 = 1;
4271 let mapping: Arc<[i32]> = Arc::from(vec![0, 1]);
4272 let mut dec = Decoder::Enum(
4273 Vec::with_capacity(DEFAULT_CAPACITY),
4274 reader_symbols.clone(),
4275 Some(EnumResolution {
4276 mapping,
4277 default_index,
4278 }),
4279 );
4280 let mut data = Vec::new();
4281 data.extend_from_slice(&encode_avro_int(0));
4282 data.extend_from_slice(&encode_avro_int(1));
4283 data.extend_from_slice(&encode_avro_int(99));
4284 let mut cur = AvroCursor::new(&data);
4285 dec.decode(&mut cur).unwrap();
4286 dec.decode(&mut cur).unwrap();
4287 dec.decode(&mut cur).unwrap();
4288 let arr = dec.flush(None).unwrap();
4289 let dict = arr
4290 .as_any()
4291 .downcast_ref::<DictionaryArray<Int32Type>>()
4292 .unwrap();
4293 let expected_keys = Int32Array::from(vec![0, 1, 1]);
4294 assert_eq!(dict.keys(), &expected_keys);
4295 let values = dict
4296 .values()
4297 .as_any()
4298 .downcast_ref::<StringArray>()
4299 .unwrap();
4300 assert_eq!(values.value(0), "A");
4301 assert_eq!(values.value(1), "B");
4302 }
4303
4304 #[test]
4305 fn test_enum_mapping_unknown_symbol_without_default_errors() {
4306 let reader_symbols: Arc<[String]> = vec!["A".to_string()].into();
4307 let default_index: i32 = -1; let mapping: Arc<[i32]> = Arc::from(vec![-1]);
4309 let mut dec = Decoder::Enum(
4310 Vec::with_capacity(DEFAULT_CAPACITY),
4311 reader_symbols,
4312 Some(EnumResolution {
4313 mapping,
4314 default_index,
4315 }),
4316 );
4317 let data = encode_avro_int(0);
4318 let mut cur = AvroCursor::new(&data);
4319 let err = dec
4320 .decode(&mut cur)
4321 .expect_err("expected decode error for unresolved enum without default");
4322 let msg = err.to_string();
4323 assert!(
4324 msg.contains("not resolvable") && msg.contains("no default"),
4325 "unexpected error message: {msg}"
4326 );
4327 }
4328
4329 fn make_record_resolved_decoder(
4330 reader_fields: &[(&str, DataType, bool)],
4331 writer_projections: Vec<FieldProjection>,
4332 ) -> Decoder {
4333 let mut field_refs: Vec<FieldRef> = Vec::with_capacity(reader_fields.len());
4334 let mut encodings: Vec<Decoder> = Vec::with_capacity(reader_fields.len());
4335 for (name, dt, nullable) in reader_fields {
4336 field_refs.push(Arc::new(ArrowField::new(*name, dt.clone(), *nullable)));
4337 let enc = match dt {
4338 DataType::Int32 => Decoder::Int32(Vec::new()),
4339 DataType::Int64 => Decoder::Int64(Vec::new()),
4340 DataType::Utf8 => {
4341 Decoder::String(OffsetBufferBuilder::new(DEFAULT_CAPACITY), Vec::new())
4342 }
4343 other => panic!("Unsupported test reader field type: {other:?}"),
4344 };
4345 encodings.push(enc);
4346 }
4347 let fields: Fields = field_refs.into();
4348 Decoder::Record {
4349 fields,
4350 decoders: encodings,
4351 defaults: vec![None; reader_fields.len()],
4352 projector: Some(Projector {
4353 writer_projections,
4354 default_injections: Arc::from(Vec::<(usize, AvroLiteral)>::new()),
4355 }),
4356 row_count: 0,
4357 }
4358 }
4359
4360 #[test]
4361 fn test_skip_writer_trailing_field_int32() {
4362 let mut dec = make_record_resolved_decoder(
4363 &[("id", arrow_schema::DataType::Int32, false)],
4364 vec![
4365 FieldProjection::ToReader(0),
4366 FieldProjection::Skip(super::Skipper::Int32),
4367 ],
4368 );
4369 let mut data = Vec::new();
4370 data.extend_from_slice(&encode_avro_int(7));
4371 data.extend_from_slice(&encode_avro_int(999));
4372 let mut cur = AvroCursor::new(&data);
4373 dec.decode(&mut cur).unwrap();
4374 assert_eq!(cur.position(), data.len());
4375 let arr = dec.flush(None).unwrap();
4376 let struct_arr = arr.as_any().downcast_ref::<StructArray>().unwrap();
4377 assert_eq!(struct_arr.len(), 1);
4378 let id = struct_arr
4379 .column_by_name("id")
4380 .unwrap()
4381 .as_any()
4382 .downcast_ref::<Int32Array>()
4383 .unwrap();
4384 assert_eq!(id.value(0), 7);
4385 }
4386
4387 #[test]
4388 fn test_skip_writer_middle_field_string() {
4389 let mut dec = make_record_resolved_decoder(
4390 &[
4391 ("id", DataType::Int32, false),
4392 ("score", DataType::Int64, false),
4393 ],
4394 vec![
4395 FieldProjection::ToReader(0),
4396 FieldProjection::Skip(Skipper::String),
4397 FieldProjection::ToReader(1),
4398 ],
4399 );
4400 let mut data = Vec::new();
4401 data.extend_from_slice(&encode_avro_int(42));
4402 data.extend_from_slice(&encode_avro_bytes(b"abcdef"));
4403 data.extend_from_slice(&encode_avro_long(1000));
4404 let mut cur = AvroCursor::new(&data);
4405 dec.decode(&mut cur).unwrap();
4406 assert_eq!(cur.position(), data.len());
4407 let arr = dec.flush(None).unwrap();
4408 let s = arr.as_any().downcast_ref::<StructArray>().unwrap();
4409 let id = s
4410 .column_by_name("id")
4411 .unwrap()
4412 .as_any()
4413 .downcast_ref::<Int32Array>()
4414 .unwrap();
4415 let score = s
4416 .column_by_name("score")
4417 .unwrap()
4418 .as_any()
4419 .downcast_ref::<Int64Array>()
4420 .unwrap();
4421 assert_eq!(id.value(0), 42);
4422 assert_eq!(score.value(0), 1000);
4423 }
4424
4425 #[test]
4426 fn test_skip_writer_array_with_negative_block_count_fast() {
4427 let mut dec = make_record_resolved_decoder(
4428 &[("id", DataType::Int32, false)],
4429 vec![
4430 FieldProjection::Skip(super::Skipper::List(Box::new(Skipper::Int32))),
4431 FieldProjection::ToReader(0),
4432 ],
4433 );
4434 let mut array_payload = Vec::new();
4435 array_payload.extend_from_slice(&encode_avro_int(1));
4436 array_payload.extend_from_slice(&encode_avro_int(2));
4437 array_payload.extend_from_slice(&encode_avro_int(3));
4438 let mut data = Vec::new();
4439 data.extend_from_slice(&encode_avro_long(-3));
4440 data.extend_from_slice(&encode_avro_long(array_payload.len() as i64));
4441 data.extend_from_slice(&array_payload);
4442 data.extend_from_slice(&encode_avro_long(0));
4443 data.extend_from_slice(&encode_avro_int(5));
4444 let mut cur = AvroCursor::new(&data);
4445 dec.decode(&mut cur).unwrap();
4446 assert_eq!(cur.position(), data.len());
4447 let arr = dec.flush(None).unwrap();
4448 let s = arr.as_any().downcast_ref::<StructArray>().unwrap();
4449 let id = s
4450 .column_by_name("id")
4451 .unwrap()
4452 .as_any()
4453 .downcast_ref::<Int32Array>()
4454 .unwrap();
4455 assert_eq!(id.len(), 1);
4456 assert_eq!(id.value(0), 5);
4457 }
4458
4459 #[test]
4460 fn test_skip_writer_map_with_negative_block_count_fast() {
4461 let mut dec = make_record_resolved_decoder(
4462 &[("id", DataType::Int32, false)],
4463 vec![
4464 FieldProjection::Skip(Skipper::Map(Box::new(Skipper::Int32))),
4465 FieldProjection::ToReader(0),
4466 ],
4467 );
4468 let mut entries = Vec::new();
4469 entries.extend_from_slice(&encode_avro_bytes(b"k1"));
4470 entries.extend_from_slice(&encode_avro_int(10));
4471 entries.extend_from_slice(&encode_avro_bytes(b"k2"));
4472 entries.extend_from_slice(&encode_avro_int(20));
4473 let mut data = Vec::new();
4474 data.extend_from_slice(&encode_avro_long(-2));
4475 data.extend_from_slice(&encode_avro_long(entries.len() as i64));
4476 data.extend_from_slice(&entries);
4477 data.extend_from_slice(&encode_avro_long(0));
4478 data.extend_from_slice(&encode_avro_int(123));
4479 let mut cur = AvroCursor::new(&data);
4480 dec.decode(&mut cur).unwrap();
4481 assert_eq!(cur.position(), data.len());
4482 let arr = dec.flush(None).unwrap();
4483 let s = arr.as_any().downcast_ref::<StructArray>().unwrap();
4484 let id = s
4485 .column_by_name("id")
4486 .unwrap()
4487 .as_any()
4488 .downcast_ref::<Int32Array>()
4489 .unwrap();
4490 assert_eq!(id.len(), 1);
4491 assert_eq!(id.value(0), 123);
4492 }
4493
4494 #[test]
4495 fn test_skip_writer_nullable_field_union_nullfirst() {
4496 let mut dec = make_record_resolved_decoder(
4497 &[("id", DataType::Int32, false)],
4498 vec![
4499 FieldProjection::Skip(super::Skipper::Nullable(
4500 Nullability::NullFirst,
4501 Box::new(super::Skipper::Int32),
4502 )),
4503 FieldProjection::ToReader(0),
4504 ],
4505 );
4506 let mut row1 = Vec::new();
4507 row1.extend_from_slice(&encode_avro_long(0));
4508 row1.extend_from_slice(&encode_avro_int(5));
4509 let mut row2 = Vec::new();
4510 row2.extend_from_slice(&encode_avro_long(1));
4511 row2.extend_from_slice(&encode_avro_int(123));
4512 row2.extend_from_slice(&encode_avro_int(7));
4513 let mut cur1 = AvroCursor::new(&row1);
4514 let mut cur2 = AvroCursor::new(&row2);
4515 dec.decode(&mut cur1).unwrap();
4516 dec.decode(&mut cur2).unwrap();
4517 assert_eq!(cur1.position(), row1.len());
4518 assert_eq!(cur2.position(), row2.len());
4519 let arr = dec.flush(None).unwrap();
4520 let s = arr.as_any().downcast_ref::<StructArray>().unwrap();
4521 let id = s
4522 .column_by_name("id")
4523 .unwrap()
4524 .as_any()
4525 .downcast_ref::<Int32Array>()
4526 .unwrap();
4527 assert_eq!(id.len(), 2);
4528 assert_eq!(id.value(0), 5);
4529 assert_eq!(id.value(1), 7);
4530 }
4531
4532 fn make_dense_union_avro(
4533 children: Vec<(Codec, &'_ str, DataType)>,
4534 type_ids: Vec<i8>,
4535 ) -> AvroDataType {
4536 let mut avro_children: Vec<AvroDataType> = Vec::with_capacity(children.len());
4537 let mut fields: Vec<arrow_schema::Field> = Vec::with_capacity(children.len());
4538 for (codec, name, dt) in children {
4539 avro_children.push(AvroDataType::new(codec, Default::default(), None));
4540 fields.push(arrow_schema::Field::new(name, dt, true));
4541 }
4542 let union_fields = UnionFields::try_new(type_ids, fields).unwrap();
4543 let union_codec = Codec::Union(avro_children.into(), union_fields, UnionMode::Dense);
4544 AvroDataType::new(union_codec, Default::default(), None)
4545 }
4546
4547 #[test]
4548 fn test_union_dense_two_children_custom_type_ids() {
4549 let union_dt = make_dense_union_avro(
4550 vec![
4551 (Codec::Int32, "i", DataType::Int32),
4552 (Codec::Utf8, "s", DataType::Utf8),
4553 ],
4554 vec![2, 5],
4555 );
4556 let mut dec = Decoder::try_new(&union_dt).unwrap();
4557 let mut r1 = Vec::new();
4558 r1.extend_from_slice(&encode_avro_long(0));
4559 r1.extend_from_slice(&encode_avro_int(7));
4560 let mut r2 = Vec::new();
4561 r2.extend_from_slice(&encode_avro_long(1));
4562 r2.extend_from_slice(&encode_avro_bytes(b"x"));
4563 let mut r3 = Vec::new();
4564 r3.extend_from_slice(&encode_avro_long(0));
4565 r3.extend_from_slice(&encode_avro_int(-1));
4566 dec.decode(&mut AvroCursor::new(&r1)).unwrap();
4567 dec.decode(&mut AvroCursor::new(&r2)).unwrap();
4568 dec.decode(&mut AvroCursor::new(&r3)).unwrap();
4569 let array = dec.flush(None).unwrap();
4570 let ua = array
4571 .as_any()
4572 .downcast_ref::<UnionArray>()
4573 .expect("expected UnionArray");
4574 assert_eq!(ua.len(), 3);
4575 assert_eq!(ua.type_id(0), 2);
4576 assert_eq!(ua.type_id(1), 5);
4577 assert_eq!(ua.type_id(2), 2);
4578 assert_eq!(ua.value_offset(0), 0);
4579 assert_eq!(ua.value_offset(1), 0);
4580 assert_eq!(ua.value_offset(2), 1);
4581 let int_child = ua
4582 .child(2)
4583 .as_any()
4584 .downcast_ref::<Int32Array>()
4585 .expect("int child");
4586 assert_eq!(int_child.len(), 2);
4587 assert_eq!(int_child.value(0), 7);
4588 assert_eq!(int_child.value(1), -1);
4589 let str_child = ua
4590 .child(5)
4591 .as_any()
4592 .downcast_ref::<StringArray>()
4593 .expect("string child");
4594 assert_eq!(str_child.len(), 1);
4595 assert_eq!(str_child.value(0), "x");
4596 }
4597
4598 #[test]
4599 fn test_union_dense_with_null_and_string_children() {
4600 let union_dt = make_dense_union_avro(
4601 vec![
4602 (Codec::Null, "n", DataType::Null),
4603 (Codec::Utf8, "s", DataType::Utf8),
4604 ],
4605 vec![42, 7],
4606 );
4607 let mut dec = Decoder::try_new(&union_dt).unwrap();
4608 let r1 = encode_avro_long(0);
4609 let mut r2 = Vec::new();
4610 r2.extend_from_slice(&encode_avro_long(1));
4611 r2.extend_from_slice(&encode_avro_bytes(b"abc"));
4612 let r3 = encode_avro_long(0);
4613 dec.decode(&mut AvroCursor::new(&r1)).unwrap();
4614 dec.decode(&mut AvroCursor::new(&r2)).unwrap();
4615 dec.decode(&mut AvroCursor::new(&r3)).unwrap();
4616 let array = dec.flush(None).unwrap();
4617 let ua = array
4618 .as_any()
4619 .downcast_ref::<UnionArray>()
4620 .expect("expected UnionArray");
4621 assert_eq!(ua.len(), 3);
4622 assert_eq!(ua.type_id(0), 42);
4623 assert_eq!(ua.type_id(1), 7);
4624 assert_eq!(ua.type_id(2), 42);
4625 assert_eq!(ua.value_offset(0), 0);
4626 assert_eq!(ua.value_offset(1), 0);
4627 assert_eq!(ua.value_offset(2), 1);
4628 let null_child = ua
4629 .child(42)
4630 .as_any()
4631 .downcast_ref::<NullArray>()
4632 .expect("null child");
4633 assert_eq!(null_child.len(), 2);
4634 let str_child = ua
4635 .child(7)
4636 .as_any()
4637 .downcast_ref::<StringArray>()
4638 .expect("string child");
4639 assert_eq!(str_child.len(), 1);
4640 assert_eq!(str_child.value(0), "abc");
4641 }
4642
4643 #[test]
4644 fn test_union_dense_offsets_reset_after_flush() {
4645 let union_dt = make_dense_union_avro(
4646 vec![
4647 (Codec::Null, "n", DataType::Null),
4648 (Codec::Utf8, "s", DataType::Utf8),
4649 ],
4650 vec![0, 1],
4651 );
4652 let mut dec = Decoder::try_new(&union_dt).unwrap();
4653
4654 for _ in 0..2 {
4655 dec.decode(&mut AvroCursor::new(&encode_avro_long(0)))
4656 .unwrap();
4657 let array = dec.flush(None).unwrap();
4658 let union = array.as_union();
4659 assert_eq!(union.value_offset(0), 0);
4660 }
4661 }
4662
4663 #[test]
4664 fn test_union_decode_negative_branch_index_errors() {
4665 let union_dt = make_dense_union_avro(
4666 vec![
4667 (Codec::Int32, "i", DataType::Int32),
4668 (Codec::Utf8, "s", DataType::Utf8),
4669 ],
4670 vec![0, 1],
4671 );
4672 let mut dec = Decoder::try_new(&union_dt).unwrap();
4673 let row = encode_avro_long(-1); let err = dec
4675 .decode(&mut AvroCursor::new(&row))
4676 .expect_err("expected error for negative branch index");
4677 let msg = err.to_string();
4678 assert!(
4679 msg.contains("Negative union branch index"),
4680 "unexpected error message: {msg}"
4681 );
4682 }
4683
4684 #[test]
4685 fn test_union_decode_out_of_range_branch_index_errors() {
4686 let union_dt = make_dense_union_avro(
4687 vec![
4688 (Codec::Int32, "i", DataType::Int32),
4689 (Codec::Utf8, "s", DataType::Utf8),
4690 ],
4691 vec![10, 11],
4692 );
4693 let mut dec = Decoder::try_new(&union_dt).unwrap();
4694 let row = encode_avro_long(2);
4695 let err = dec
4696 .decode(&mut AvroCursor::new(&row))
4697 .expect_err("expected error for out-of-range branch index");
4698 let msg = err.to_string();
4699 assert!(
4700 msg.contains("out of range"),
4701 "unexpected error message: {msg}"
4702 );
4703 }
4704
4705 #[test]
4706 fn test_union_sparse_mode_not_supported() {
4707 let children: Vec<AvroDataType> = vec![
4708 AvroDataType::new(Codec::Int32, Default::default(), None),
4709 AvroDataType::new(Codec::Utf8, Default::default(), None),
4710 ];
4711 let uf = UnionFields::try_new(
4712 vec![1, 3],
4713 vec![
4714 arrow_schema::Field::new("i", DataType::Int32, true),
4715 arrow_schema::Field::new("s", DataType::Utf8, true),
4716 ],
4717 )
4718 .unwrap();
4719 let codec = Codec::Union(children.into(), uf, UnionMode::Sparse);
4720 let dt = AvroDataType::new(codec, Default::default(), None);
4721 let err = Decoder::try_new(&dt).expect_err("sparse union should not be supported");
4722 let msg = err.to_string();
4723 assert!(
4724 msg.contains("Sparse Arrow unions are not yet supported"),
4725 "unexpected error message: {msg}"
4726 );
4727 }
4728
4729 fn make_record_decoder_with_projector_defaults(
4730 reader_fields: &[(&str, DataType, bool)],
4731 field_defaults: Vec<Option<AvroLiteral>>,
4732 default_injections: Vec<(usize, AvroLiteral)>,
4733 ) -> Decoder {
4734 assert_eq!(
4735 field_defaults.len(),
4736 reader_fields.len(),
4737 "field_defaults must have one entry per reader field"
4738 );
4739 let mut field_refs: Vec<FieldRef> = Vec::with_capacity(reader_fields.len());
4740 let mut encodings: Vec<Decoder> = Vec::with_capacity(reader_fields.len());
4741 for (name, dt, nullable) in reader_fields {
4742 field_refs.push(Arc::new(ArrowField::new(*name, dt.clone(), *nullable)));
4743 let enc = match dt {
4744 DataType::Int32 => Decoder::Int32(Vec::with_capacity(DEFAULT_CAPACITY)),
4745 DataType::Int64 => Decoder::Int64(Vec::with_capacity(DEFAULT_CAPACITY)),
4746 DataType::Utf8 => Decoder::String(
4747 OffsetBufferBuilder::new(DEFAULT_CAPACITY),
4748 Vec::with_capacity(DEFAULT_CAPACITY),
4749 ),
4750 other => panic!("Unsupported test field type in helper: {other:?}"),
4751 };
4752 encodings.push(enc);
4753 }
4754 let fields: Fields = field_refs.into();
4755 let projector = Projector {
4756 writer_projections: vec![],
4757 default_injections: Arc::from(default_injections),
4758 };
4759 Decoder::Record {
4760 fields,
4761 decoders: encodings,
4762 defaults: field_defaults,
4763 projector: Some(projector),
4764 row_count: 0,
4765 }
4766 }
4767
4768 #[cfg(feature = "avro_custom_types")]
4769 #[test]
4770 fn test_default_append_custom_integer_range_validation() {
4771 let mut d_i8 = Decoder::Int8(Vec::with_capacity(DEFAULT_CAPACITY));
4772 d_i8.append_default(&AvroLiteral::Int(i8::MIN as i32))
4773 .unwrap();
4774 d_i8.append_default(&AvroLiteral::Int(i8::MAX as i32))
4775 .unwrap();
4776 let err_i8_high = d_i8
4777 .append_default(&AvroLiteral::Int(i8::MAX as i32 + 1))
4778 .unwrap_err();
4779 assert!(err_i8_high.to_string().contains("out of range for i8"));
4780 let err_i8_low = d_i8
4781 .append_default(&AvroLiteral::Int(i8::MIN as i32 - 1))
4782 .unwrap_err();
4783 assert!(err_i8_low.to_string().contains("out of range for i8"));
4784 let arr_i8 = d_i8.flush(None).unwrap();
4785 let values_i8 = arr_i8.as_any().downcast_ref::<Int8Array>().unwrap();
4786 assert_eq!(values_i8.values(), &[i8::MIN, i8::MAX]);
4787
4788 let mut d_i16 = Decoder::Int16(Vec::with_capacity(DEFAULT_CAPACITY));
4789 d_i16
4790 .append_default(&AvroLiteral::Int(i16::MIN as i32))
4791 .unwrap();
4792 d_i16
4793 .append_default(&AvroLiteral::Int(i16::MAX as i32))
4794 .unwrap();
4795 let err_i16_high = d_i16
4796 .append_default(&AvroLiteral::Int(i16::MAX as i32 + 1))
4797 .unwrap_err();
4798 assert!(err_i16_high.to_string().contains("out of range for i16"));
4799 let err_i16_low = d_i16
4800 .append_default(&AvroLiteral::Int(i16::MIN as i32 - 1))
4801 .unwrap_err();
4802 assert!(err_i16_low.to_string().contains("out of range for i16"));
4803 let arr_i16 = d_i16.flush(None).unwrap();
4804 let values_i16 = arr_i16.as_any().downcast_ref::<Int16Array>().unwrap();
4805 assert_eq!(values_i16.values(), &[i16::MIN, i16::MAX]);
4806
4807 let mut d_u8 = Decoder::UInt8(Vec::with_capacity(DEFAULT_CAPACITY));
4808 d_u8.append_default(&AvroLiteral::Int(0)).unwrap();
4809 d_u8.append_default(&AvroLiteral::Int(u8::MAX as i32))
4810 .unwrap();
4811 let err_u8_neg = d_u8.append_default(&AvroLiteral::Int(-1)).unwrap_err();
4812 assert!(err_u8_neg.to_string().contains("out of range for u8"));
4813 let err_u8_high = d_u8
4814 .append_default(&AvroLiteral::Int(u8::MAX as i32 + 1))
4815 .unwrap_err();
4816 assert!(err_u8_high.to_string().contains("out of range for u8"));
4817 let arr_u8 = d_u8.flush(None).unwrap();
4818 let values_u8 = arr_u8.as_any().downcast_ref::<UInt8Array>().unwrap();
4819 assert_eq!(values_u8.values(), &[0, u8::MAX]);
4820
4821 let mut d_u16 = Decoder::UInt16(Vec::with_capacity(DEFAULT_CAPACITY));
4822 d_u16.append_default(&AvroLiteral::Int(0)).unwrap();
4823 d_u16
4824 .append_default(&AvroLiteral::Int(u16::MAX as i32))
4825 .unwrap();
4826 let err_u16_neg = d_u16.append_default(&AvroLiteral::Int(-1)).unwrap_err();
4827 assert!(err_u16_neg.to_string().contains("out of range for u16"));
4828 let err_u16_high = d_u16
4829 .append_default(&AvroLiteral::Int(u16::MAX as i32 + 1))
4830 .unwrap_err();
4831 assert!(err_u16_high.to_string().contains("out of range for u16"));
4832 let arr_u16 = d_u16.flush(None).unwrap();
4833 let values_u16 = arr_u16.as_any().downcast_ref::<UInt16Array>().unwrap();
4834 assert_eq!(values_u16.values(), &[0, u16::MAX]);
4835
4836 let mut d_u32 = Decoder::UInt32(Vec::with_capacity(DEFAULT_CAPACITY));
4837 d_u32.append_default(&AvroLiteral::Long(0)).unwrap();
4838 d_u32
4839 .append_default(&AvroLiteral::Long(u32::MAX as i64))
4840 .unwrap();
4841 let err_u32_neg = d_u32.append_default(&AvroLiteral::Long(-1)).unwrap_err();
4842 assert!(err_u32_neg.to_string().contains("out of range for u32"));
4843 let err_u32_high = d_u32
4844 .append_default(&AvroLiteral::Long(u32::MAX as i64 + 1))
4845 .unwrap_err();
4846 assert!(err_u32_high.to_string().contains("out of range for u32"));
4847 let arr_u32 = d_u32.flush(None).unwrap();
4848 let values_u32 = arr_u32.as_any().downcast_ref::<UInt32Array>().unwrap();
4849 assert_eq!(values_u32.values(), &[0, u32::MAX]);
4850 }
4851
4852 #[cfg(feature = "avro_custom_types")]
4853 #[test]
4854 fn test_decode_custom_integer_range_validation() {
4855 let mut d_i8 = Decoder::try_new(&avro_from_codec(Codec::Int8)).unwrap();
4856 d_i8.decode(&mut AvroCursor::new(&encode_avro_int(i8::MIN as i32)))
4857 .unwrap();
4858 d_i8.decode(&mut AvroCursor::new(&encode_avro_int(i8::MAX as i32)))
4859 .unwrap();
4860 let err_i8_high = d_i8
4861 .decode(&mut AvroCursor::new(&encode_avro_int(i8::MAX as i32 + 1)))
4862 .unwrap_err();
4863 assert!(err_i8_high.to_string().contains("out of range for i8"));
4864 let err_i8_low = d_i8
4865 .decode(&mut AvroCursor::new(&encode_avro_int(i8::MIN as i32 - 1)))
4866 .unwrap_err();
4867 assert!(err_i8_low.to_string().contains("out of range for i8"));
4868 let arr_i8 = d_i8.flush(None).unwrap();
4869 let values_i8 = arr_i8.as_any().downcast_ref::<Int8Array>().unwrap();
4870 assert_eq!(values_i8.values(), &[i8::MIN, i8::MAX]);
4871
4872 let mut d_i16 = Decoder::try_new(&avro_from_codec(Codec::Int16)).unwrap();
4873 d_i16
4874 .decode(&mut AvroCursor::new(&encode_avro_int(i16::MIN as i32)))
4875 .unwrap();
4876 d_i16
4877 .decode(&mut AvroCursor::new(&encode_avro_int(i16::MAX as i32)))
4878 .unwrap();
4879 let err_i16_high = d_i16
4880 .decode(&mut AvroCursor::new(&encode_avro_int(i16::MAX as i32 + 1)))
4881 .unwrap_err();
4882 assert!(err_i16_high.to_string().contains("out of range for i16"));
4883 let err_i16_low = d_i16
4884 .decode(&mut AvroCursor::new(&encode_avro_int(i16::MIN as i32 - 1)))
4885 .unwrap_err();
4886 assert!(err_i16_low.to_string().contains("out of range for i16"));
4887 let arr_i16 = d_i16.flush(None).unwrap();
4888 let values_i16 = arr_i16.as_any().downcast_ref::<Int16Array>().unwrap();
4889 assert_eq!(values_i16.values(), &[i16::MIN, i16::MAX]);
4890
4891 let mut d_u8 = Decoder::try_new(&avro_from_codec(Codec::UInt8)).unwrap();
4892 d_u8.decode(&mut AvroCursor::new(&encode_avro_int(0)))
4893 .unwrap();
4894 d_u8.decode(&mut AvroCursor::new(&encode_avro_int(u8::MAX as i32)))
4895 .unwrap();
4896 let err_u8_neg = d_u8
4897 .decode(&mut AvroCursor::new(&encode_avro_int(-1)))
4898 .unwrap_err();
4899 assert!(err_u8_neg.to_string().contains("out of range for u8"));
4900 let err_u8_high = d_u8
4901 .decode(&mut AvroCursor::new(&encode_avro_int(u8::MAX as i32 + 1)))
4902 .unwrap_err();
4903 assert!(err_u8_high.to_string().contains("out of range for u8"));
4904 let arr_u8 = d_u8.flush(None).unwrap();
4905 let values_u8 = arr_u8.as_any().downcast_ref::<UInt8Array>().unwrap();
4906 assert_eq!(values_u8.values(), &[0, u8::MAX]);
4907
4908 let mut d_u16 = Decoder::try_new(&avro_from_codec(Codec::UInt16)).unwrap();
4909 d_u16
4910 .decode(&mut AvroCursor::new(&encode_avro_int(0)))
4911 .unwrap();
4912 d_u16
4913 .decode(&mut AvroCursor::new(&encode_avro_int(u16::MAX as i32)))
4914 .unwrap();
4915 let err_u16_neg = d_u16
4916 .decode(&mut AvroCursor::new(&encode_avro_int(-1)))
4917 .unwrap_err();
4918 assert!(err_u16_neg.to_string().contains("out of range for u16"));
4919 let err_u16_high = d_u16
4920 .decode(&mut AvroCursor::new(&encode_avro_int(u16::MAX as i32 + 1)))
4921 .unwrap_err();
4922 assert!(err_u16_high.to_string().contains("out of range for u16"));
4923 let arr_u16 = d_u16.flush(None).unwrap();
4924 let values_u16 = arr_u16.as_any().downcast_ref::<UInt16Array>().unwrap();
4925 assert_eq!(values_u16.values(), &[0, u16::MAX]);
4926
4927 let mut d_u32 = Decoder::try_new(&avro_from_codec(Codec::UInt32)).unwrap();
4928 d_u32
4929 .decode(&mut AvroCursor::new(&encode_avro_long(0)))
4930 .unwrap();
4931 d_u32
4932 .decode(&mut AvroCursor::new(&encode_avro_long(u32::MAX as i64)))
4933 .unwrap();
4934 let err_u32_neg = d_u32
4935 .decode(&mut AvroCursor::new(&encode_avro_long(-1)))
4936 .unwrap_err();
4937 assert!(err_u32_neg.to_string().contains("out of range for u32"));
4938 let err_u32_high = d_u32
4939 .decode(&mut AvroCursor::new(&encode_avro_long(u32::MAX as i64 + 1)))
4940 .unwrap_err();
4941 assert!(err_u32_high.to_string().contains("out of range for u32"));
4942 let arr_u32 = d_u32.flush(None).unwrap();
4943 let values_u32 = arr_u32.as_any().downcast_ref::<UInt32Array>().unwrap();
4944 assert_eq!(values_u32.values(), &[0, u32::MAX]);
4945 }
4946
4947 #[test]
4948 fn test_default_append_int32_and_int64_from_int_and_long() {
4949 let mut d_i32 = Decoder::Int32(Vec::with_capacity(DEFAULT_CAPACITY));
4950 d_i32.append_default(&AvroLiteral::Int(42)).unwrap();
4951 let arr = d_i32.flush(None).unwrap();
4952 let a = arr.as_any().downcast_ref::<Int32Array>().unwrap();
4953 assert_eq!(a.len(), 1);
4954 assert_eq!(a.value(0), 42);
4955 let mut d_i64 = Decoder::Int64(Vec::with_capacity(DEFAULT_CAPACITY));
4956 d_i64.append_default(&AvroLiteral::Int(5)).unwrap();
4957 d_i64.append_default(&AvroLiteral::Long(7)).unwrap();
4958 let arr64 = d_i64.flush(None).unwrap();
4959 let a64 = arr64.as_any().downcast_ref::<Int64Array>().unwrap();
4960 assert_eq!(a64.len(), 2);
4961 assert_eq!(a64.value(0), 5);
4962 assert_eq!(a64.value(1), 7);
4963 }
4964
4965 #[test]
4966 fn test_default_append_floats_and_doubles() {
4967 let mut d_f32 = Decoder::Float32(Vec::with_capacity(DEFAULT_CAPACITY));
4968 d_f32.append_default(&AvroLiteral::Float(1.5)).unwrap();
4969 let arr32 = d_f32.flush(None).unwrap();
4970 let a = arr32.as_any().downcast_ref::<Float32Array>().unwrap();
4971 assert_eq!(a.value(0), 1.5);
4972 let mut d_f64 = Decoder::Float64(Vec::with_capacity(DEFAULT_CAPACITY));
4973 d_f64.append_default(&AvroLiteral::Double(2.25)).unwrap();
4974 let arr64 = d_f64.flush(None).unwrap();
4975 let b = arr64.as_any().downcast_ref::<Float64Array>().unwrap();
4976 assert_eq!(b.value(0), 2.25);
4977 }
4978
4979 #[test]
4980 fn test_default_append_string_and_bytes() {
4981 let mut d_str = Decoder::String(
4982 OffsetBufferBuilder::new(DEFAULT_CAPACITY),
4983 Vec::with_capacity(DEFAULT_CAPACITY),
4984 );
4985 d_str
4986 .append_default(&AvroLiteral::String("hi".into()))
4987 .unwrap();
4988 let s_arr = d_str.flush(None).unwrap();
4989 let arr = s_arr.as_any().downcast_ref::<StringArray>().unwrap();
4990 assert_eq!(arr.value(0), "hi");
4991 let mut d_bytes = Decoder::Binary(
4992 OffsetBufferBuilder::new(DEFAULT_CAPACITY),
4993 Vec::with_capacity(DEFAULT_CAPACITY),
4994 );
4995 d_bytes
4996 .append_default(&AvroLiteral::Bytes(vec![1, 2, 3]))
4997 .unwrap();
4998 let b_arr = d_bytes.flush(None).unwrap();
4999 let barr = b_arr.as_any().downcast_ref::<BinaryArray>().unwrap();
5000 assert_eq!(barr.value(0), &[1, 2, 3]);
5001 let mut d_str_err = Decoder::String(
5002 OffsetBufferBuilder::new(DEFAULT_CAPACITY),
5003 Vec::with_capacity(DEFAULT_CAPACITY),
5004 );
5005 let err = d_str_err
5006 .append_default(&AvroLiteral::Bytes(vec![0x61, 0x62]))
5007 .unwrap_err();
5008 assert!(
5009 err.to_string()
5010 .contains("Default for string must be string"),
5011 "unexpected error: {err:?}"
5012 );
5013 }
5014
5015 #[test]
5016 fn test_nullable_null_runs_defer_validity_and_values_together() {
5017 let mut decoder = Decoder::Nullable(NullableDecoder::new(
5018 NullablePlan::ReadTag {
5019 nullability: Nullability::NullFirst,
5020 resolution: ResolutionPlan::Promotion(Promotion::Direct),
5021 },
5022 Decoder::Int32(Vec::new()),
5023 ));
5024
5025 decoder.append_nulls(64).unwrap();
5026 let Decoder::Nullable(nullable) = &decoder else {
5027 unreachable!();
5028 };
5029 assert_eq!(nullable.pending_nulls, 64);
5030 assert_eq!(nullable.validity.len(), 0);
5031 let Decoder::Int32(values) = nullable.values.as_ref() else {
5032 unreachable!();
5033 };
5034 assert!(values.is_empty());
5035
5036 decoder.append_default(&AvroLiteral::Int(7)).unwrap();
5037 let Decoder::Nullable(nullable) = &decoder else {
5038 unreachable!();
5039 };
5040 assert_eq!(nullable.pending_nulls, 0);
5041 assert_eq!(nullable.validity.len(), 65);
5042 let Decoder::Int32(values) = nullable.values.as_ref() else {
5043 unreachable!();
5044 };
5045 assert_eq!(values.len(), 65);
5046 assert_eq!(values[64], 7);
5047
5048 decoder.append_nulls(32).unwrap();
5049 let values = decoder.flush(None).unwrap();
5050 assert_eq!(values.len(), 97);
5051 assert_eq!(values.null_count(), 96);
5052 assert_eq!(values.as_primitive::<Int32Type>().value(64), 7);
5053 }
5054
5055 #[test]
5056 fn test_default_append_nullable_int32_null_and_value() {
5057 let inner = Decoder::Int32(Vec::with_capacity(DEFAULT_CAPACITY));
5058 let mut dec = Decoder::Nullable(NullableDecoder::new(
5059 NullablePlan::ReadTag {
5060 nullability: Nullability::NullFirst,
5061 resolution: ResolutionPlan::Promotion(Promotion::Direct),
5062 },
5063 inner,
5064 ));
5065 dec.append_default(&AvroLiteral::Null).unwrap();
5066 dec.append_default(&AvroLiteral::Null).unwrap();
5067 dec.append_default(&AvroLiteral::Int(11)).unwrap();
5068 dec.append_default(&AvroLiteral::Null).unwrap();
5069 dec.append_default(&AvroLiteral::Null).unwrap();
5070 dec.append_default(&AvroLiteral::Int(12)).unwrap();
5071 let arr = dec.flush(None).unwrap();
5072 let a = arr.as_any().downcast_ref::<Int32Array>().unwrap();
5073 assert_eq!(a.len(), 6);
5074 assert!(a.is_null(0));
5075 assert!(a.is_null(1));
5076 assert_eq!(a.value(2), 11);
5077 assert!(a.is_null(3));
5078 assert!(a.is_null(4));
5079 assert_eq!(a.value(5), 12);
5080 }
5081
5082 #[test]
5083 fn test_default_append_array_of_ints() {
5084 let list_dt = avro_from_codec(Codec::List(Arc::new(avro_from_codec(Codec::Int32))));
5085 let mut d = Decoder::try_new(&list_dt).unwrap();
5086 let items = vec![
5087 AvroLiteral::Int(1),
5088 AvroLiteral::Int(2),
5089 AvroLiteral::Int(3),
5090 ];
5091 d.append_default(&AvroLiteral::Array(items)).unwrap();
5092 let arr = d.flush(None).unwrap();
5093 let list = arr.as_any().downcast_ref::<ListArray>().unwrap();
5094 assert_eq!(list.len(), 1);
5095 assert_eq!(list.value_length(0), 3);
5096 let vals = list.values().as_any().downcast_ref::<Int32Array>().unwrap();
5097 assert_eq!(vals.values(), &[1, 2, 3]);
5098 }
5099
5100 #[test]
5101 fn test_default_append_map_string_to_int() {
5102 let map_dt = avro_from_codec(Codec::Map(Arc::new(avro_from_codec(Codec::Int32))));
5103 let mut d = Decoder::try_new(&map_dt).unwrap();
5104 let mut m: IndexMap<String, AvroLiteral> = IndexMap::new();
5105 m.insert("k1".to_string(), AvroLiteral::Int(10));
5106 m.insert("k2".to_string(), AvroLiteral::Int(20));
5107 d.append_default(&AvroLiteral::Map(m)).unwrap();
5108 let arr = d.flush(None).unwrap();
5109 let map = arr.as_any().downcast_ref::<MapArray>().unwrap();
5110 assert_eq!(map.len(), 1);
5111 assert_eq!(map.value_length(0), 2);
5112 let binding = map.value(0);
5113 let entries = binding.as_any().downcast_ref::<StructArray>().unwrap();
5114 let k = entries
5115 .column_by_name("key")
5116 .unwrap()
5117 .as_any()
5118 .downcast_ref::<StringArray>()
5119 .unwrap();
5120 let v = entries
5121 .column_by_name("value")
5122 .unwrap()
5123 .as_any()
5124 .downcast_ref::<Int32Array>()
5125 .unwrap();
5126 let keys: std::collections::HashSet<&str> = (0..k.len()).map(|i| k.value(i)).collect();
5127 assert_eq!(keys, ["k1", "k2"].into_iter().collect());
5128 let vals: std::collections::HashSet<i32> = (0..v.len()).map(|i| v.value(i)).collect();
5129 assert_eq!(vals, [10, 20].into_iter().collect());
5130 }
5131
5132 #[test]
5133 fn test_default_append_enum_by_symbol() {
5134 let symbols: Arc<[String]> = vec!["A".into(), "B".into(), "C".into()].into();
5135 let mut d = Decoder::Enum(Vec::with_capacity(DEFAULT_CAPACITY), symbols.clone(), None);
5136 d.append_default(&AvroLiteral::Enum("B".into())).unwrap();
5137 let arr = d.flush(None).unwrap();
5138 let dict = arr
5139 .as_any()
5140 .downcast_ref::<DictionaryArray<Int32Type>>()
5141 .unwrap();
5142 assert_eq!(dict.len(), 1);
5143 let expected = Int32Array::from(vec![1]);
5144 assert_eq!(dict.keys(), &expected);
5145 let values = dict
5146 .values()
5147 .as_any()
5148 .downcast_ref::<StringArray>()
5149 .unwrap();
5150 assert_eq!(values.value(1), "B");
5151 }
5152
5153 #[test]
5154 fn test_default_append_uuid_and_type_error() {
5155 let mut d = Decoder::Uuid(Vec::with_capacity(DEFAULT_CAPACITY));
5156 let uuid_str = "123e4567-e89b-12d3-a456-426614174000";
5157 d.append_default(&AvroLiteral::String(uuid_str.into()))
5158 .unwrap();
5159 let arr_ref = d.flush(None).unwrap();
5160 let arr = arr_ref
5161 .as_any()
5162 .downcast_ref::<FixedSizeBinaryArray>()
5163 .unwrap();
5164 assert_eq!(arr.value_length(), 16);
5165 assert_eq!(arr.len(), 1);
5166 let mut d2 = Decoder::Uuid(Vec::with_capacity(DEFAULT_CAPACITY));
5167 let err = d2
5168 .append_default(&AvroLiteral::Bytes(vec![0u8; 16]))
5169 .unwrap_err();
5170 assert!(
5171 err.to_string().contains("Default for uuid must be string"),
5172 "unexpected error: {err:?}"
5173 );
5174 }
5175
5176 #[test]
5177 fn test_default_append_fixed_and_length_mismatch() {
5178 let mut d = Decoder::Fixed(4, Vec::with_capacity(DEFAULT_CAPACITY));
5179 d.append_default(&AvroLiteral::Bytes(vec![1, 2, 3, 4]))
5180 .unwrap();
5181 let arr_ref = d.flush(None).unwrap();
5182 let arr = arr_ref
5183 .as_any()
5184 .downcast_ref::<FixedSizeBinaryArray>()
5185 .unwrap();
5186 assert_eq!(arr.value_length(), 4);
5187 assert_eq!(arr.value(0), &[1, 2, 3, 4]);
5188 let mut d_err = Decoder::Fixed(4, Vec::with_capacity(DEFAULT_CAPACITY));
5189 let err = d_err
5190 .append_default(&AvroLiteral::Bytes(vec![1, 2, 3]))
5191 .unwrap_err();
5192 assert!(
5193 err.to_string().contains("Fixed default length"),
5194 "unexpected error: {err:?}"
5195 );
5196 }
5197
5198 #[test]
5199 fn test_default_append_duration_and_length_validation() {
5200 let dt = avro_from_codec(Codec::Interval);
5201 let mut d = Decoder::try_new(&dt).unwrap();
5202 let mut bytes = Vec::with_capacity(12);
5203 bytes.extend_from_slice(&1u32.to_le_bytes());
5204 bytes.extend_from_slice(&2u32.to_le_bytes());
5205 bytes.extend_from_slice(&3u32.to_le_bytes());
5206 d.append_default(&AvroLiteral::Bytes(bytes)).unwrap();
5207 let arr_ref = d.flush(None).unwrap();
5208 let arr = arr_ref
5209 .as_any()
5210 .downcast_ref::<IntervalMonthDayNanoArray>()
5211 .unwrap();
5212 assert_eq!(arr.len(), 1);
5213 let v = arr.value(0);
5214 assert_eq!(v.months, 1);
5215 assert_eq!(v.days, 2);
5216 assert_eq!(v.nanoseconds, 3_000_000);
5217 let mut d_err = Decoder::try_new(&avro_from_codec(Codec::Interval)).unwrap();
5218 let err = d_err
5219 .append_default(&AvroLiteral::Bytes(vec![0u8; 11]))
5220 .unwrap_err();
5221 assert!(
5222 err.to_string()
5223 .contains("Duration default must be exactly 12 bytes"),
5224 "unexpected error: {err:?}"
5225 );
5226 }
5227
5228 #[test]
5229 fn test_default_append_decimal256_from_bytes() {
5230 let dt = avro_from_codec(Codec::Decimal(50, Some(2), Some(32)));
5231 let mut d = Decoder::try_new(&dt).unwrap();
5232 let pos: [u8; 32] = [
5233 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5234 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5235 0x00, 0x00, 0x30, 0x39,
5236 ];
5237 d.append_default(&AvroLiteral::Bytes(pos.to_vec())).unwrap();
5238 let neg: [u8; 32] = [
5239 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
5240 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
5241 0xFF, 0xFF, 0xFF, 0x85,
5242 ];
5243 d.append_default(&AvroLiteral::Bytes(neg.to_vec())).unwrap();
5244 let arr = d.flush(None).unwrap();
5245 let dec = arr.as_any().downcast_ref::<Decimal256Array>().unwrap();
5246 assert_eq!(dec.len(), 2);
5247 assert_eq!(dec.value_as_string(0), "123.45");
5248 assert_eq!(dec.value_as_string(1), "-1.23");
5249 }
5250
5251 #[test]
5252 fn test_record_append_default_map_missing_fields_uses_projector_field_defaults() {
5253 let field_defaults = vec![None, Some(AvroLiteral::String("hi".into()))];
5254 let mut rec = make_record_decoder_with_projector_defaults(
5255 &[("a", DataType::Int32, false), ("b", DataType::Utf8, false)],
5256 field_defaults,
5257 vec![],
5258 );
5259 let mut map: IndexMap<String, AvroLiteral> = IndexMap::new();
5260 map.insert("a".to_string(), AvroLiteral::Int(7));
5261 rec.append_default(&AvroLiteral::Map(map)).unwrap();
5262 let arr = rec.flush(None).unwrap();
5263 let s = arr.as_any().downcast_ref::<StructArray>().unwrap();
5264 let a = s
5265 .column_by_name("a")
5266 .unwrap()
5267 .as_any()
5268 .downcast_ref::<Int32Array>()
5269 .unwrap();
5270 let b = s
5271 .column_by_name("b")
5272 .unwrap()
5273 .as_any()
5274 .downcast_ref::<StringArray>()
5275 .unwrap();
5276 assert_eq!(a.value(0), 7);
5277 assert_eq!(b.value(0), "hi");
5278 }
5279
5280 #[test]
5281 fn test_record_append_default_null_uses_projector_field_defaults() {
5282 let field_defaults = vec![
5283 Some(AvroLiteral::Int(5)),
5284 Some(AvroLiteral::String("x".into())),
5285 ];
5286 let mut rec = make_record_decoder_with_projector_defaults(
5287 &[("a", DataType::Int32, false), ("b", DataType::Utf8, false)],
5288 field_defaults,
5289 vec![],
5290 );
5291 rec.append_default(&AvroLiteral::Null).unwrap();
5292 let arr = rec.flush(None).unwrap();
5293 let s = arr.as_any().downcast_ref::<StructArray>().unwrap();
5294 let a = s
5295 .column_by_name("a")
5296 .unwrap()
5297 .as_any()
5298 .downcast_ref::<Int32Array>()
5299 .unwrap();
5300 let b = s
5301 .column_by_name("b")
5302 .unwrap()
5303 .as_any()
5304 .downcast_ref::<StringArray>()
5305 .unwrap();
5306 assert_eq!(a.value(0), 5);
5307 assert_eq!(b.value(0), "x");
5308 }
5309
5310 #[test]
5311 fn test_record_append_default_missing_fields_without_projector_defaults_yields_type_nulls_or_empties()
5312 {
5313 let fields = vec![("a", DataType::Int32, true), ("b", DataType::Utf8, true)];
5314 let mut field_refs: Vec<FieldRef> = Vec::new();
5315 let mut encoders: Vec<Decoder> = Vec::new();
5316 for (name, dt, nullable) in &fields {
5317 field_refs.push(Arc::new(ArrowField::new(*name, dt.clone(), *nullable)));
5318 }
5319 let enc_a = Decoder::Nullable(NullableDecoder::new(
5320 NullablePlan::ReadTag {
5321 nullability: Nullability::NullSecond,
5322 resolution: ResolutionPlan::Promotion(Promotion::Direct),
5323 },
5324 Decoder::Int32(Vec::with_capacity(DEFAULT_CAPACITY)),
5325 ));
5326 let enc_b = Decoder::Nullable(NullableDecoder::new(
5327 NullablePlan::ReadTag {
5328 nullability: Nullability::NullSecond,
5329 resolution: ResolutionPlan::Promotion(Promotion::Direct),
5330 },
5331 Decoder::String(
5332 OffsetBufferBuilder::new(DEFAULT_CAPACITY),
5333 Vec::with_capacity(DEFAULT_CAPACITY),
5334 ),
5335 ));
5336 encoders.push(enc_a);
5337 encoders.push(enc_b);
5338 let field_defaults = vec![None, None]; let projector = Projector {
5340 writer_projections: vec![],
5341 default_injections: Arc::from(Vec::<(usize, AvroLiteral)>::new()),
5342 };
5343 let mut rec = Decoder::Record {
5344 fields: field_refs.into(),
5345 decoders: encoders,
5346 defaults: field_defaults,
5347 projector: Some(projector),
5348 row_count: 0,
5349 };
5350 let mut map: IndexMap<String, AvroLiteral> = IndexMap::new();
5351 map.insert("a".to_string(), AvroLiteral::Int(9));
5352 rec.append_default(&AvroLiteral::Map(map)).unwrap();
5353 let arr = rec.flush(None).unwrap();
5354 let s = arr.as_any().downcast_ref::<StructArray>().unwrap();
5355 let a = s
5356 .column_by_name("a")
5357 .unwrap()
5358 .as_any()
5359 .downcast_ref::<Int32Array>()
5360 .unwrap();
5361 let b = s
5362 .column_by_name("b")
5363 .unwrap()
5364 .as_any()
5365 .downcast_ref::<StringArray>()
5366 .unwrap();
5367 assert!(a.is_valid(0));
5368 assert_eq!(a.value(0), 9);
5369 assert!(b.is_null(0));
5370 }
5371
5372 #[test]
5373 fn test_projector_default_injection_when_writer_lacks_fields() {
5374 let defaults = vec![None, None];
5375 let injections = vec![
5376 (0, AvroLiteral::Int(99)),
5377 (1, AvroLiteral::String("alice".into())),
5378 ];
5379 let mut rec = make_record_decoder_with_projector_defaults(
5380 &[
5381 ("id", DataType::Int32, false),
5382 ("name", DataType::Utf8, false),
5383 ],
5384 defaults,
5385 injections,
5386 );
5387 rec.decode(&mut AvroCursor::new(&[])).unwrap();
5388 let arr = rec.flush(None).unwrap();
5389 let s = arr.as_any().downcast_ref::<StructArray>().unwrap();
5390 let id = s
5391 .column_by_name("id")
5392 .unwrap()
5393 .as_any()
5394 .downcast_ref::<Int32Array>()
5395 .unwrap();
5396 let name = s
5397 .column_by_name("name")
5398 .unwrap()
5399 .as_any()
5400 .downcast_ref::<StringArray>()
5401 .unwrap();
5402 assert_eq!(id.value(0), 99);
5403 assert_eq!(name.value(0), "alice");
5404 }
5405
5406 #[test]
5407 fn union_type_ids_are_not_child_indexes() {
5408 let encodings: Vec<AvroDataType> =
5409 vec![avro_from_codec(Codec::Int32), avro_from_codec(Codec::Utf8)];
5410 let fields: UnionFields = [
5411 (42_i8, Arc::new(ArrowField::new("a", DataType::Int32, true))),
5412 (7_i8, Arc::new(ArrowField::new("b", DataType::Utf8, true))),
5413 ]
5414 .into_iter()
5415 .collect();
5416 let dt = avro_from_codec(Codec::Union(
5417 encodings.into(),
5418 fields.clone(),
5419 UnionMode::Dense,
5420 ));
5421 let mut dec = Decoder::try_new(&dt).expect("decoder");
5422 let mut b1 = encode_avro_long(1);
5423 b1.extend(encode_avro_bytes(b"hi"));
5424 dec.decode(&mut AvroCursor::new(&b1)).expect("decode b1");
5425 let mut b0 = encode_avro_long(0);
5426 b0.extend(encode_avro_int(5));
5427 dec.decode(&mut AvroCursor::new(&b0)).expect("decode b0");
5428 let arr = dec.flush(None).expect("flush");
5429 let ua = arr.as_any().downcast_ref::<UnionArray>().expect("union");
5430 assert_eq!(ua.len(), 2);
5431 assert_eq!(ua.type_id(0), 7, "type id must come from UnionFields");
5432 assert_eq!(ua.type_id(1), 42, "type id must come from UnionFields");
5433 assert_eq!(ua.value_offset(0), 0);
5434 assert_eq!(ua.value_offset(1), 0);
5435 let utf8_child = ua.child(7).as_any().downcast_ref::<StringArray>().unwrap();
5436 assert_eq!(utf8_child.len(), 1);
5437 assert_eq!(utf8_child.value(0), "hi");
5438 let int_child = ua.child(42).as_any().downcast_ref::<Int32Array>().unwrap();
5439 assert_eq!(int_child.len(), 1);
5440 assert_eq!(int_child.value(0), 5);
5441 let type_ids: Vec<i8> = fields.iter().map(|(tid, _)| tid).collect();
5442 assert_eq!(type_ids, vec![42_i8, 7_i8]);
5443 }
5444
5445 #[cfg(feature = "avro_custom_types")]
5446 #[test]
5447 fn skipper_from_avro_maps_custom_duration_variants_to_int64() -> Result<(), AvroError> {
5448 for codec in [
5449 Codec::DurationNanos,
5450 Codec::DurationMicros,
5451 Codec::DurationMillis,
5452 Codec::DurationSeconds,
5453 ] {
5454 let dt = make_avro_dt(codec.clone(), None);
5455 let s = Skipper::from_avro(&dt)?;
5456 match s {
5457 Skipper::Int64 => {}
5458 other => panic!("expected Int64 skipper for {codec:?}, got {other:?}"),
5459 }
5460 }
5461 Ok(())
5462 }
5463
5464 #[cfg(feature = "avro_custom_types")]
5465 #[test]
5466 fn skipper_skip_consumes_one_long_for_custom_durations() -> Result<(), AvroError> {
5467 let values: [i64; 7] = [0, 1, -1, 150, -150, i64::MAX / 3, i64::MIN / 3];
5468 for codec in [
5469 Codec::DurationNanos,
5470 Codec::DurationMicros,
5471 Codec::DurationMillis,
5472 Codec::DurationSeconds,
5473 ] {
5474 let dt = make_avro_dt(codec.clone(), None);
5475 let s = Skipper::from_avro(&dt)?;
5476 for &v in &values {
5477 let bytes = encode_avro_long(v);
5478 let mut cursor = AvroCursor::new(&bytes);
5479 s.skip(&mut cursor)?;
5480 assert_eq!(
5481 cursor.position(),
5482 bytes.len(),
5483 "did not consume all bytes for {codec:?} value {v}"
5484 );
5485 }
5486 }
5487 Ok(())
5488 }
5489
5490 #[cfg(feature = "avro_custom_types")]
5491 #[test]
5492 fn skipper_nullable_custom_duration_respects_null_first() -> Result<(), AvroError> {
5493 let dt = make_avro_dt(Codec::DurationNanos, Some(Nullability::NullFirst));
5494 let s = Skipper::from_avro(&dt)?;
5495 match &s {
5496 Skipper::Nullable(Nullability::NullFirst, inner) => match **inner {
5497 Skipper::Int64 => {}
5498 ref other => panic!("expected inner Int64, got {other:?}"),
5499 },
5500 other => panic!("expected Nullable(NullFirst, Int64), got {other:?}"),
5501 }
5502 {
5503 let buf = encode_vlq_u64(0);
5504 let mut cursor = AvroCursor::new(&buf);
5505 s.skip(&mut cursor)?;
5506 assert_eq!(cursor.position(), 1, "expected to consume only tag=0");
5507 }
5508 {
5509 let mut buf = encode_vlq_u64(1);
5510 buf.extend(encode_avro_long(0));
5511 let mut cursor = AvroCursor::new(&buf);
5512 s.skip(&mut cursor)?;
5513 assert_eq!(cursor.position(), 2, "expected to consume tag=1 + long(0)");
5514 }
5515
5516 Ok(())
5517 }
5518
5519 #[cfg(feature = "avro_custom_types")]
5520 #[test]
5521 fn skipper_nullable_custom_duration_respects_null_second() -> Result<(), AvroError> {
5522 let dt = make_avro_dt(Codec::DurationMicros, Some(Nullability::NullSecond));
5523 let s = Skipper::from_avro(&dt)?;
5524 match &s {
5525 Skipper::Nullable(Nullability::NullSecond, inner) => match **inner {
5526 Skipper::Int64 => {}
5527 ref other => panic!("expected inner Int64, got {other:?}"),
5528 },
5529 other => panic!("expected Nullable(NullSecond, Int64), got {other:?}"),
5530 }
5531 {
5532 let buf = encode_vlq_u64(1);
5533 let mut cursor = AvroCursor::new(&buf);
5534 s.skip(&mut cursor)?;
5535 assert_eq!(cursor.position(), 1, "expected to consume only tag=1");
5536 }
5537 {
5538 let mut buf = encode_vlq_u64(0);
5539 buf.extend(encode_avro_long(-1));
5540 let mut cursor = AvroCursor::new(&buf);
5541 s.skip(&mut cursor)?;
5542 assert_eq!(
5543 cursor.position(),
5544 1 + encode_avro_long(-1).len(),
5545 "expected to consume tag=0 + long(-1)"
5546 );
5547 }
5548 Ok(())
5549 }
5550
5551 #[test]
5552 fn skipper_interval_is_fixed12_and_skips_12_bytes() -> Result<(), AvroError> {
5553 let dt = make_avro_dt(Codec::Interval, None);
5554 let s = Skipper::from_avro(&dt)?;
5555 match s {
5556 Skipper::DurationFixed12 => {}
5557 other => panic!("expected DurationFixed12, got {other:?}"),
5558 }
5559 let payload = vec![0u8; 12];
5560 let mut cursor = AvroCursor::new(&payload);
5561 s.skip(&mut cursor)?;
5562 assert_eq!(cursor.position(), 12, "expected to consume 12 fixed bytes");
5563 Ok(())
5564 }
5565
5566 #[cfg(feature = "avro_custom_types")]
5567 #[test]
5568 fn test_run_end_encoded_width16_int32_basic_grouping() {
5569 use arrow_array::RunArray;
5570 use std::sync::Arc;
5571 let inner = avro_from_codec(Codec::Int32);
5572 let ree = AvroDataType::new(
5573 Codec::RunEndEncoded(Arc::new(inner), 16),
5574 Default::default(),
5575 None,
5576 );
5577 let mut dec = Decoder::try_new(&ree).expect("create REE decoder");
5578 for v in [1, 1, 1, 2, 2, 3, 3, 3, 3] {
5579 let bytes = encode_avro_int(v);
5580 dec.decode(&mut AvroCursor::new(&bytes)).expect("decode");
5581 }
5582 let arr = dec.flush(None).expect("flush");
5583 let ra = arr
5584 .as_any()
5585 .downcast_ref::<RunArray<Int16Type>>()
5586 .expect("RunArray<Int16Type>");
5587 assert_eq!(ra.len(), 9);
5588 assert_eq!(ra.run_ends().values(), &[3, 5, 9]);
5589 let vals = ra
5590 .values()
5591 .as_ref()
5592 .as_any()
5593 .downcast_ref::<Int32Array>()
5594 .expect("values Int32");
5595 assert_eq!(vals.values(), &[1, 2, 3]);
5596 }
5597
5598 #[cfg(feature = "avro_custom_types")]
5599 #[test]
5600 fn test_run_end_encoded_width32_nullable_values_group_nulls() {
5601 use arrow_array::RunArray;
5602 use std::sync::Arc;
5603 let inner = AvroDataType::new(
5604 Codec::Int32,
5605 Default::default(),
5606 Some(Nullability::NullSecond),
5607 );
5608 let ree = AvroDataType::new(
5609 Codec::RunEndEncoded(Arc::new(inner), 32),
5610 Default::default(),
5611 None,
5612 );
5613 let mut dec = Decoder::try_new(&ree).expect("create REE decoder");
5614 let seq: [Option<i32>; 8] = [
5615 None,
5616 None,
5617 Some(7),
5618 Some(7),
5619 Some(7),
5620 None,
5621 Some(5),
5622 Some(5),
5623 ];
5624 for item in seq {
5625 let mut bytes = Vec::new();
5626 match item {
5627 None => bytes.extend_from_slice(&encode_vlq_u64(1)),
5628 Some(v) => {
5629 bytes.extend_from_slice(&encode_vlq_u64(0));
5630 bytes.extend_from_slice(&encode_avro_int(v));
5631 }
5632 }
5633 dec.decode(&mut AvroCursor::new(&bytes)).expect("decode");
5634 }
5635 let arr = dec.flush(None).expect("flush");
5636 let ra = arr
5637 .as_any()
5638 .downcast_ref::<RunArray<Int32Type>>()
5639 .expect("RunArray<Int32Type>");
5640 assert_eq!(ra.len(), 8);
5641 assert_eq!(ra.run_ends().values(), &[2, 5, 6, 8]);
5642 let vals = ra
5643 .values()
5644 .as_ref()
5645 .as_any()
5646 .downcast_ref::<Int32Array>()
5647 .expect("values Int32 (nullable)");
5648 assert_eq!(vals.len(), 4);
5649 assert!(vals.is_null(0));
5650 assert_eq!(vals.value(1), 7);
5651 assert!(vals.is_null(2));
5652 assert_eq!(vals.value(3), 5);
5653 }
5654
5655 #[cfg(feature = "avro_custom_types")]
5656 #[test]
5657 fn test_run_end_encoded_decode_with_promotion_int_to_double_via_nullable_from_single() {
5658 use arrow_array::RunArray;
5659 let inner_values = Decoder::Float64(Vec::with_capacity(DEFAULT_CAPACITY));
5660 let ree = Decoder::RunEndEncoded(
5661 8, 0,
5663 Box::new(inner_values),
5664 );
5665 let mut dec = Decoder::Nullable(NullableDecoder::new(
5666 NullablePlan::FromSingle {
5667 resolution: ResolutionPlan::Promotion(Promotion::IntToDouble),
5668 },
5669 ree,
5670 ));
5671 for v in [1, 1, 2, 2, 2] {
5672 let bytes = encode_avro_int(v);
5673 dec.decode(&mut AvroCursor::new(&bytes)).expect("decode");
5674 }
5675 let arr = dec.flush(None).expect("flush");
5676 let ra = arr
5677 .as_any()
5678 .downcast_ref::<RunArray<Int64Type>>()
5679 .expect("RunArray<Int64Type>");
5680 assert_eq!(ra.len(), 5);
5681 assert_eq!(ra.run_ends().values(), &[2, 5]);
5682 let vals = ra
5683 .values()
5684 .as_ref()
5685 .as_any()
5686 .downcast_ref::<Float64Array>()
5687 .expect("values Float64");
5688 assert_eq!(vals.values(), &[1.0, 2.0]);
5689 }
5690
5691 #[cfg(feature = "avro_custom_types")]
5692 #[test]
5693 fn test_run_end_encoded_unsupported_run_end_width_errors() {
5694 use std::sync::Arc;
5695 let inner = avro_from_codec(Codec::Int32);
5696 let dt = AvroDataType::new(
5697 Codec::RunEndEncoded(Arc::new(inner), 3),
5698 Default::default(),
5699 None,
5700 );
5701 let err = Decoder::try_new(&dt).expect_err("must reject unsupported width");
5702 let msg = err.to_string();
5703 assert!(
5704 msg.contains("Unsupported run-end width")
5705 && msg.contains("16/32/64 bits or 2/4/8 bytes"),
5706 "unexpected error message: {msg}"
5707 );
5708 }
5709
5710 #[cfg(feature = "avro_custom_types")]
5711 #[test]
5712 fn test_run_end_encoded_empty_input_is_empty_runarray() {
5713 use arrow_array::RunArray;
5714 use std::sync::Arc;
5715 let inner = avro_from_codec(Codec::Utf8);
5716 let dt = AvroDataType::new(
5717 Codec::RunEndEncoded(Arc::new(inner), 4),
5718 Default::default(),
5719 None,
5720 );
5721 let mut dec = Decoder::try_new(&dt).expect("create REE decoder");
5722 let arr = dec.flush(None).expect("flush");
5723 let ra = arr
5724 .as_any()
5725 .downcast_ref::<RunArray<Int32Type>>()
5726 .expect("RunArray<Int32Type>");
5727 assert_eq!(ra.len(), 0);
5728 assert_eq!(ra.run_ends().len(), 0);
5729 assert_eq!(ra.values().len(), 0);
5730 }
5731
5732 #[cfg(feature = "avro_custom_types")]
5733 #[test]
5734 fn test_run_end_encoded_strings_grouping_width32_bits() {
5735 use arrow_array::RunArray;
5736 use std::sync::Arc;
5737 let inner = avro_from_codec(Codec::Utf8);
5738 let dt = AvroDataType::new(
5739 Codec::RunEndEncoded(Arc::new(inner), 32),
5740 Default::default(),
5741 None,
5742 );
5743 let mut dec = Decoder::try_new(&dt).expect("create REE decoder");
5744 for s in ["a", "a", "bb", "bb", "bb", "a"] {
5745 let bytes = encode_avro_bytes(s.as_bytes());
5746 dec.decode(&mut AvroCursor::new(&bytes)).expect("decode");
5747 }
5748 let arr = dec.flush(None).expect("flush");
5749 let ra = arr
5750 .as_any()
5751 .downcast_ref::<RunArray<Int32Type>>()
5752 .expect("RunArray<Int32Type>");
5753 assert_eq!(ra.run_ends().values(), &[2, 5, 6]);
5754 let vals = ra
5755 .values()
5756 .as_ref()
5757 .as_any()
5758 .downcast_ref::<StringArray>()
5759 .expect("values String");
5760 assert_eq!(vals.len(), 3);
5761 assert_eq!(vals.value(0), "a");
5762 assert_eq!(vals.value(1), "bb");
5763 assert_eq!(vals.value(2), "a");
5764 }
5765
5766 #[cfg(not(feature = "avro_custom_types"))]
5767 #[test]
5768 fn test_no_custom_types_feature_smoke_decodes_plain_int32() {
5769 let dt = avro_from_codec(Codec::Int32);
5770 let mut dec = Decoder::try_new(&dt).expect("create Int32 decoder");
5771 for v in [1, 2, 3] {
5772 let bytes = encode_avro_int(v);
5773 dec.decode(&mut AvroCursor::new(&bytes)).expect("decode");
5774 }
5775 let arr = dec.flush(None).expect("flush");
5776 let a = arr
5777 .as_any()
5778 .downcast_ref::<Int32Array>()
5779 .expect("Int32Array");
5780 assert_eq!(a.values(), &[1, 2, 3]);
5781 }
5782
5783 #[test]
5784 fn test_timestamp_nanos_decoding_offset_zero() {
5785 let avro_type = avro_from_codec(Codec::TimestampNanos(Some(Tz::OffsetZero)));
5786 let mut decoder = Decoder::try_new(&avro_type).expect("create TimestampNanos decoder");
5787 let mut data = Vec::new();
5788 for v in [0_i64, 1_i64, -1_i64, 1_234_567_890_i64] {
5789 data.extend_from_slice(&encode_avro_long(v));
5790 }
5791 let mut cur = AvroCursor::new(&data);
5792 for _ in 0..4 {
5793 decoder.decode(&mut cur).expect("decode nanos ts");
5794 }
5795 let array = decoder.flush(None).expect("flush nanos ts");
5796 let ts = array
5797 .as_any()
5798 .downcast_ref::<TimestampNanosecondArray>()
5799 .expect("TimestampNanosecondArray");
5800 assert_eq!(ts.values(), &[0, 1, -1, 1_234_567_890]);
5801 match ts.data_type() {
5802 DataType::Timestamp(arrow_schema::TimeUnit::Nanosecond, tz) => {
5803 assert_eq!(tz.as_deref(), Some("+00:00"));
5804 }
5805 other => panic!("expected Timestamp(Nanosecond, Some(\"+00:00\")), got {other:?}"),
5806 }
5807 }
5808
5809 #[test]
5810 fn test_timestamp_nanos_decoding_utc() {
5811 let avro_type = avro_from_codec(Codec::TimestampNanos(Some(Tz::Utc)));
5812 let mut decoder = Decoder::try_new(&avro_type).expect("create TimestampNanos decoder");
5813 let mut data = Vec::new();
5814 for v in [0_i64, 1_i64, -1_i64, 1_234_567_890_i64] {
5815 data.extend_from_slice(&encode_avro_long(v));
5816 }
5817 let mut cur = AvroCursor::new(&data);
5818 for _ in 0..4 {
5819 decoder.decode(&mut cur).expect("decode nanos ts");
5820 }
5821 let array = decoder.flush(None).expect("flush nanos ts");
5822 let ts = array
5823 .as_any()
5824 .downcast_ref::<TimestampNanosecondArray>()
5825 .expect("TimestampNanosecondArray");
5826 assert_eq!(ts.values(), &[0, 1, -1, 1_234_567_890]);
5827 match ts.data_type() {
5828 DataType::Timestamp(arrow_schema::TimeUnit::Nanosecond, tz) => {
5829 assert_eq!(tz.as_deref(), Some("UTC"));
5830 }
5831 other => panic!("expected Timestamp(Nanosecond, Some(\"UTC\")), got {other:?}"),
5832 }
5833 }
5834
5835 #[test]
5836 fn test_timestamp_nanos_decoding_local() {
5837 let avro_type = avro_from_codec(Codec::TimestampNanos(None));
5838 let mut decoder = Decoder::try_new(&avro_type).expect("create TimestampNanos decoder");
5839 let mut data = Vec::new();
5840 for v in [10_i64, 20_i64, -30_i64] {
5841 data.extend_from_slice(&encode_avro_long(v));
5842 }
5843 let mut cur = AvroCursor::new(&data);
5844 for _ in 0..3 {
5845 decoder.decode(&mut cur).expect("decode nanos ts");
5846 }
5847 let array = decoder.flush(None).expect("flush nanos ts");
5848 let ts = array
5849 .as_any()
5850 .downcast_ref::<TimestampNanosecondArray>()
5851 .expect("TimestampNanosecondArray");
5852 assert_eq!(ts.values(), &[10, 20, -30]);
5853 match ts.data_type() {
5854 DataType::Timestamp(arrow_schema::TimeUnit::Nanosecond, tz) => {
5855 assert_eq!(tz.as_deref(), None);
5856 }
5857 other => panic!("expected Timestamp(Nanosecond, None), got {other:?}"),
5858 }
5859 }
5860
5861 #[test]
5862 fn test_timestamp_nanos_decoding_with_nulls() {
5863 let avro_type = AvroDataType::new(
5864 Codec::TimestampNanos(None),
5865 Default::default(),
5866 Some(Nullability::NullFirst),
5867 );
5868 let mut decoder = Decoder::try_new(&avro_type).expect("create nullable TimestampNanos");
5869 let mut data = Vec::new();
5870 data.extend_from_slice(&encode_avro_long(1));
5871 data.extend_from_slice(&encode_avro_long(42));
5872 data.extend_from_slice(&encode_avro_long(0));
5873 data.extend_from_slice(&encode_avro_long(1));
5874 data.extend_from_slice(&encode_avro_long(-7));
5875 let mut cur = AvroCursor::new(&data);
5876 for _ in 0..3 {
5877 decoder.decode(&mut cur).expect("decode nullable nanos ts");
5878 }
5879 let array = decoder.flush(None).expect("flush nullable nanos ts");
5880 let ts = array
5881 .as_any()
5882 .downcast_ref::<TimestampNanosecondArray>()
5883 .expect("TimestampNanosecondArray");
5884 assert_eq!(ts.len(), 3);
5885 assert!(ts.is_valid(0));
5886 assert!(ts.is_null(1));
5887 assert!(ts.is_valid(2));
5888 assert_eq!(ts.value(0), 42);
5889 assert_eq!(ts.value(2), -7);
5890 match ts.data_type() {
5891 DataType::Timestamp(arrow_schema::TimeUnit::Nanosecond, tz) => {
5892 assert_eq!(tz.as_deref(), None);
5893 }
5894 other => panic!("expected Timestamp(Nanosecond, None), got {other:?}"),
5895 }
5896 }
5897}