Skip to main content

mz_avro/
decode.rs

1// Copyright 2018 Flavien Raynaud.
2// Copyright Materialize, Inc. and contributors. All rights reserved.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License in the LICENSE file at the
7// root of this repository, or online at
8//
9//     http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16//
17// This file is derived from the avro-rs project, available at
18// https://github.com/flavray/avro-rs. It was incorporated
19// directly into Materialize on March 3, 2020.
20//
21// The original source code is subject to the terms of the MIT license, a copy
22// of which can be found in the LICENSE file at the root of this repository.
23
24use std::cmp;
25use std::collections::BTreeSet;
26use std::fmt::{self, Display};
27use std::fs::File;
28use std::io::{self, Cursor, Read, Seek, SeekFrom};
29
30use chrono::{DateTime, NaiveDate};
31use flate2::read::MultiGzDecoder;
32
33use crate::error::{DecodeError, Error as AvroError};
34use crate::schema::{
35    RecordField, ResolvedDefaultValueField, ResolvedRecordField, Schema, SchemaNode, SchemaPiece,
36    SchemaPieceOrNamed, SchemaPieceRefOrNamed,
37};
38use crate::types::{Scalar, Value};
39use crate::util::{TsUnit, safe_len, zag_i32, zag_i64};
40use crate::{TrivialDecoder, ValueDecoder};
41
42pub trait StatefulAvroDecodable: Sized {
43    type Decoder: AvroDecode<Out = Self>;
44    type State;
45    fn new_decoder(state: Self::State) -> Self::Decoder;
46}
47pub trait AvroDecodable: Sized {
48    type Decoder: AvroDecode<Out = Self>;
49
50    fn new_decoder() -> Self::Decoder;
51}
52impl<T> AvroDecodable for T
53where
54    T: StatefulAvroDecodable,
55    T::State: Default,
56{
57    type Decoder = <Self as StatefulAvroDecodable>::Decoder;
58
59    fn new_decoder() -> Self::Decoder {
60        <Self as StatefulAvroDecodable>::new_decoder(Default::default())
61    }
62}
63#[inline]
64fn decode_long_nonneg<R: Read>(reader: &mut R) -> Result<u64, AvroError> {
65    let u = match zag_i64(reader)? {
66        i if i >= 0 => i as u64,
67        i => return Err(AvroError::Decode(DecodeError::ExpectedNonnegInteger(i))),
68    };
69    Ok(u)
70}
71
72fn decode_int_nonneg<R: Read>(reader: &mut R) -> Result<u32, AvroError> {
73    let u = match zag_i32(reader)? {
74        i if i >= 0 => i as u32,
75        i => {
76            return Err(AvroError::Decode(DecodeError::ExpectedNonnegInteger(
77                i as i64,
78            )));
79        }
80    };
81    Ok(u)
82}
83
84#[inline]
85fn decode_len<R: Read>(reader: &mut R) -> Result<usize, AvroError> {
86    zag_i64(reader).and_then(|i| safe_len(i as usize))
87}
88
89#[inline]
90fn decode_float<R: Read>(reader: &mut R) -> Result<f32, AvroError> {
91    let mut buf = [0u8; 4];
92    reader.read_exact(&mut buf[..])?;
93    Ok(f32::from_le_bytes(buf))
94}
95
96#[inline]
97fn decode_double<R: Read>(reader: &mut R) -> Result<f64, AvroError> {
98    let mut buf = [0u8; 8];
99    reader.read_exact(&mut buf[..])?;
100    Ok(f64::from_le_bytes(buf))
101}
102
103impl Display for TsUnit {
104    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105        match self {
106            TsUnit::Millis => write!(f, "ms"),
107            TsUnit::Micros => write!(f, "us"),
108        }
109    }
110}
111
112#[cfg(test)]
113mod tests {
114    use chrono::DateTime;
115
116    use crate::types::Value;
117    use crate::util::TsUnit;
118
119    use super::build_ts_value;
120
121    #[mz_ore::test]
122    fn test_negative_timestamps() {
123        assert_eq!(
124            build_ts_value(-1, TsUnit::Millis).unwrap(),
125            Value::Timestamp(
126                DateTime::from_timestamp(-1, 999_000_000)
127                    .unwrap()
128                    .naive_utc()
129            )
130        );
131        assert_eq!(
132            build_ts_value(-1000, TsUnit::Millis).unwrap(),
133            Value::Timestamp(DateTime::from_timestamp(-1, 0).unwrap().naive_utc())
134        );
135        assert_eq!(
136            build_ts_value(-1000, TsUnit::Micros).unwrap(),
137            Value::Timestamp(
138                DateTime::from_timestamp(-1, 999_000_000)
139                    .unwrap()
140                    .naive_utc()
141            )
142        );
143        assert_eq!(
144            build_ts_value(-1, TsUnit::Micros).unwrap(),
145            Value::Timestamp(
146                DateTime::from_timestamp(-1, 999_999_000)
147                    .unwrap()
148                    .naive_utc()
149            )
150        );
151        assert_eq!(
152            build_ts_value(-123_456_789_123, TsUnit::Micros).unwrap(),
153            Value::Timestamp(
154                DateTime::from_timestamp(-123_457, (1_000_000 - 789_123) * 1_000)
155                    .unwrap()
156                    .naive_utc()
157            )
158        );
159    }
160
161    #[mz_ore::test]
162    fn array_block_len_bounded_by_remaining_input() {
163        // A tiny body claiming a huge array block must error, not allocate. A
164        // small (or hostile) message used to drive an unbounded `Vec<Value>` by
165        // claiming a multi-million-element block whose items decode from ~no
166        // input (e.g. an empty record). Regression for an OOM found by fuzzing.
167        use std::str::FromStr;
168
169        use super::{AvroDeserializer, GeneralDeserializer};
170        use crate::util::zig_i64;
171        use crate::{Schema, ValueDecoder};
172
173        let schema = Schema::from_str(r#"{"type": "array", "items": "long"}"#).unwrap();
174        let mut body = Vec::new();
175        zig_i64(8_000_000, &mut body); // block count dwarfs the (here, empty) element data
176        let dsr = GeneralDeserializer {
177            schema: schema.top_node(),
178        };
179        let mut reader: &[u8] = &body;
180        let res = dsr.deserialize(&mut reader, ValueDecoder);
181        assert!(
182            res.is_err(),
183            "an array block longer than the remaining input must be rejected, not allocated"
184        );
185    }
186
187    #[mz_ore::test]
188    fn zero_width_array_elements_decode() {
189        // The remaining-input bound must not reject valid arrays whose elements
190        // encode to zero bytes. `null` and empty records have no per-element byte
191        // floor, so a ten-element block legitimately follows its count with no
192        // element bytes at all (Materialize's own writer emits `array<null>` of
193        // ten as `[20, 0]`: block count 10, then the terminating zero block).
194        use std::str::FromStr;
195
196        use super::{AvroDeserializer, GeneralDeserializer};
197        use crate::types::Value;
198        use crate::util::zig_i64;
199        use crate::{Schema, ValueDecoder};
200
201        for (items, want) in [
202            (r#""null""#, Value::Null),
203            (
204                r#"{"type": "record", "name": "Empty", "fields": []}"#,
205                Value::Record(vec![]),
206            ),
207        ] {
208            let schema =
209                Schema::from_str(&format!(r#"{{"type": "array", "items": {items}}}"#)).unwrap();
210            let mut body = Vec::new();
211            zig_i64(10, &mut body); // ten elements...
212            body.push(0); // ...then the terminating zero block. No element bytes.
213            let dsr = GeneralDeserializer {
214                schema: schema.top_node(),
215            };
216            let mut reader: &[u8] = &body;
217            let decoded = dsr
218                .deserialize(&mut reader, ValueDecoder)
219                .expect("a zero-width array element type must decode, not be rejected");
220            assert_eq!(decoded, Value::Array(vec![want; 10]));
221        }
222    }
223
224    #[mz_ore::test]
225    fn valid_null_array_falsely_rejected() {
226        // Materialize's encoder emits no element bytes for `null` array
227        // elements, so decoding must not assume each element consumes at least
228        // one byte of remaining input.
229        use std::str::FromStr;
230
231        use super::{AvroDeserializer, GeneralDeserializer};
232        use crate::encode::encode_to_vec;
233        use crate::types::Value;
234        use crate::{Schema, ValueDecoder};
235
236        let schema = Schema::from_str(r#"{"type": "array", "items": "null"}"#).unwrap();
237        let value = Value::Array(vec![Value::Null, Value::Null]);
238        let body = encode_to_vec(&value, &schema);
239
240        let dsr = GeneralDeserializer {
241            schema: schema.top_node(),
242        };
243        let mut reader: &[u8] = &body;
244        let res = dsr.deserialize(&mut reader, ValueDecoder);
245        assert!(
246            res.is_ok(),
247            "an encoder-produced array of nulls should round-trip, but got: {res:?}"
248        );
249    }
250
251    #[mz_ore::test]
252    fn zero_width_array_elements_decode_across_blocks() {
253        // Zero-width arrays can be encoded as multiple blocks. The cumulative
254        // cap must not reject ordinary valid data below the limit.
255        use std::str::FromStr;
256
257        use super::{AvroDeserializer, GeneralDeserializer};
258        use crate::types::Value;
259        use crate::util::zig_i64;
260        use crate::{Schema, ValueDecoder};
261
262        let schema = Schema::from_str(r#"{"type": "array", "items": "null"}"#).unwrap();
263        let mut body = Vec::new();
264        zig_i64(4, &mut body);
265        zig_i64(6, &mut body);
266        body.push(0);
267
268        let dsr = GeneralDeserializer {
269            schema: schema.top_node(),
270        };
271        let mut reader: &[u8] = &body;
272        let decoded = dsr
273            .deserialize(&mut reader, ValueDecoder)
274            .expect("zero-width arrays may span multiple blocks below the cap");
275        assert_eq!(decoded, Value::Array(vec![Value::Null; 10]));
276    }
277
278    #[mz_ore::test]
279    fn zero_width_array_total_len_bounded_across_blocks() {
280        // A zero-width element type has no input-proportional per-block bound.
281        // Keep a cumulative cap so repeated legal-size blocks cannot drive an
282        // unbounded decode. Seed the shared node budget at the cap to test the
283        // edge without walking millions of null elements first.
284        use std::str::FromStr;
285
286        use super::{AvroArrayAccess, DECODE_NODES, MAX_VALUE_NODES, SimpleArrayAccess};
287        use crate::util::zig_i64;
288        use crate::{Schema, TrivialDecoder};
289
290        let schema = Schema::from_str(r#""null""#).unwrap();
291        let mut body = Vec::new();
292        zig_i64(1, &mut body);
293
294        let mut reader: &[u8] = &body;
295        let mut access = SimpleArrayAccess::new(&mut reader, schema.top_node());
296        // Drive `SimpleArrayAccess` directly (no top-level decode entry to reset
297        // the budget), so pre-charge the shared counter to the cap by hand.
298        DECODE_NODES.with(|n| n.set(MAX_VALUE_NODES));
299
300        let err = access
301            .decode_next(TrivialDecoder)
302            .expect_err("a new block past the cumulative node budget must be rejected");
303        DECODE_NODES.with(|n| n.set(0));
304        assert!(
305            err.to_string().contains("exceeds cumulative limit"),
306            "unexpected error: {err}"
307        );
308    }
309
310    #[mz_ore::test]
311    fn zero_width_record_array_bounded() {
312        // Regression for an OOM found by the reader_decode fuzz target: an
313        // `array<record{null}>` element is zero-width on the wire (the byte-floor
314        // check below can't bound it) yet each element still allocates a
315        // `Value::Record`, so a multi-million-element block claimed from a
316        // handful of bytes amplified into gigabytes. The cumulative node cap must
317        // reject it rather than allocate.
318        use std::str::FromStr;
319
320        use super::{AvroDeserializer, GeneralDeserializer};
321        use crate::util::zig_i64;
322        use crate::{Schema, ValueDecoder};
323
324        let schema = Schema::from_str(
325            r#"{"type": "array", "items":
326                {"type": "record", "name": "R", "fields": [{"name": "g0", "type": "null"}]}}"#,
327        )
328        .unwrap();
329        // A single block claiming far more zero-width records than the node cap,
330        // followed by no element bytes at all.
331        let mut body = Vec::new();
332        zig_i64(100_000_000, &mut body);
333        let dsr = GeneralDeserializer {
334            schema: schema.top_node(),
335        };
336        let mut reader: &[u8] = &body;
337        let res = dsr.deserialize(&mut reader, ValueDecoder);
338        assert!(
339            res.is_err(),
340            "an array of zero-width records longer than the node cap must be rejected, not allocated"
341        );
342    }
343
344    #[mz_ore::test]
345    fn small_zero_width_record_array_decodes() {
346        // The node cap must not reject an ordinary, below-cap array of zero-width
347        // records: ten `record{null}`s encode (like `array<null>`) as just the
348        // block count followed by the terminating zero block.
349        use std::str::FromStr;
350
351        use super::{AvroDeserializer, GeneralDeserializer};
352        use crate::types::Value;
353        use crate::util::zig_i64;
354        use crate::{Schema, ValueDecoder};
355
356        let schema = Schema::from_str(
357            r#"{"type": "array", "items":
358                {"type": "record", "name": "R", "fields": [{"name": "g0", "type": "null"}]}}"#,
359        )
360        .unwrap();
361        let mut body = Vec::new();
362        zig_i64(10, &mut body);
363        body.push(0);
364        let dsr = GeneralDeserializer {
365            schema: schema.top_node(),
366        };
367        let mut reader: &[u8] = &body;
368        let decoded = dsr
369            .deserialize(&mut reader, ValueDecoder)
370            .expect("a below-cap array of zero-width records must decode, not be rejected");
371        let want = Value::Record(vec![("g0".to_string(), Value::Null)]);
372        assert_eq!(decoded, Value::Array(vec![want; 10]));
373    }
374
375    #[mz_ore::test]
376    fn nested_zero_width_collection_shares_node_budget() {
377        // Regression: the node budget must be shared across every collection in
378        // one datum, not reset per collection. With a per-collection budget each
379        // inner array of `array<record{array<record{null}>}>` would get a fresh
380        // `MAX_VALUE_NODES` ceiling, so a few wire bytes amplify into
381        // ~`MAX_VALUE_NODES` *per outer element* (the same blow-up the cap exists
382        // to stop, one nesting level deeper). Drive the decode so an inner
383        // array's block-header charge — reached only after the enclosing record
384        // starts decoding — trips the *shared* cumulative cap, proving the inner
385        // collection sees the outer element's spend rather than a fresh budget.
386        use std::str::FromStr;
387
388        use super::{AvroDeserializer, GeneralDeserializer, MAX_VALUE_NODES};
389        use crate::util::zig_i64;
390        use crate::{Schema, ValueDecoder};
391
392        let schema = Schema::from_str(
393            r#"{"type": "array", "items":
394                {"type": "record", "name": "Outer", "fields": [
395                    {"name": "inner", "type":
396                        {"type": "array", "items":
397                            {"type": "record", "name": "Inner",
398                             "fields": [{"name": "g0", "type": "null"}]}}}]}}"#,
399        )
400        .unwrap();
401        // One outer element (charges 2 nodes), whose inner array then claims
402        // `MAX_VALUE_NODES / 2` zero-width records — exactly `MAX_VALUE_NODES`
403        // weighted nodes, which clears the inner block's own per-block check but
404        // pushes the *shared* total (2 + MAX_VALUE_NODES) over the cap. No inner
405        // element bytes follow: a correct decode rejects at the header before
406        // allocating anything; the per-collection bug would instead materialize
407        // ~2M `Value::Record`s and only later hit EOF.
408        let mut body = Vec::new();
409        zig_i64(1, &mut body);
410        zig_i64((MAX_VALUE_NODES / 2) as i64, &mut body);
411        let dsr = GeneralDeserializer {
412            schema: schema.top_node(),
413        };
414        let mut reader: &[u8] = &body;
415        let err = dsr.deserialize(&mut reader, ValueDecoder).expect_err(
416            "a nested array claiming MAX_VALUE_NODES on top of the outer spend must be rejected",
417        );
418        assert!(
419            err.to_string().contains("exceeds cumulative limit"),
420            "unexpected error: {err}"
421        );
422    }
423
424    #[mz_ore::test]
425    fn top_level_decode_resets_stale_node_budget() {
426        // A decode that errored partway can leave the thread-local node counter
427        // non-zero; the next top-level decode must reset it (depth 0 -> 1) or an
428        // unrelated datum on the same thread is wrongly rejected. Pin the counter
429        // at the cap to stand in for that leftover, then require a small array to
430        // still decode.
431        use std::str::FromStr;
432
433        use super::{AvroDeserializer, DECODE_NODES, GeneralDeserializer, MAX_VALUE_NODES};
434        use crate::types::Value;
435        use crate::util::zig_i64;
436        use crate::{Schema, ValueDecoder};
437
438        let schema = Schema::from_str(r#"{"type": "array", "items": "null"}"#).unwrap();
439        let mut body = Vec::new();
440        zig_i64(3, &mut body);
441        body.push(0);
442
443        DECODE_NODES.with(|n| n.set(MAX_VALUE_NODES));
444        let dsr = GeneralDeserializer {
445            schema: schema.top_node(),
446        };
447        let mut reader: &[u8] = &body;
448        let decoded = dsr
449            .deserialize(&mut reader, ValueDecoder)
450            .expect("the top-level entry must reset a stale node budget");
451        assert_eq!(decoded, Value::Array(vec![Value::Null; 3]));
452    }
453}
454
455/// A convenience function to build timestamp values from underlying longs.
456pub fn build_ts_value(value: i64, unit: TsUnit) -> Result<Value, AvroError> {
457    let result = match unit {
458        TsUnit::Millis => DateTime::from_timestamp_millis(value),
459        TsUnit::Micros => DateTime::from_timestamp_micros(value),
460    };
461    let ndt = result.ok_or(AvroError::Decode(DecodeError::BadTimestamp { unit, value }))?;
462    Ok(Value::Timestamp(ndt.naive_utc()))
463}
464
465/// A convenience trait for types that are both readable and skippable.
466///
467/// A blanket implementation is provided for all types that implement both
468/// [`Read`] and [`Skip`].
469pub trait AvroRead: Read + Skip {}
470
471impl<T> AvroRead for T where T: Read + Skip {}
472
473/// A trait that allows for efficient skipping forward while reading data.
474pub trait Skip: Read {
475    /// Advance the cursor by `len` bytes.
476    ///
477    /// If possible, the implementation should be more efficient than calling
478    /// [`Read::read`] and discarding the resulting bytes.
479    ///
480    /// Calling `skip` with a `len` that advances the cursor past the end of the
481    /// underlying data source is permissible. The only requirement is that the
482    /// next call to [`Read::read`] indicates EOF.
483    ///
484    /// # Errors
485    ///
486    /// Can return an error in all the same cases that [`Read::read`] can.
487    ///
488    /// TODO: Remove this clippy suppression when the issue is fixed.
489    /// See <https://github.com/rust-lang/rust-clippy/issues/12519>
490    #[allow(clippy::unused_io_amount)]
491    fn skip(&mut self, mut len: usize) -> Result<(), io::Error> {
492        const BUF_SIZE: usize = 512;
493        let mut buf = [0; BUF_SIZE];
494
495        while len > 0 {
496            let n = if len < BUF_SIZE {
497                self.read(&mut buf[..len])?
498            } else {
499                self.read(&mut buf)?
500            };
501            if n == 0 {
502                break;
503            }
504            len -= n;
505        }
506        Ok(())
507    }
508
509    /// An upper bound, if cheaply known, on the number of bytes still readable
510    /// from this source. Used to reject an array/map block that claims more
511    /// elements than the input could possibly contain: each element consumes at
512    /// least zero bytes, so a block longer than the remaining input only happens
513    /// when a small (or hostile) message claims a huge count, which would
514    /// otherwise drive an unbounded `Vec` allocation (length amplification).
515    /// Streaming sources that can't answer cheaply return `None`.
516    fn remaining_input(&self) -> Option<usize> {
517        None
518    }
519}
520
521impl Skip for File {
522    fn skip(&mut self, len: usize) -> Result<(), io::Error> {
523        self.seek(SeekFrom::Current(len as i64))?;
524        Ok(())
525    }
526}
527
528impl Skip for &[u8] {
529    fn skip(&mut self, len: usize) -> Result<(), io::Error> {
530        let len = cmp::min(len, self.len());
531        *self = &self[len..];
532        Ok(())
533    }
534
535    fn remaining_input(&self) -> Option<usize> {
536        Some(self.len())
537    }
538}
539
540impl<S: Skip + ?Sized> Skip for Box<S> {
541    fn skip(&mut self, len: usize) -> Result<(), io::Error> {
542        self.as_mut().skip(len)
543    }
544
545    fn remaining_input(&self) -> Option<usize> {
546        self.as_ref().remaining_input()
547    }
548}
549
550impl<T: AsRef<[u8]>> Skip for Cursor<T> {
551    fn skip(&mut self, len: usize) -> Result<(), io::Error> {
552        self.seek(SeekFrom::Current(len as i64))?;
553        Ok(())
554    }
555
556    fn remaining_input(&self) -> Option<usize> {
557        let total = self.get_ref().as_ref().len();
558        Some(total.saturating_sub(usize::try_from(self.position()).unwrap_or(usize::MAX)))
559    }
560}
561
562impl<R: Read> Skip for MultiGzDecoder<R> {}
563
564pub enum ValueOrReader<'a, V, R: AvroRead> {
565    Value(V),
566    Reader { len: usize, r: &'a mut R },
567}
568
569enum SchemaOrDefault<'b, R: AvroRead> {
570    Schema(&'b mut R, SchemaNode<'b>),
571    Default(&'b Value),
572}
573pub struct AvroFieldAccess<'b, R: AvroRead> {
574    schema: SchemaOrDefault<'b, R>,
575}
576
577impl<'b, R: AvroRead> AvroFieldAccess<'b, R> {
578    pub fn decode_field<D: AvroDecode>(self, d: D) -> Result<D::Out, AvroError> {
579        match self.schema {
580            SchemaOrDefault::Schema(r, schema) => {
581                let des = GeneralDeserializer { schema };
582                des.deserialize(r, d)
583            }
584            SchemaOrDefault::Default(value) => give_value(d, value),
585        }
586    }
587}
588
589pub trait AvroRecordAccess<R: AvroRead> {
590    fn next_field<'b>(
591        &'b mut self,
592    ) -> Result<Option<(&'b str, usize, AvroFieldAccess<'b, R>)>, AvroError>;
593}
594
595struct SimpleRecordAccess<'a, R: AvroRead> {
596    schema: SchemaNode<'a>,
597    r: &'a mut R,
598    fields: &'a [RecordField],
599    i: usize,
600}
601
602impl<'a, R: AvroRead> SimpleRecordAccess<'a, R> {
603    fn new(schema: SchemaNode<'a>, r: &'a mut R, fields: &'a [RecordField]) -> Self {
604        Self {
605            schema,
606            r,
607            fields,
608            i: 0,
609        }
610    }
611}
612
613impl<'a, R: AvroRead> AvroRecordAccess<R> for SimpleRecordAccess<'a, R> {
614    fn next_field<'b>(
615        &'b mut self,
616    ) -> Result<Option<(&'b str, usize, AvroFieldAccess<'b, R>)>, AvroError> {
617        assert!(self.i <= self.fields.len());
618        if self.i == self.fields.len() {
619            Ok(None)
620        } else {
621            let f = &self.fields[self.i];
622            self.i += 1;
623            Ok(Some((
624                f.name.as_str(),
625                f.position,
626                AvroFieldAccess {
627                    schema: SchemaOrDefault::Schema(self.r, self.schema.step(&f.schema)),
628                },
629            )))
630        }
631    }
632}
633
634struct ValueRecordAccess<'a> {
635    values: &'a [(String, Value)],
636    i: usize,
637}
638
639impl<'a> ValueRecordAccess<'a> {
640    fn new(values: &'a [(String, Value)]) -> Self {
641        Self { values, i: 0 }
642    }
643}
644
645impl<'a> AvroRecordAccess<&'a [u8]> for ValueRecordAccess<'a> {
646    fn next_field<'b>(
647        &'b mut self,
648    ) -> Result<Option<(&'b str, usize, AvroFieldAccess<'b, &'a [u8]>)>, AvroError> {
649        assert!(self.i <= self.values.len());
650        if self.i == self.values.len() {
651            Ok(None)
652        } else {
653            let (name, val) = &self.values[self.i];
654            self.i += 1;
655            Ok(Some((
656                name.as_str(),
657                self.i - 1,
658                AvroFieldAccess {
659                    schema: SchemaOrDefault::Default(val),
660                },
661            )))
662        }
663    }
664}
665
666struct ValueMapAccess<'a> {
667    values: &'a [(String, Value)],
668    i: usize,
669}
670
671impl<'a> ValueMapAccess<'a> {
672    fn new(values: &'a [(String, Value)]) -> Self {
673        Self { values, i: 0 }
674    }
675}
676
677impl<'a> AvroMapAccess for ValueMapAccess<'a> {
678    type R = &'a [u8];
679    fn next_entry<'b>(
680        &'b mut self,
681    ) -> Result<Option<(String, AvroFieldAccess<'b, Self::R>)>, AvroError> {
682        assert!(self.i <= self.values.len());
683        if self.i == self.values.len() {
684            Ok(None)
685        } else {
686            let (name, val) = &self.values[self.i];
687            self.i += 1;
688            Ok(Some((
689                name.clone(),
690                AvroFieldAccess {
691                    schema: SchemaOrDefault::Default(val),
692                },
693            )))
694        }
695    }
696}
697
698struct ResolvedRecordAccess<'a, R: AvroRead> {
699    defaults: &'a [ResolvedDefaultValueField],
700    i_defaults: usize,
701    fields: &'a [ResolvedRecordField],
702    i_fields: usize,
703    r: &'a mut R,
704    schema: SchemaNode<'a>,
705}
706
707impl<'a, R: AvroRead> ResolvedRecordAccess<'a, R> {
708    fn new(
709        defaults: &'a [ResolvedDefaultValueField],
710        fields: &'a [ResolvedRecordField],
711        r: &'a mut R,
712        schema: SchemaNode<'a>,
713    ) -> Self {
714        Self {
715            defaults,
716            i_defaults: 0,
717            fields,
718            i_fields: 0,
719            r,
720            schema,
721        }
722    }
723}
724
725impl<'a, R: AvroRead> AvroRecordAccess<R> for ResolvedRecordAccess<'a, R> {
726    fn next_field<'b>(
727        &'b mut self,
728    ) -> Result<Option<(&'b str, usize, AvroFieldAccess<'b, R>)>, AvroError> {
729        assert!(self.i_defaults <= self.defaults.len() && self.i_fields <= self.fields.len());
730        if self.i_defaults < self.defaults.len() {
731            let default = &self.defaults[self.i_defaults];
732            self.i_defaults += 1;
733            Ok(Some((
734                default.name.as_str(),
735                default.position,
736                AvroFieldAccess {
737                    schema: SchemaOrDefault::Default(&default.default),
738                },
739            )))
740        } else {
741            while self.i_fields < self.fields.len() {
742                let field = &self.fields[self.i_fields];
743                self.i_fields += 1;
744                match field {
745                    ResolvedRecordField::Absent(absent_schema) => {
746                        // we don't care what's in the value, but we still need to read it in order to skip ahead the proper amount in the input.
747                        let d = GeneralDeserializer {
748                            schema: absent_schema.top_node(),
749                        };
750                        d.deserialize(self.r, TrivialDecoder)?;
751                        continue;
752                    }
753                    ResolvedRecordField::Present(field) => {
754                        return Ok(Some((
755                            field.name.as_str(),
756                            field.position,
757                            AvroFieldAccess {
758                                schema: SchemaOrDefault::Schema(
759                                    self.r,
760                                    self.schema.step(&field.schema),
761                                ),
762                            },
763                        )));
764                    }
765                }
766            }
767            Ok(None)
768        }
769    }
770}
771
772pub trait AvroArrayAccess {
773    fn decode_next<D: AvroDecode>(&mut self, d: D) -> Result<Option<D::Out>, AvroError>;
774}
775
776pub trait AvroMapAccess {
777    type R: AvroRead;
778    fn next_entry<'b>(
779        &'b mut self,
780    ) -> Result<Option<(String, AvroFieldAccess<'b, Self::R>)>, AvroError>;
781}
782
783pub struct SimpleMapAccess<'a, R: AvroRead> {
784    entry_schema: SchemaNode<'a>,
785    r: &'a mut R,
786    done: bool,
787    remaining: usize,
788    /// Lower bound on the `Value` nodes a single entry materializes: the key
789    /// `String` plus the value's [`min_value_nodes`]. Charged against the shared
790    /// [`DECODE_NODES`] budget per block; see [`charge_value_nodes`].
791    entry_nodes: usize,
792}
793
794impl<'a, R: AvroRead> SimpleMapAccess<'a, R> {
795    fn new(entry_schema: SchemaNode<'a>, r: &'a mut R) -> Self {
796        Self {
797            entry_schema,
798            r,
799            done: false,
800            remaining: 0,
801            // One node for the key `String`, plus the value's own nodes.
802            entry_nodes: 1usize.saturating_add(min_value_nodes(entry_schema)),
803        }
804    }
805}
806
807impl<'a, R: AvroRead> AvroMapAccess for SimpleMapAccess<'a, R> {
808    type R = R;
809    fn next_entry<'b>(&'b mut self) -> Result<Option<(String, AvroFieldAccess<'b, R>)>, AvroError> {
810        if self.done {
811            return Ok(None);
812        }
813        if self.remaining == 0 {
814            // TODO -- we can use len_in_bytes to quickly skip non-demanded arrays
815            let (len, _len_in_bytes) = match zag_i64(self.r)? {
816                len if len > 0 => (len as usize, None),
817                neglen if neglen < 0 => (neglen.unsigned_abs() as usize, Some(decode_len(self.r)?)),
818                0 => {
819                    self.done = true;
820                    return Ok(None);
821                }
822                _ => unreachable!(),
823            };
824            // See `SimpleArrayAccess::decode_next` — same `MAX_VALUE_NODES`
825            // memory bound applies, weighting the entry count by the per-entry
826            // node lower bound so a block whose values are wide-but-zero-width
827            // records can't amplify a few wire bytes into millions of `Value`s.
828            let block_nodes = len.saturating_mul(self.entry_nodes);
829            if block_nodes > MAX_VALUE_NODES {
830                return Err(AvroError::Decode(DecodeError::Custom(format!(
831                    "Avro map block length {len} exceeds limit {MAX_VALUE_NODES} decoded values"
832                ))));
833            }
834            // Charge against the budget shared by every array/map in the datum,
835            // so nested collections can't each get a fresh cap (see
836            // `charge_value_nodes` / `MAX_VALUE_NODES`).
837            charge_value_nodes("map", block_nodes)?;
838            // A block can't hold more entries than there are bytes left to
839            // decode them from; reject a count that claims otherwise rather than
840            // letting it drive an unbounded allocation (see `Skip::remaining_input`).
841            // Unlike an array item, every map entry encodes at least a one-byte
842            // key-length varint, so each entry has a guaranteed one-byte floor and
843            // a count above the remaining input is always bogus.
844            if let Some(remaining) = self.r.remaining_input() {
845                if len > remaining {
846                    return Err(AvroError::Decode(DecodeError::Custom(format!(
847                        "Avro map block length {len} exceeds remaining input ({remaining} bytes)"
848                    ))));
849                }
850            }
851            self.remaining = len;
852        }
853        assert!(self.remaining > 0);
854        self.remaining -= 1;
855
856        // TODO - We can try to avoid this allocation, but  nobody uses maps in Materialize
857        // right now so it doesn't really matter.
858        let key_len = decode_len(self.r)?;
859        let mut key_buf = vec![];
860        key_buf.resize_with(key_len, Default::default);
861        self.r.read_exact(&mut key_buf)?;
862        let key = String::from_utf8(key_buf)
863            .map_err(|_e| AvroError::Decode(DecodeError::MapKeyUtf8Error))?;
864
865        let a = AvroFieldAccess {
866            schema: SchemaOrDefault::Schema(self.r, self.entry_schema),
867        };
868        Ok(Some((key, a)))
869    }
870}
871
872struct SimpleArrayAccess<'a, R: AvroRead> {
873    r: &'a mut R,
874    schema: SchemaNode<'a>,
875    remaining: usize,
876    /// Lower bound on the `Value` nodes a single element materializes (see
877    /// [`min_value_nodes`]). Charged against the shared [`DECODE_NODES`] budget
878    /// per block; see [`charge_value_nodes`].
879    element_nodes: usize,
880    done: bool,
881}
882
883impl<'a, R: AvroRead> SimpleArrayAccess<'a, R> {
884    fn new(r: &'a mut R, schema: SchemaNode<'a>) -> Self {
885        Self {
886            r,
887            schema,
888            remaining: 0,
889            element_nodes: min_value_nodes(schema),
890            done: false,
891        }
892    }
893}
894
895struct ValueArrayAccess<'a> {
896    values: &'a [Value],
897    i: usize,
898}
899
900impl<'a> ValueArrayAccess<'a> {
901    fn new(values: &'a [Value]) -> Self {
902        Self { values, i: 0 }
903    }
904}
905
906impl<'a> AvroArrayAccess for ValueArrayAccess<'a> {
907    fn decode_next<D: AvroDecode>(&mut self, d: D) -> Result<Option<D::Out>, AvroError> {
908        assert!(self.i <= self.values.len());
909        if self.i == self.values.len() {
910            Ok(None)
911        } else {
912            let val = give_value(d, &self.values[self.i])?;
913            self.i += 1;
914            Ok(Some(val))
915        }
916    }
917}
918
919/// Sanity cap on the number of `Value` nodes one top-level decode may
920/// materialize across *every* array and map in the datum. Arrays and maps apply
921/// it per block (a fast reject for an absurd single-block count) and against the
922/// shared cumulative budget threaded through the whole decode (see
923/// [`charge_value_nodes`] / [`DECODE_NODES`]).
924///
925/// This bounds *memory*, not element count: each element is weighted by
926/// [`min_value_nodes`], a lower bound on the `Value` nodes it decodes into. An
927/// element-count cap alone is not enough, because a zero-width element — `null`,
928/// or a record of only `null`/empty-record fields — occupies no input yet still
929/// allocates a `Value` (a `Vec` slot, plus a record's own `Vec` and field-name
930/// `String`s). The [`min_encoded_len`] byte-floor check below bounds a block by
931/// the remaining input only when each element occupies at least one wire byte,
932/// so a multi-million-element block of zero-width elements would otherwise
933/// amplify a handful of bytes into gigabytes. Weighting the count and capping
934/// the product bounds that amplification (as well as the analogous case of a
935/// huge block of wide, positive-floor records read from a large input).
936///
937/// The budget is shared across the whole datum rather than reset per collection
938/// so the bound *composes through nesting*: a per-collection budget would hand
939/// every `array`/`map` a fresh ceiling, letting a schema like
940/// `array<record{array<record{null}>}>` amplify a few wire bytes into roughly
941/// this cap raised to the nesting depth. Sharing one budget keeps the worst case
942/// flat regardless of nesting.
943///
944/// Without any cap, a malicious or corrupt file can claim up to `i64::MAX` items
945/// and the generic array/map decode loop runs until it OOMs or hits `Vec`
946/// capacity-overflow.
947///
948/// At `1 << 22` nodes the worst case (decoding zero-width records right up to the
949/// cap) peaks around 750 MiB — including the transient doubling of the element
950/// `Vec` mid-`push` — leaving comfortable headroom under the fuzzer's 2 GiB RSS
951/// limit, while still admitting any realistically-sized array/map.
952const MAX_VALUE_NODES: usize = 1 << 22;
953
954/// A *lower* bound on the number of bytes any value of `schema` encodes to on
955/// the wire.
956///
957/// Used to reject an array block whose claimed element count could not possibly
958/// fit in the remaining input: a block of `len` elements occupies at least
959/// `len * min_encoded_len` bytes. Only an under-estimate is ever safe here — an
960/// over-estimate would reject valid data — so anything whose floor we can't
961/// prove (schema-resolution pieces, named-type recursion cycles) contributes
962/// `0`, which simply relaxes the bound.
963///
964/// Crucially this returns `0` for zero-width types — `null`, an empty record, a
965/// record of only such fields — because those genuinely encode to no bytes.
966/// Materialize's own writer emits a ten-element `array<null>` as `[20, 0]`, so a
967/// blanket "count must not exceed remaining bytes" rule would reject valid
968/// input. For zero-width element types the caller falls back to the cumulative
969/// [`MAX_VALUE_NODES`] cap (weighted by [`min_value_nodes`]).
970fn min_encoded_len(schema: SchemaNode) -> usize {
971    let mut visited = BTreeSet::new();
972    min_encoded_len_piece(schema.root, schema.inner, &mut visited)
973}
974
975/// Resolves a (possibly named) schema reference, guarding against named-type
976/// cycles, then defers to [`min_encoded_len_piece`].
977fn min_encoded_len_or_named(
978    root: &Schema,
979    node: SchemaPieceRefOrNamed,
980    visited: &mut BTreeSet<usize>,
981) -> usize {
982    match node {
983        SchemaPieceRefOrNamed::Piece(piece) => min_encoded_len_piece(root, piece, visited),
984        SchemaPieceRefOrNamed::Named(idx) => {
985            // A named-type cycle can only close through a record field; treat
986            // the back-edge as zero-width so we never over-estimate.
987            if !visited.insert(idx) {
988                return 0;
989            }
990            let len = min_encoded_len_piece(root, &root.lookup(idx).piece, visited);
991            visited.remove(&idx);
992            len
993        }
994    }
995}
996
997fn min_encoded_len_piece(
998    root: &Schema,
999    piece: &SchemaPiece,
1000    visited: &mut BTreeSet<usize>,
1001) -> usize {
1002    match piece {
1003        // Encodes to nothing at all.
1004        SchemaPiece::Null => 0,
1005        // A single byte (zig-zag varint of 0 is one byte; a bool is one byte).
1006        SchemaPiece::Boolean
1007        | SchemaPiece::Int
1008        | SchemaPiece::Long
1009        | SchemaPiece::Date
1010        | SchemaPiece::TimestampMilli
1011        | SchemaPiece::TimestampMicro => 1,
1012        SchemaPiece::Float => 4,
1013        SchemaPiece::Double => 8,
1014        // `fixed`-backed decimals are exactly their size; `bytes`-backed ones,
1015        // like `bytes`/`string`, carry at least a one-byte length varint.
1016        SchemaPiece::Decimal {
1017            fixed_size: Some(size),
1018            ..
1019        } => *size,
1020        SchemaPiece::Decimal {
1021            fixed_size: None, ..
1022        }
1023        | SchemaPiece::Bytes
1024        | SchemaPiece::String
1025        | SchemaPiece::Json
1026        | SchemaPiece::Uuid => 1,
1027        // An empty array/map encodes as a single zero-count byte regardless of
1028        // the element type, so don't recurse into it.
1029        SchemaPiece::Array(_) | SchemaPiece::Map(_) => 1,
1030        // A union always writes at least its one-byte branch index.
1031        SchemaPiece::Union(_) => 1,
1032        // An enum writes a one-byte symbol index.
1033        SchemaPiece::Enum { .. } => 1,
1034        SchemaPiece::Fixed { size } => *size,
1035        // A record's encoding is its fields' encodings concatenated, so its
1036        // floor is the sum of the fields' floors — which can be `0` (the empty
1037        // record, or a record of only `null`/empty-record fields).
1038        SchemaPiece::Record { fields, .. } => fields.iter().fold(0, |acc, field| {
1039            acc.saturating_add(min_encoded_len_or_named(
1040                root,
1041                field.schema.as_ref(),
1042                visited,
1043            ))
1044        }),
1045        // Schema-resolution pieces only arise on the reader/writer-mismatch
1046        // path; we don't try to prove a floor for them.
1047        _ => 0,
1048    }
1049}
1050
1051/// Bounds the object count an object-container-file block declares against the
1052/// payload that is supposed to hold those objects.
1053///
1054/// The count comes straight off the wire, and `util::safe_len` alone caps it at
1055/// `MAX_ALLOCATION_BYTES` — a sensible ceiling for a byte length, an enormous one
1056/// for a count, and in no way related to the block it describes. `payload_len` is
1057/// the block's *decompressed* length.
1058///
1059/// Which bound applies is decided the same way as for an array block, and for the
1060/// same reason (see [`min_encoded_len`]): the byte floor when the object schema has
1061/// a proven positive one, otherwise the node-weighted cap, because a zero-width
1062/// object — an empty record, or a record of only `null`/empty-record fields —
1063/// encodes to no bytes at all, so no payload length can constrain how many of them
1064/// a block may claim.
1065///
1066/// Unlike an array block, the two bounds are *alternatives* rather than both being
1067/// applied. An array materializes all of its elements at once, so its cap is about
1068/// retained memory; a block's objects are yielded and dropped one at a time, so the
1069/// cap here is about work amplified out of a few bytes. Once the byte floor holds,
1070/// the work is linear in the file and needs no further ceiling — and capping nodes
1071/// as well would reject a legitimate large block of small records.
1072///
1073/// Not charged against [`DECODE_NODES`]: that budget is per top-level datum and
1074/// each object in a block is its own datum. This is a standalone check on the
1075/// block header.
1076pub(crate) fn bound_block_object_count(
1077    schema: SchemaNode,
1078    count: usize,
1079    payload_len: usize,
1080) -> Result<(), AvroError> {
1081    let min_bytes = min_encoded_len(schema);
1082    if min_bytes > 0 {
1083        if count.saturating_mul(min_bytes) > payload_len {
1084            return Err(AvroError::Decode(DecodeError::Custom(format!(
1085                "Avro block object count {count} exceeds block payload ({payload_len} bytes)"
1086            ))));
1087        }
1088        return Ok(());
1089    }
1090    let nodes = count.saturating_mul(min_value_nodes(schema));
1091    if nodes > MAX_VALUE_NODES {
1092        return Err(AvroError::Decode(DecodeError::Custom(format!(
1093            "Avro block object count {count} exceeds limit {MAX_VALUE_NODES} decoded values"
1094        ))));
1095    }
1096    Ok(())
1097}
1098
1099/// A *lower* bound on the number of `Value` nodes a single value of `schema`
1100/// materializes into when decoded.
1101///
1102/// Used to weight an array/map element so the cumulative [`MAX_VALUE_NODES`] cap
1103/// bounds decoded *memory*, not just element count. The amplifying case the cap
1104/// exists for — `null` and records of only zero-width fields — is counted
1105/// *exactly* here (a record always materializes every field, and none of these
1106/// types involve a union/array/map whose runtime size we couldn't predict), so
1107/// the bound is tight where it matters most.
1108///
1109/// As with [`min_encoded_len`], only an under-estimate is ever safe (an
1110/// over-estimate would reject valid data), so a nested array/map contributes
1111/// `1` — its empty-collection floor — and its actual contents are charged
1112/// against the shared [`MAX_VALUE_NODES`] budget as they are decoded (so the
1113/// cap still composes through nesting); a union contributes `1` (its count is
1114/// already bounded by the remaining input via its one-byte branch floor); and
1115/// unprovable schema-resolution pieces contribute `1`. Every value is at least
1116/// one node, so the weight is always `>= 1`.
1117fn min_value_nodes(schema: SchemaNode) -> usize {
1118    let mut visited = BTreeSet::new();
1119    min_value_nodes_piece(schema.root, schema.inner, &mut visited)
1120}
1121
1122/// Resolves a (possibly named) schema reference, guarding against named-type
1123/// cycles, then defers to [`min_value_nodes_piece`].
1124fn min_value_nodes_or_named(
1125    root: &Schema,
1126    node: SchemaPieceRefOrNamed,
1127    visited: &mut BTreeSet<usize>,
1128) -> usize {
1129    match node {
1130        SchemaPieceRefOrNamed::Piece(piece) => min_value_nodes_piece(root, piece, visited),
1131        SchemaPieceRefOrNamed::Named(idx) => {
1132            // A named-type cycle can only close through a record field; treat the
1133            // back-edge as a single node so we never over-estimate (and never
1134            // recurse forever).
1135            if !visited.insert(idx) {
1136                return 1;
1137            }
1138            let nodes = min_value_nodes_piece(root, &root.lookup(idx).piece, visited);
1139            visited.remove(&idx);
1140            nodes
1141        }
1142    }
1143}
1144
1145fn min_value_nodes_piece(
1146    root: &Schema,
1147    piece: &SchemaPiece,
1148    visited: &mut BTreeSet<usize>,
1149) -> usize {
1150    match piece {
1151        // A record materializes itself plus every one of its fields. This is the
1152        // only type that can be zero-width on the wire yet still allocate, so
1153        // counting its fields exactly is what makes the cap effective.
1154        SchemaPiece::Record { fields, .. } => fields.iter().fold(1, |acc, field| {
1155            acc.saturating_add(min_value_nodes_or_named(
1156                root,
1157                field.schema.as_ref(),
1158                visited,
1159            ))
1160        }),
1161        // Every other type materializes a single node for the purposes of this
1162        // lower bound: scalars and leaves trivially; an array/map at minimum an
1163        // empty collection (its contents bounded by its own cumulative cap); a
1164        // union its (input-bounded) branch index; and resolution pieces we don't
1165        // try to prove.
1166        _ => 1,
1167    }
1168}
1169
1170impl<'a, R: AvroRead> AvroArrayAccess for SimpleArrayAccess<'a, R> {
1171    fn decode_next<D: AvroDecode>(&mut self, d: D) -> Result<Option<D::Out>, AvroError> {
1172        if self.done {
1173            return Ok(None);
1174        }
1175        if self.remaining == 0 {
1176            // TODO -- we can use len_in_bytes to quickly skip non-demanded arrays
1177            let (len, _len_in_bytes) = match zag_i64(self.r)? {
1178                len if len > 0 => (len as usize, None),
1179                neglen if neglen < 0 => (neglen.unsigned_abs() as usize, Some(decode_len(self.r)?)),
1180                0 => {
1181                    self.done = true;
1182                    return Ok(None);
1183                }
1184                _ => unreachable!(),
1185            };
1186            // Weight the count by the per-element node lower bound so the cap
1187            // bounds decoded memory, not just element count: a block of
1188            // zero-width-but-allocating elements (e.g. a record of `null`s)
1189            // amplifies a few wire bytes into millions of `Value`s otherwise.
1190            let block_nodes = len.saturating_mul(self.element_nodes);
1191            if block_nodes > MAX_VALUE_NODES {
1192                return Err(AvroError::Decode(DecodeError::Custom(format!(
1193                    "Avro array block length {len} exceeds limit {MAX_VALUE_NODES} \
1194                     decoded values"
1195                ))));
1196            }
1197            // Charge against the budget shared by every array/map in the datum,
1198            // so nested collections can't each get a fresh cap (see
1199            // `charge_value_nodes` / `MAX_VALUE_NODES`).
1200            charge_value_nodes("array", block_nodes)?;
1201            // A block of `len` items occupies at least `len * min_elem` bytes,
1202            // so a count needing more than the remaining input can't be honest;
1203            // reject it rather than let it drive an unbounded allocation (see
1204            // `Skip::remaining_input`). Unlike a map entry — which always carries
1205            // at least a one-byte key-length varint — an array item can encode to
1206            // zero bytes (`null`, an empty record), so this bound only applies
1207            // when the element type has a proven positive byte floor. For
1208            // zero-width element types (`min_elem == 0`) we rely on the
1209            // cumulative `MAX_VALUE_NODES` cap; otherwise a valid datum such as a
1210            // ten-element `array<null>` (encoded as `[20, 0]`) would be wrongly
1211            // rejected.
1212            if let Some(remaining) = self.r.remaining_input() {
1213                let min_elem = min_encoded_len(self.schema);
1214                if min_elem > 0 && len.saturating_mul(min_elem) > remaining {
1215                    return Err(AvroError::Decode(DecodeError::Custom(format!(
1216                        "Avro array block length {len} exceeds remaining input ({remaining} bytes)"
1217                    ))));
1218                }
1219            }
1220            self.remaining = len;
1221        }
1222        assert!(self.remaining > 0);
1223        self.remaining -= 1;
1224        let des = GeneralDeserializer {
1225            schema: self.schema,
1226        };
1227        des.deserialize(self.r, d).map(Some)
1228    }
1229}
1230
1231#[macro_export]
1232macro_rules! define_unexpected {
1233    (record) => {
1234        fn record<R: $crate::AvroRead, A: $crate::AvroRecordAccess<R>>(
1235            self,
1236            _a: &mut A,
1237        ) -> Result<Self::Out, $crate::error::Error> {
1238            Err($crate::error::Error::Decode($crate::error::DecodeError::UnexpectedRecord))
1239        }
1240    };
1241    (union_branch) => {
1242        fn union_branch<'avro_macro_lifetime, R: $crate::AvroRead, D: $crate::AvroDeserializer>(
1243            self,
1244            _idx: usize,
1245            _n_variants: usize,
1246            _null_variant: Option<usize>,
1247            _deserializer: D,
1248            _reader: &'avro_macro_lifetime mut R,
1249        ) -> Result<Self::Out, $crate::error::Error> {
1250            Err($crate::error::Error::Decode($crate::error::DecodeError::UnexpectedUnion))
1251        }
1252    };
1253    (array) => {
1254        fn array<A: $crate::AvroArrayAccess>(
1255            self,
1256            _a: &mut A,
1257        ) -> Result<Self::Out, $crate::error::Error> {
1258            Err($crate::error::Error::Decode(
1259                $crate::error::DecodeError::UnexpectedArray,
1260            ))
1261        }
1262    };
1263    (map) => {
1264        fn map<M: $crate::AvroMapAccess>(
1265            self,
1266            _m: &mut M,
1267        ) -> Result<Self::Out, $crate::error::Error> {
1268            Err($crate::error::Error::Decode(
1269                $crate::error::DecodeError::UnexpectedMap,
1270            ))
1271        }
1272    };
1273    (enum_variant) => {
1274        fn enum_variant(
1275            self,
1276            _symbol: &str,
1277            _idx: usize,
1278        ) -> Result<Self::Out, $crate::error::Error> {
1279            Err($crate::error::Error::Decode(
1280                $crate::error::DecodeError::UnexpectedEnum,
1281            ))
1282        }
1283    };
1284    (scalar) => {
1285        fn scalar(self, _scalar: $crate::types::Scalar) -> Result<Self::Out, $crate::error::Error> {
1286            Err($crate::error::Error::Decode($crate::error::DecodeError::UnexpectedScalar))
1287        }
1288    };
1289    (decimal) => {
1290        fn decimal<'avro_macro_lifetime, R: AvroRead>(
1291            self,
1292            _precision: usize,
1293            _scale: usize,
1294            _r: $crate::ValueOrReader<'avro_macro_lifetime, &'avro_macro_lifetime [u8], R>,
1295        ) -> Result<Self::Out, $crate::error::Error> {
1296            Err($crate::error::Error::Decode($crate::error::DecodeError::UnexpectedDecimal))
1297        }
1298    };
1299    (bytes) => {
1300        fn bytes<'avro_macro_lifetime, R: AvroRead>(
1301            self,
1302            _r: $crate::ValueOrReader<'avro_macro_lifetime, &'avro_macro_lifetime [u8], R>,
1303        ) -> Result<Self::Out, $crate::error::Error> {
1304            Err($crate::error::Error::Decode($crate::error::DecodeError::UnexpectedBytes))
1305        }
1306    };
1307    (string) => {
1308        fn string<'avro_macro_lifetime, R: AvroRead>(
1309            self,
1310            _r: $crate::ValueOrReader<'avro_macro_lifetime, &'avro_macro_lifetime str, R>,
1311        ) -> Result<Self::Out, $crate::error::Error> {
1312            Err($crate::error::Error::Decode($crate::error::DecodeError::UnexpectedString))
1313        }
1314    };
1315    (json) => {
1316        fn json<'avro_macro_lifetime, R: AvroRead>(
1317            self,
1318            _r: $crate::ValueOrReader<
1319                'avro_macro_lifetime,
1320                &'avro_macro_lifetime serde_json::Value,
1321                R,
1322            >,
1323        ) -> Result<Self::Out, $crate::error::Error> {
1324            Err($crate::error::Error::Decode($crate::error::DecodeError::UnexpectedJson))
1325        }
1326    };
1327    (uuid) => {
1328        fn uuid<'avro_macro_lifetime, R: AvroRead>(
1329            self,
1330            _r: $crate::ValueOrReader<'avro_macro_lifetime, &'avro_macro_lifetime [u8], R>,
1331        ) -> Result<Self::Out, $crate::error::Error> {
1332            Err($crate::error::Error::Decode($crate::error::DecodeError::UnexpectedUuid))
1333        }
1334    };
1335    (fixed) => {
1336        fn fixed<'avro_macro_lifetime, R: AvroRead>(
1337            self,
1338            _r: $crate::ValueOrReader<'avro_macro_lifetime, &'avro_macro_lifetime [u8], R>,
1339        ) -> Result<Self::Out, $crate::error::Error> {
1340            Err($crate::error::Error::Decode($crate::error::DecodeError::UnexpectedFixed))
1341        }
1342    };
1343    ($($kind:ident),+) => {
1344        $($crate::define_unexpected!{$kind})+
1345    }
1346}
1347
1348pub trait AvroDecode: Sized {
1349    type Out;
1350    fn record<R: AvroRead, A: AvroRecordAccess<R>>(
1351        self,
1352        _a: &mut A,
1353    ) -> Result<Self::Out, AvroError>;
1354
1355    fn union_branch<'a, R: AvroRead, D: AvroDeserializer>(
1356        self,
1357        _idx: usize,
1358        _n_variants: usize,
1359        _null_variant: Option<usize>,
1360        _deserializer: D,
1361        _reader: &'a mut R,
1362    ) -> Result<Self::Out, AvroError>;
1363
1364    fn array<A: AvroArrayAccess>(self, _a: &mut A) -> Result<Self::Out, AvroError>;
1365
1366    fn map<M: AvroMapAccess>(self, _m: &mut M) -> Result<Self::Out, AvroError>;
1367
1368    fn enum_variant(self, _symbol: &str, _idx: usize) -> Result<Self::Out, AvroError>;
1369
1370    fn scalar(self, _scalar: Scalar) -> Result<Self::Out, AvroError>;
1371
1372    fn decimal<'a, R: AvroRead>(
1373        self,
1374        _precision: usize,
1375        _scale: usize,
1376        _r: ValueOrReader<'a, &'a [u8], R>,
1377    ) -> Result<Self::Out, AvroError>;
1378
1379    fn bytes<'a, R: AvroRead>(
1380        self,
1381        _r: ValueOrReader<'a, &'a [u8], R>,
1382    ) -> Result<Self::Out, AvroError>;
1383    fn string<'a, R: AvroRead>(
1384        self,
1385        _r: ValueOrReader<'a, &'a str, R>,
1386    ) -> Result<Self::Out, AvroError>;
1387    fn json<'a, R: AvroRead>(
1388        self,
1389        _r: ValueOrReader<'a, &'a serde_json::Value, R>,
1390    ) -> Result<Self::Out, AvroError>;
1391    fn uuid<'a, R: AvroRead>(
1392        self,
1393        _r: ValueOrReader<'a, &'a [u8], R>,
1394    ) -> Result<Self::Out, AvroError>;
1395    fn fixed<'a, R: AvroRead>(
1396        self,
1397        _r: ValueOrReader<'a, &'a [u8], R>,
1398    ) -> Result<Self::Out, AvroError>;
1399    fn map_decoder<T, F: FnMut(Self::Out) -> Result<T, AvroError>>(
1400        self,
1401        f: F,
1402    ) -> public_decoders::MappingDecoder<T, Self::Out, Self, F> {
1403        public_decoders::MappingDecoder::new(self, f)
1404    }
1405}
1406
1407pub mod public_decoders {
1408
1409    use std::collections::BTreeMap;
1410
1411    use crate::error::{DecodeError, Error as AvroError};
1412    use crate::types::{DecimalValue, Scalar, Value};
1413    use crate::{
1414        AvroArrayAccess, AvroDecode, AvroDeserializer, AvroRead, AvroRecordAccess, ValueOrReader,
1415    };
1416
1417    use super::{AvroDecodable, AvroMapAccess, StatefulAvroDecodable};
1418
1419    macro_rules! define_simple_decoder {
1420        ($name:ident, $out:ty, $($scalar_branch:ident);*) => {
1421            pub struct $name;
1422            impl AvroDecode for $name {
1423                type Out = $out;
1424                fn scalar(self, scalar: Scalar) -> Result<$out, AvroError> {
1425                    let out = match scalar {
1426                        $(
1427                            Scalar::$scalar_branch(inner) => {inner.try_into()?}
1428                        ),*
1429                            other => return Err(AvroError::Decode(
1430                                DecodeError::UnexpectedScalarKind(other.into()),
1431                            ))
1432                    };
1433                    Ok(out)
1434                }
1435                define_unexpected! {
1436                    array, record, union_branch, map,
1437                    enum_variant, decimal, bytes, string,
1438                    json, uuid, fixed
1439                }
1440            }
1441
1442            impl StatefulAvroDecodable for $out {
1443                type Decoder = $name;
1444                type State = ();
1445                fn new_decoder(_state: ()) -> $name {
1446                    $name
1447                }
1448            }
1449        }
1450    }
1451
1452    define_simple_decoder!(I32Decoder, i32, Int;Long);
1453    define_simple_decoder!(I64Decoder, i64, Int;Long);
1454    define_simple_decoder!(U64Decoder, u64, Int;Long);
1455    define_simple_decoder!(UsizeDecoder, usize, Int;Long);
1456    define_simple_decoder!(IsizeDecoder, isize, Int;Long);
1457
1458    pub struct MappingDecoder<
1459        T,
1460        InnerOut,
1461        Inner: AvroDecode<Out = InnerOut>,
1462        Conv: FnMut(InnerOut) -> Result<T, AvroError>,
1463    > {
1464        inner: Inner,
1465        conv: Conv,
1466    }
1467
1468    impl<
1469        T,
1470        InnerOut,
1471        Inner: AvroDecode<Out = InnerOut>,
1472        Conv: FnMut(InnerOut) -> Result<T, AvroError>,
1473    > MappingDecoder<T, InnerOut, Inner, Conv>
1474    {
1475        pub fn new(inner: Inner, conv: Conv) -> Self {
1476            Self { inner, conv }
1477        }
1478    }
1479
1480    impl<
1481        T,
1482        InnerOut,
1483        Inner: AvroDecode<Out = InnerOut>,
1484        Conv: FnMut(InnerOut) -> Result<T, AvroError>,
1485    > AvroDecode for MappingDecoder<T, InnerOut, Inner, Conv>
1486    {
1487        type Out = T;
1488
1489        fn record<R: AvroRead, A: AvroRecordAccess<R>>(
1490            mut self,
1491            a: &mut A,
1492        ) -> Result<Self::Out, AvroError> {
1493            (self.conv)(self.inner.record(a)?)
1494        }
1495
1496        fn union_branch<'a, R: AvroRead, D: AvroDeserializer>(
1497            mut self,
1498            idx: usize,
1499            n_variants: usize,
1500            null_variant: Option<usize>,
1501            deserializer: D,
1502            reader: &'a mut R,
1503        ) -> Result<Self::Out, AvroError> {
1504            (self.conv)(self.inner.union_branch(
1505                idx,
1506                n_variants,
1507                null_variant,
1508                deserializer,
1509                reader,
1510            )?)
1511        }
1512
1513        fn array<A: AvroArrayAccess>(mut self, a: &mut A) -> Result<Self::Out, AvroError> {
1514            (self.conv)(self.inner.array(a)?)
1515        }
1516
1517        fn map<M: AvroMapAccess>(mut self, m: &mut M) -> Result<Self::Out, AvroError> {
1518            (self.conv)(self.inner.map(m)?)
1519        }
1520
1521        fn enum_variant(mut self, symbol: &str, idx: usize) -> Result<Self::Out, AvroError> {
1522            (self.conv)(self.inner.enum_variant(symbol, idx)?)
1523        }
1524
1525        fn scalar(mut self, scalar: Scalar) -> Result<Self::Out, AvroError> {
1526            (self.conv)(self.inner.scalar(scalar)?)
1527        }
1528
1529        fn decimal<'a, R: AvroRead>(
1530            mut self,
1531            precision: usize,
1532            scale: usize,
1533            r: ValueOrReader<'a, &'a [u8], R>,
1534        ) -> Result<Self::Out, AvroError> {
1535            (self.conv)(self.inner.decimal(precision, scale, r)?)
1536        }
1537
1538        fn bytes<'a, R: AvroRead>(
1539            mut self,
1540            r: ValueOrReader<'a, &'a [u8], R>,
1541        ) -> Result<Self::Out, AvroError> {
1542            (self.conv)(self.inner.bytes(r)?)
1543        }
1544
1545        fn string<'a, R: AvroRead>(
1546            mut self,
1547            r: ValueOrReader<'a, &'a str, R>,
1548        ) -> Result<Self::Out, AvroError> {
1549            (self.conv)(self.inner.string(r)?)
1550        }
1551
1552        fn json<'a, R: AvroRead>(
1553            mut self,
1554            r: ValueOrReader<'a, &'a serde_json::Value, R>,
1555        ) -> Result<Self::Out, AvroError> {
1556            (self.conv)(self.inner.json(r)?)
1557        }
1558
1559        fn uuid<'a, R: AvroRead>(
1560            mut self,
1561            r: ValueOrReader<'a, &'a [u8], R>,
1562        ) -> Result<Self::Out, AvroError> {
1563            (self.conv)(self.inner.uuid(r)?)
1564        }
1565
1566        fn fixed<'a, R: AvroRead>(
1567            mut self,
1568            r: ValueOrReader<'a, &'a [u8], R>,
1569        ) -> Result<Self::Out, AvroError> {
1570            (self.conv)(self.inner.fixed(r)?)
1571        }
1572    }
1573    pub struct ArrayAsVecDecoder<
1574        InnerOut,
1575        Inner: AvroDecode<Out = InnerOut>,
1576        Ctor: FnMut() -> Inner,
1577    > {
1578        ctor: Ctor,
1579        buf: Vec<InnerOut>,
1580    }
1581
1582    impl<InnerOut, Inner: AvroDecode<Out = InnerOut>, Ctor: FnMut() -> Inner>
1583        ArrayAsVecDecoder<InnerOut, Inner, Ctor>
1584    {
1585        pub fn new(ctor: Ctor) -> Self {
1586            Self { ctor, buf: vec![] }
1587        }
1588    }
1589    impl<InnerOut, Inner: AvroDecode<Out = InnerOut>, Ctor: FnMut() -> Inner> AvroDecode
1590        for ArrayAsVecDecoder<InnerOut, Inner, Ctor>
1591    {
1592        type Out = Vec<InnerOut>;
1593        fn array<A: AvroArrayAccess>(mut self, a: &mut A) -> Result<Self::Out, AvroError> {
1594            while let Some(next) = a.decode_next((self.ctor)())? {
1595                self.buf.push(next);
1596            }
1597            Ok(self.buf)
1598        }
1599        define_unexpected! {
1600            record, union_branch, map, enum_variant,
1601            scalar, decimal, bytes, string, json, uuid,
1602            fixed
1603        }
1604    }
1605
1606    pub struct DefaultArrayAsVecDecoder<T> {
1607        buf: Vec<T>,
1608    }
1609    impl<T> Default for DefaultArrayAsVecDecoder<T> {
1610        fn default() -> Self {
1611            Self { buf: vec![] }
1612        }
1613    }
1614    impl<T: AvroDecodable> AvroDecode for DefaultArrayAsVecDecoder<T> {
1615        type Out = Vec<T>;
1616        fn array<A: AvroArrayAccess>(mut self, a: &mut A) -> Result<Self::Out, AvroError> {
1617            while let Some(next) = {
1618                let inner = T::new_decoder();
1619                a.decode_next(inner)?
1620            } {
1621                self.buf.push(next);
1622            }
1623            Ok(self.buf)
1624        }
1625        define_unexpected! {
1626            record, union_branch, map, enum_variant,
1627            scalar, decimal, bytes, string, json, uuid,
1628            fixed
1629        }
1630    }
1631    impl<T: AvroDecodable> StatefulAvroDecodable for Vec<T> {
1632        type Decoder = DefaultArrayAsVecDecoder<T>;
1633        type State = ();
1634
1635        fn new_decoder(_state: Self::State) -> Self::Decoder {
1636            DefaultArrayAsVecDecoder::<T>::default()
1637        }
1638    }
1639    pub struct TrivialDecoder;
1640
1641    impl TrivialDecoder {
1642        fn maybe_skip<'a, V, R: AvroRead>(
1643            self,
1644            r: ValueOrReader<'a, V, R>,
1645        ) -> Result<(), AvroError> {
1646            if let ValueOrReader::Reader { len, r } = r {
1647                Ok(r.skip(len)?)
1648            } else {
1649                Ok(())
1650            }
1651        }
1652    }
1653
1654    impl AvroDecode for TrivialDecoder {
1655        type Out = ();
1656        fn record<R: AvroRead, A: AvroRecordAccess<R>>(self, a: &mut A) -> Result<(), AvroError> {
1657            while let Some((_, _, f)) = a.next_field()? {
1658                f.decode_field(TrivialDecoder)?;
1659            }
1660            Ok(())
1661        }
1662        fn union_branch<'a, R: AvroRead, D: AvroDeserializer>(
1663            self,
1664            _idx: usize,
1665            _n_variants: usize,
1666            _null_variant: Option<usize>,
1667            deserializer: D,
1668            reader: &'a mut R,
1669        ) -> Result<(), AvroError> {
1670            deserializer.deserialize(reader, self)
1671        }
1672
1673        fn enum_variant(self, _symbol: &str, _idx: usize) -> Result<(), AvroError> {
1674            Ok(())
1675        }
1676        fn scalar(self, _scalar: Scalar) -> Result<(), AvroError> {
1677            Ok(())
1678        }
1679        fn decimal<'a, R: AvroRead>(
1680            self,
1681            _precision: usize,
1682            _scale: usize,
1683            r: ValueOrReader<'a, &'a [u8], R>,
1684        ) -> Result<(), AvroError> {
1685            self.maybe_skip(r)
1686        }
1687        fn bytes<'a, R: AvroRead>(
1688            self,
1689            r: ValueOrReader<'a, &'a [u8], R>,
1690        ) -> Result<(), AvroError> {
1691            self.maybe_skip(r)
1692        }
1693        fn string<'a, R: AvroRead>(
1694            self,
1695            r: ValueOrReader<'a, &'a str, R>,
1696        ) -> Result<(), AvroError> {
1697            self.maybe_skip(r)
1698        }
1699        fn json<'a, R: AvroRead>(
1700            self,
1701            r: ValueOrReader<'a, &'a serde_json::Value, R>,
1702        ) -> Result<(), AvroError> {
1703            self.maybe_skip(r)
1704        }
1705        fn uuid<'a, R: AvroRead>(self, r: ValueOrReader<'a, &'a [u8], R>) -> Result<(), AvroError> {
1706            self.maybe_skip(r)
1707        }
1708        fn fixed<'a, R: AvroRead>(
1709            self,
1710            r: ValueOrReader<'a, &'a [u8], R>,
1711        ) -> Result<(), AvroError> {
1712            self.maybe_skip(r)
1713        }
1714        fn array<A: AvroArrayAccess>(self, a: &mut A) -> Result<(), AvroError> {
1715            while a.decode_next(TrivialDecoder)?.is_some() {}
1716            Ok(())
1717        }
1718
1719        fn map<M: AvroMapAccess>(self, m: &mut M) -> Result<(), AvroError> {
1720            while let Some((_n, entry)) = m.next_entry()? {
1721                entry.decode_field(TrivialDecoder)?
1722            }
1723            Ok(())
1724        }
1725    }
1726    pub struct ValueDecoder;
1727    impl AvroDecode for ValueDecoder {
1728        type Out = Value;
1729        fn record<R: AvroRead, A: AvroRecordAccess<R>>(
1730            self,
1731            a: &mut A,
1732        ) -> Result<Value, AvroError> {
1733            let mut fields = vec![];
1734            while let Some((name, idx, f)) = a.next_field()? {
1735                let next = ValueDecoder;
1736                let val = f.decode_field(next)?;
1737                fields.push((idx, (name.to_string(), val)));
1738            }
1739            fields.sort_by_key(|(idx, _)| *idx);
1740
1741            Ok(Value::Record(
1742                fields
1743                    .into_iter()
1744                    .map(|(_idx, (name, val))| (name, val))
1745                    .collect(),
1746            ))
1747        }
1748        fn union_branch<'a, R: AvroRead, D: AvroDeserializer>(
1749            self,
1750            index: usize,
1751            n_variants: usize,
1752            null_variant: Option<usize>,
1753            deserializer: D,
1754            reader: &'a mut R,
1755        ) -> Result<Value, AvroError> {
1756            let next = ValueDecoder;
1757            let inner = Box::new(deserializer.deserialize(reader, next)?);
1758            Ok(Value::Union {
1759                index,
1760                inner,
1761                n_variants,
1762                null_variant,
1763            })
1764        }
1765        fn array<A: AvroArrayAccess>(self, a: &mut A) -> Result<Value, AvroError> {
1766            let mut items = vec![];
1767            loop {
1768                let next = ValueDecoder;
1769
1770                if let Some(value) = a.decode_next(next)? {
1771                    items.push(value)
1772                } else {
1773                    break;
1774                }
1775            }
1776            Ok(Value::Array(items))
1777        }
1778        fn enum_variant(self, symbol: &str, idx: usize) -> Result<Value, AvroError> {
1779            Ok(Value::Enum(idx, symbol.to_string()))
1780        }
1781        fn scalar(self, scalar: Scalar) -> Result<Value, AvroError> {
1782            Ok(scalar.into())
1783        }
1784        fn decimal<'a, R: AvroRead>(
1785            self,
1786            precision: usize,
1787            scale: usize,
1788            r: ValueOrReader<'a, &'a [u8], R>,
1789        ) -> Result<Value, AvroError> {
1790            let unscaled = match r {
1791                ValueOrReader::Value(buf) => buf.to_vec(),
1792                ValueOrReader::Reader { len, r } => {
1793                    let mut buf = vec![];
1794                    buf.resize_with(len, Default::default);
1795                    r.read_exact(&mut buf)?;
1796                    buf
1797                }
1798            };
1799            Ok(Value::Decimal(DecimalValue {
1800                unscaled,
1801                precision,
1802                scale,
1803            }))
1804        }
1805        fn bytes<'a, R: AvroRead>(
1806            self,
1807            r: ValueOrReader<'a, &'a [u8], R>,
1808        ) -> Result<Value, AvroError> {
1809            let buf = match r {
1810                ValueOrReader::Value(buf) => buf.to_vec(),
1811                ValueOrReader::Reader { len, r } => {
1812                    let mut buf = vec![];
1813                    buf.resize_with(len, Default::default);
1814                    r.read_exact(&mut buf)?;
1815                    buf
1816                }
1817            };
1818            Ok(Value::Bytes(buf))
1819        }
1820        fn string<'a, R: AvroRead>(
1821            self,
1822            r: ValueOrReader<'a, &'a str, R>,
1823        ) -> Result<Value, AvroError> {
1824            let s = match r {
1825                ValueOrReader::Value(s) => s.to_string(),
1826                ValueOrReader::Reader { len, r } => {
1827                    let mut buf = vec![];
1828                    buf.resize_with(len, Default::default);
1829                    r.read_exact(&mut buf)?;
1830                    String::from_utf8(buf)
1831                        .map_err(|_e| AvroError::Decode(DecodeError::StringUtf8Error))?
1832                }
1833            };
1834            Ok(Value::String(s))
1835        }
1836        fn json<'a, R: AvroRead>(
1837            self,
1838            r: ValueOrReader<'a, &'a serde_json::Value, R>,
1839        ) -> Result<Value, AvroError> {
1840            let val = match r {
1841                ValueOrReader::Value(val) => val.clone(),
1842                ValueOrReader::Reader { len, r } => {
1843                    let mut buf = vec![];
1844                    buf.resize_with(len, Default::default);
1845                    r.read_exact(&mut buf)?;
1846                    serde_json::from_slice(&buf).map_err(|e| {
1847                        AvroError::Decode(DecodeError::BadJson {
1848                            category: e.classify(),
1849                            bytes: buf.to_owned(),
1850                        })
1851                    })?
1852                }
1853            };
1854            Ok(Value::Json(val))
1855        }
1856        fn uuid<'a, R: AvroRead>(
1857            self,
1858            r: ValueOrReader<'a, &'a [u8], R>,
1859        ) -> Result<Value, AvroError> {
1860            let buf = match r {
1861                ValueOrReader::Value(val) => val.to_vec(),
1862                ValueOrReader::Reader { len, r } => {
1863                    let mut buf = vec![];
1864                    buf.resize_with(len, Default::default);
1865                    r.read_exact(&mut buf)?;
1866                    buf
1867                }
1868            };
1869            let s = std::str::from_utf8(&buf)
1870                .map_err(|_| AvroError::Decode(DecodeError::UuidUtf8Error))?;
1871            let val =
1872                uuid::Uuid::parse_str(s).map_err(|e| AvroError::Decode(DecodeError::BadUuid(e)))?;
1873            Ok(Value::Uuid(val))
1874        }
1875        fn fixed<'a, R: AvroRead>(
1876            self,
1877            r: ValueOrReader<'a, &'a [u8], R>,
1878        ) -> Result<Value, AvroError> {
1879            let buf = match r {
1880                ValueOrReader::Value(buf) => buf.to_vec(),
1881                ValueOrReader::Reader { len, r } => {
1882                    let mut buf = vec![];
1883                    buf.resize_with(len, Default::default);
1884                    r.read_exact(&mut buf)?;
1885                    buf
1886                }
1887            };
1888            Ok(Value::Fixed(buf.len(), buf))
1889        }
1890        fn map<M: AvroMapAccess>(self, m: &mut M) -> Result<Value, AvroError> {
1891            let mut entries = BTreeMap::new();
1892            while let Some((name, a)) = m.next_entry()? {
1893                let d = ValueDecoder;
1894                let val = a.decode_field(d)?;
1895                entries.insert(name, val);
1896            }
1897            Ok(Value::Map(entries))
1898        }
1899    }
1900}
1901
1902impl<'a> AvroDeserializer for &'a Value {
1903    fn deserialize<R: AvroRead, D: AvroDecode>(
1904        self,
1905        _r: &mut R,
1906        d: D,
1907    ) -> Result<D::Out, AvroError> {
1908        give_value(d, self)
1909    }
1910}
1911
1912pub fn give_value<D: AvroDecode>(d: D, v: &Value) -> Result<D::Out, AvroError> {
1913    use ValueOrReader::Value as V;
1914    match v {
1915        Value::Null => d.scalar(Scalar::Null),
1916        Value::Boolean(val) => d.scalar(Scalar::Boolean(*val)),
1917        Value::Int(val) => d.scalar(Scalar::Int(*val)),
1918        Value::Long(val) => d.scalar(Scalar::Long(*val)),
1919        Value::Float(val) => d.scalar(Scalar::Float(*val)),
1920        Value::Double(val) => d.scalar(Scalar::Double(*val)),
1921        Value::Date(val) => d.scalar(Scalar::Date(*val)),
1922        Value::Timestamp(val) => d.scalar(Scalar::Timestamp(*val)),
1923        // The &[u8] parameter here (and elsewhere in this function) is arbitrary, but we have to put in something in order for the function
1924        // to type-check
1925        Value::Decimal(val) => d.decimal::<&[u8]>(val.precision, val.scale, V(&val.unscaled)),
1926        Value::Bytes(val) => d.bytes::<&[u8]>(V(val)),
1927        Value::String(val) => d.string::<&[u8]>(V(val)),
1928        Value::Fixed(_len, val) => d.fixed::<&[u8]>(V(val)),
1929        Value::Enum(idx, symbol) => d.enum_variant(symbol, *idx),
1930        Value::Union {
1931            index,
1932            inner,
1933            n_variants,
1934            null_variant,
1935        } => {
1936            let mut empty_reader: &[u8] = &[];
1937            d.union_branch(
1938                *index,
1939                *n_variants,
1940                *null_variant,
1941                &**inner,
1942                &mut empty_reader,
1943            )
1944        }
1945        Value::Array(val) => {
1946            let mut a = ValueArrayAccess::new(val);
1947            d.array(&mut a)
1948        }
1949        Value::Map(val) => {
1950            let vals: Vec<_> = val.clone().into_iter().collect();
1951            let mut m = ValueMapAccess::new(vals.as_slice());
1952            d.map(&mut m)
1953        }
1954        Value::Record(val) => {
1955            let mut a = ValueRecordAccess::new(val);
1956            d.record(&mut a)
1957        }
1958        Value::Json(val) => d.json::<&[u8]>(V(val)),
1959        Value::Uuid(val) => d.uuid::<&[u8]>(V(val.to_string().as_bytes())),
1960    }
1961}
1962
1963pub trait AvroDeserializer {
1964    fn deserialize<R: AvroRead, D: AvroDecode>(self, r: &mut R, d: D) -> Result<D::Out, AvroError>;
1965}
1966
1967#[derive(Clone, Copy)]
1968pub struct GeneralDeserializer<'a> {
1969    pub schema: SchemaNode<'a>,
1970}
1971
1972/// Cap on recursive `GeneralDeserializer::deserialize` calls. Avro records
1973/// may reference themselves (`{"name":"X","type":"record","fields":[
1974/// {"name":"x","type":"X"}]}`), so a malicious file plus matching wire
1975/// bytes can recurse forever and overflow the stack.
1976const MAX_DECODE_DEPTH: usize = 128;
1977
1978thread_local! {
1979    static DECODE_DEPTH: std::cell::Cell<usize> = const { std::cell::Cell::new(0) };
1980    /// Cumulative `Value` nodes decoded so far in the current top-level decode,
1981    /// shared by every array and map in the datum and bounded by
1982    /// [`MAX_VALUE_NODES`]. Reset to `0` at each top-level entry (see
1983    /// [`DecodeDepthGuard::enter`]) so the budget composes across nesting
1984    /// instead of resetting per collection. Charged via [`charge_value_nodes`].
1985    static DECODE_NODES: std::cell::Cell<usize> = const { std::cell::Cell::new(0) };
1986}
1987
1988struct DecodeDepthGuard;
1989impl DecodeDepthGuard {
1990    fn enter() -> Result<Self, AvroError> {
1991        DECODE_DEPTH.with(|d| {
1992            let new = d.get() + 1;
1993            if new > MAX_DECODE_DEPTH {
1994                return Err(AvroError::Decode(DecodeError::Custom(format!(
1995                    "Avro decode depth exceeds limit {MAX_DECODE_DEPTH}"
1996                ))));
1997            }
1998            d.set(new);
1999            // The `Value`-node budget is shared across every array/map in one
2000            // datum so nesting can't multiply the cap (see `MAX_VALUE_NODES`).
2001            // This is the top-level entry (depth 0 -> 1), so reset it: each datum
2002            // starts fresh even if a previous decode on this thread errored out
2003            // partway and left the counter non-zero.
2004            if new == 1 {
2005                DECODE_NODES.with(|n| n.set(0));
2006            }
2007            Ok(DecodeDepthGuard)
2008        })
2009    }
2010}
2011impl Drop for DecodeDepthGuard {
2012    fn drop(&mut self) {
2013        DECODE_DEPTH.with(|d| d.set(d.get().saturating_sub(1)));
2014    }
2015}
2016
2017/// Charges `nodes` against the per-datum [`DECODE_NODES`] budget shared by every
2018/// array and map in a single top-level decode, rejecting once the cumulative
2019/// total exceeds [`MAX_VALUE_NODES`]. `kind` (`"array"` / `"map"`) only labels
2020/// the error.
2021///
2022/// The budget is shared — rather than tracked per collection instance — so the
2023/// cap composes across nesting; see [`MAX_VALUE_NODES`] for why a per-collection
2024/// budget would let nested zero-width collections amplify past it.
2025fn charge_value_nodes(kind: &str, nodes: usize) -> Result<(), AvroError> {
2026    DECODE_NODES.with(|n| {
2027        let total = n.get().saturating_add(nodes);
2028        if total > MAX_VALUE_NODES {
2029            return Err(AvroError::Decode(DecodeError::Custom(format!(
2030                "Avro {kind} decode exceeds cumulative limit {MAX_VALUE_NODES} decoded values"
2031            ))));
2032        }
2033        n.set(total);
2034        Ok(())
2035    })
2036}
2037
2038impl<'a> AvroDeserializer for GeneralDeserializer<'a> {
2039    fn deserialize<R: AvroRead, D: AvroDecode>(self, r: &mut R, d: D) -> Result<D::Out, AvroError> {
2040        let _guard = DecodeDepthGuard::enter()?;
2041        use ValueOrReader::Reader;
2042        match self.schema.inner {
2043            SchemaPiece::Null => d.scalar(Scalar::Null),
2044            SchemaPiece::Boolean => {
2045                let mut buf = [0u8; 1];
2046                r.read_exact(&mut buf[..])?;
2047                let val = match buf[0] {
2048                    0u8 => false,
2049                    1u8 => true,
2050                    other => return Err(AvroError::Decode(DecodeError::BadBoolean(other))),
2051                };
2052                d.scalar(Scalar::Boolean(val))
2053            }
2054            SchemaPiece::Int => {
2055                let val = zag_i32(r)?;
2056                d.scalar(Scalar::Int(val))
2057            }
2058            SchemaPiece::Long => {
2059                let val = zag_i64(r)?;
2060                d.scalar(Scalar::Long(val))
2061            }
2062            SchemaPiece::Float => {
2063                let val = decode_float(r)?;
2064                d.scalar(Scalar::Float(val))
2065            }
2066            SchemaPiece::Double => {
2067                let val = decode_double(r)?;
2068                d.scalar(Scalar::Double(val))
2069            }
2070            SchemaPiece::Date => {
2071                let days = zag_i32(r)?;
2072                d.scalar(Scalar::Date(days))
2073            }
2074            SchemaPiece::TimestampMilli => {
2075                let total_millis = zag_i64(r)?;
2076                let scalar = match build_ts_value(total_millis, TsUnit::Millis)? {
2077                    Value::Timestamp(ts) => Scalar::Timestamp(ts),
2078                    _ => unreachable!(),
2079                };
2080                d.scalar(scalar)
2081            }
2082            SchemaPiece::TimestampMicro => {
2083                let total_micros = zag_i64(r)?;
2084                let scalar = match build_ts_value(total_micros, TsUnit::Micros)? {
2085                    Value::Timestamp(ts) => Scalar::Timestamp(ts),
2086                    _ => unreachable!(),
2087                };
2088                d.scalar(scalar)
2089            }
2090            SchemaPiece::Decimal {
2091                precision,
2092                scale,
2093                fixed_size,
2094            } => {
2095                let len = fixed_size.map(Ok).unwrap_or_else(|| decode_len(r))?;
2096                d.decimal(*precision, *scale, Reader { len, r })
2097            }
2098            SchemaPiece::Bytes => {
2099                let len = decode_len(r)?;
2100                d.bytes(Reader { len, r })
2101            }
2102            SchemaPiece::String => {
2103                let len = decode_len(r)?;
2104                d.string(Reader { len, r })
2105            }
2106            SchemaPiece::Json => {
2107                let len = decode_len(r)?;
2108                d.json(Reader { len, r })
2109            }
2110            SchemaPiece::Uuid => {
2111                let len = decode_len(r)?;
2112                d.uuid(Reader { len, r })
2113            }
2114            SchemaPiece::Array(inner) => {
2115                // From the spec:
2116                // Arrays are encoded as a series of blocks. Each block consists of a long count value, followed by that many array items. A block with count zero indicates the end of the array. Each item is encoded per the array's item schema.
2117                // If a block's count is negative, its absolute value is used, and the count is followed immediately by a long block size indicating the number of bytes in the block. This block size permits fast skipping through data, e.g., when projecting a record to a subset of its fields.
2118
2119                let mut a = SimpleArrayAccess::new(r, self.schema.step(inner));
2120                d.array(&mut a)
2121            }
2122            SchemaPiece::Map(inner) => {
2123                // See logic for `SchemaPiece::Array` above. Maps are encoded similarly.
2124                let mut m = SimpleMapAccess::new(self.schema.step(inner), r);
2125                d.map(&mut m)
2126            }
2127            SchemaPiece::Union(inner) => {
2128                let index = decode_long_nonneg(r)? as usize;
2129                let variants = inner.variants();
2130                match variants.get(index) {
2131                    Some(variant) => {
2132                        let n_variants = variants.len();
2133                        let null_variant = variants
2134                            .iter()
2135                            .position(|v| v == &SchemaPieceOrNamed::Piece(SchemaPiece::Null));
2136                        let dsr = GeneralDeserializer {
2137                            schema: self.schema.step(variant),
2138                        };
2139                        d.union_branch(index, n_variants, null_variant, dsr, r)
2140                    }
2141                    None => Err(AvroError::Decode(DecodeError::BadUnionIndex {
2142                        index,
2143                        len: variants.len(),
2144                    })),
2145                }
2146            }
2147            SchemaPiece::ResolveIntLong => {
2148                let val = zag_i32(r)? as i64;
2149                d.scalar(Scalar::Long(val))
2150            }
2151            SchemaPiece::ResolveIntFloat => {
2152                let val = zag_i32(r)? as f32;
2153                d.scalar(Scalar::Float(val))
2154            }
2155            SchemaPiece::ResolveIntDouble => {
2156                let val = zag_i32(r)? as f64;
2157                d.scalar(Scalar::Double(val))
2158            }
2159            SchemaPiece::ResolveLongFloat => {
2160                let val = zag_i64(r)? as f32;
2161                d.scalar(Scalar::Float(val))
2162            }
2163            SchemaPiece::ResolveLongDouble => {
2164                let val = zag_i64(r)? as f64;
2165                d.scalar(Scalar::Double(val))
2166            }
2167            SchemaPiece::ResolveFloatDouble => {
2168                let val = decode_float(r)? as f64;
2169                d.scalar(Scalar::Double(val))
2170            }
2171            SchemaPiece::ResolveConcreteUnion {
2172                index,
2173                inner,
2174                n_reader_variants,
2175                reader_null_variant,
2176            } => {
2177                let dsr = GeneralDeserializer {
2178                    schema: self.schema.step(&**inner),
2179                };
2180                d.union_branch(*index, *n_reader_variants, *reader_null_variant, dsr, r)
2181            }
2182            SchemaPiece::ResolveUnionUnion {
2183                permutation,
2184                n_reader_variants,
2185                reader_null_variant,
2186            } => {
2187                let index = decode_long_nonneg(r)? as usize;
2188                if index >= permutation.len() {
2189                    return Err(AvroError::Decode(DecodeError::BadUnionIndex {
2190                        index,
2191                        len: permutation.len(),
2192                    }));
2193                }
2194                match &permutation[index] {
2195                    Err(e) => Err(e.clone()),
2196                    Ok((index, variant)) => {
2197                        let dsr = GeneralDeserializer {
2198                            schema: self.schema.step(variant),
2199                        };
2200                        d.union_branch(*index, *n_reader_variants, *reader_null_variant, dsr, r)
2201                    }
2202                }
2203            }
2204            SchemaPiece::ResolveUnionConcrete { index, inner } => {
2205                let found_index = decode_long_nonneg(r)? as usize;
2206                if *index != found_index {
2207                    Err(AvroError::Decode(DecodeError::WrongUnionIndex {
2208                        expected: *index,
2209                        actual: found_index,
2210                    }))
2211                } else {
2212                    let dsr = GeneralDeserializer {
2213                        schema: self.schema.step(inner.as_ref()),
2214                    };
2215                    // The reader is not expecting a union here, so don't call `D::union_branch`
2216                    dsr.deserialize(r, d)
2217                }
2218            }
2219            SchemaPiece::Record {
2220                doc: _,
2221                fields,
2222                lookup: _,
2223            } => {
2224                let mut a = SimpleRecordAccess::new(self.schema, r, fields);
2225                d.record(&mut a)
2226            }
2227            SchemaPiece::Enum {
2228                symbols,
2229                doc: _,
2230                default_idx: _,
2231            } => {
2232                let index = decode_int_nonneg(r)? as usize;
2233                match symbols.get(index) {
2234                    None => Err(AvroError::Decode(DecodeError::BadEnumIndex {
2235                        index,
2236                        len: symbols.len(),
2237                    })),
2238                    Some(symbol) => d.enum_variant(symbol, index),
2239                }
2240            }
2241            SchemaPiece::Fixed { size } => d.fixed(Reader { len: *size, r }),
2242            // XXX - This does not deliver fields to the consumer in the same order they were
2243            // declared in the reader schema, which might cause headache for consumers...
2244            // Unfortunately, there isn't a good way to do so without pre-decoding the whole record
2245            // (which would require a lot of allocations)
2246            // and then sorting the fields. So, just let the consumer deal with re-ordering.
2247            SchemaPiece::ResolveRecord {
2248                defaults,
2249                fields,
2250                n_reader_fields: _,
2251            } => {
2252                let mut a = ResolvedRecordAccess::new(defaults, fields, r, self.schema);
2253                d.record(&mut a)
2254            }
2255            SchemaPiece::ResolveEnum {
2256                doc: _,
2257                symbols,
2258                default,
2259            } => {
2260                let index = decode_int_nonneg(r)? as usize;
2261                match symbols.get(index) {
2262                    None => Err(AvroError::Decode(DecodeError::BadEnumIndex {
2263                        index,
2264                        len: symbols.len(),
2265                    })),
2266                    Some(op) => match op {
2267                        Err(missing) => {
2268                            if let Some((reader_index, symbol)) = default.clone() {
2269                                d.enum_variant(&symbol, reader_index)
2270                            } else {
2271                                Err(AvroError::Decode(DecodeError::MissingEnumIndex {
2272                                    index,
2273                                    symbol: missing.clone(),
2274                                }))
2275                            }
2276                        }
2277                        Ok((index, name)) => d.enum_variant(name, *index),
2278                    },
2279                }
2280            }
2281            SchemaPiece::ResolveIntTsMilli => {
2282                let total_millis = zag_i32(r)?;
2283                let scalar = match build_ts_value(total_millis as i64, TsUnit::Millis)? {
2284                    Value::Timestamp(ts) => Scalar::Timestamp(ts),
2285                    _ => unreachable!(),
2286                };
2287                d.scalar(scalar)
2288            }
2289            SchemaPiece::ResolveIntTsMicro => {
2290                let total_micros = zag_i32(r)?;
2291                let scalar = match build_ts_value(total_micros as i64, TsUnit::Micros)? {
2292                    Value::Timestamp(ts) => Scalar::Timestamp(ts),
2293                    _ => unreachable!(),
2294                };
2295                d.scalar(scalar)
2296            }
2297            SchemaPiece::ResolveDateTimestamp => {
2298                let days = zag_i32(r)?;
2299
2300                let date = NaiveDate::from_ymd_opt(1970, 1, 1)
2301                    .expect("naive date known valid")
2302                    .checked_add_signed(
2303                        chrono::Duration::try_days(days.into())
2304                            .ok_or(AvroError::Decode(DecodeError::BadDate(days)))?,
2305                    )
2306                    .ok_or(AvroError::Decode(DecodeError::BadDate(days)))?;
2307                let dt = date.and_hms_opt(0, 0, 0).expect("HMS known valid");
2308                d.scalar(Scalar::Timestamp(dt))
2309            }
2310        }
2311    }
2312}
2313/// Decode a `Value` from avro format given its `Schema`.
2314pub fn decode<'a, R: AvroRead>(
2315    schema: SchemaNode<'a>,
2316    reader: &'a mut R,
2317) -> Result<Value, AvroError> {
2318    let d = ValueDecoder;
2319    let dsr = GeneralDeserializer { schema };
2320    let val = dsr.deserialize(reader, d)?;
2321    Ok(val)
2322}