Skip to main content

facet_postcard/
parser.rs

1//! Postcard parser implementing FormatParser and FormatJitParser.
2//!
3//! Postcard is NOT a self-describing format, but Tier-0 deserialization is supported
4//! via the `hint_struct_fields` mechanism. The driver tells the parser how many fields
5//! to expect, and the parser emits `OrderedField` events accordingly.
6
7use alloc::borrow::Cow;
8use alloc::vec::Vec;
9
10use crate::error::{PostcardError, codes};
11use facet_format::{
12    ContainerKind, EnumVariantHint, FieldEvidence, FieldKey, FieldLocationHint, FormatParser,
13    ParseEvent, ProbeStream, ScalarTypeHint, ScalarValue,
14};
15
16/// Stored variant metadata for enum parsing.
17#[derive(Debug, Clone)]
18struct VariantMeta {
19    name: String,
20    kind: facet_core::StructKind,
21    field_count: usize,
22}
23
24/// Parser state for tracking nested structures.
25#[derive(Debug, Clone)]
26enum ParserState {
27    /// At the top level or after completing a value.
28    Ready,
29    /// Inside a struct, tracking remaining fields.
30    InStruct { remaining_fields: usize },
31    /// Inside a sequence, tracking remaining elements.
32    InSequence { remaining_elements: u64 },
33    /// Inside an enum variant, tracking parsing progress.
34    InEnum {
35        variant_name: String,
36        variant_kind: facet_core::StructKind,
37        variant_field_count: usize,
38        field_key_emitted: bool,
39        /// For multi-field variants, whether we've emitted the inner wrapper start
40        wrapper_start_emitted: bool,
41        /// For multi-field variants, whether we've emitted the inner wrapper end
42        wrapper_end_emitted: bool,
43    },
44    /// Inside a map, tracking remaining entries.
45    /// Maps are serialized as sequences of key-value pairs.
46    InMap { remaining_entries: u64 },
47    /// Inside a dynamically tagged array (facet_value::Value array).
48    InDynamicArray { remaining_elements: u64 },
49    /// Inside a dynamically tagged object (facet_value::Value object).
50    InDynamicObject {
51        remaining_entries: u64,
52        expecting_key: bool,
53    },
54}
55
56/// Postcard parser for Tier-0 and Tier-2 deserialization.
57///
58/// For Tier-0, the parser relies on `hint_struct_fields` to know how many fields
59/// to expect in structs. Sequences are length-prefixed in the wire format.
60pub struct PostcardParser<'de> {
61    input: &'de [u8],
62    pos: usize,
63    /// Stack of parser states for nested structures.
64    state_stack: Vec<ParserState>,
65    /// Peeked event (for `peek_event`).
66    peeked: Option<ParseEvent<'de>>,
67    /// Pending struct field count from `hint_struct_fields`.
68    pending_struct_fields: Option<usize>,
69    /// Pending scalar type hint from `hint_scalar_type`.
70    pending_scalar_type: Option<ScalarTypeHint>,
71    /// Pending sequence flag from `hint_sequence`.
72    pending_sequence: bool,
73    /// Pending byte sequence flag from `hint_byte_sequence`.
74    pending_byte_sequence: bool,
75    /// Pending fixed-size array length from `hint_array`.
76    pending_array: Option<usize>,
77    /// Pending option flag from `hint_option`.
78    pending_option: bool,
79    /// Pending enum variant metadata from `hint_enum`.
80    pending_enum: Option<Vec<VariantMeta>>,
81    /// Pending opaque scalar type from `hint_opaque_scalar`.
82    pending_opaque: Option<OpaqueScalarHint>,
83    /// Pending map flag from `hint_map`.
84    pending_map: bool,
85    /// Pending dynamic value tag from `hint_dynamic_value`.
86    pending_dynamic: bool,
87}
88
89/// Information about an opaque scalar type for format-specific handling.
90#[derive(Debug, Clone)]
91struct OpaqueScalarHint {
92    type_identifier: &'static str,
93    /// True if the inner type is f32 (for OrderedFloat/NotNan)
94    inner_is_f32: bool,
95}
96
97impl<'de> PostcardParser<'de> {
98    /// Create a new postcard parser from input bytes.
99    pub const fn new(input: &'de [u8]) -> Self {
100        Self {
101            input,
102            pos: 0,
103            state_stack: Vec::new(),
104            peeked: None,
105            pending_struct_fields: None,
106            pending_scalar_type: None,
107            pending_sequence: false,
108            pending_byte_sequence: false,
109            pending_array: None,
110            pending_option: false,
111            pending_enum: None,
112            pending_opaque: None,
113            pending_map: false,
114            pending_dynamic: false,
115        }
116    }
117
118    /// Read a single byte, advancing position.
119    fn read_byte(&mut self) -> Result<u8, PostcardError> {
120        if self.pos >= self.input.len() {
121            return Err(PostcardError {
122                code: codes::UNEXPECTED_EOF,
123                pos: self.pos,
124                message: "unexpected end of input".into(),
125                source_bytes: None,
126            });
127        }
128        let byte = self.input[self.pos];
129        self.pos += 1;
130        Ok(byte)
131    }
132
133    /// Read a varint (LEB128 encoded unsigned integer).
134    fn read_varint(&mut self) -> Result<u64, PostcardError> {
135        let mut result: u64 = 0;
136        let mut shift: u32 = 0;
137
138        loop {
139            let byte = self.read_byte()?;
140            let data = (byte & 0x7F) as u64;
141
142            if shift >= 64 {
143                return Err(PostcardError {
144                    code: codes::VARINT_OVERFLOW,
145                    pos: self.pos,
146                    message: "varint overflow".into(),
147                    source_bytes: None,
148                });
149            }
150
151            result |= data << shift;
152            shift += 7;
153
154            if (byte & 0x80) == 0 {
155                return Ok(result);
156            }
157        }
158    }
159
160    /// Read a signed varint (ZigZag + LEB128).
161    fn read_signed_varint(&mut self) -> Result<i64, PostcardError> {
162        let unsigned = self.read_varint()?;
163        // ZigZag decode: (n >> 1) ^ -(n & 1)
164        let decoded = ((unsigned >> 1) as i64) ^ -((unsigned & 1) as i64);
165        Ok(decoded)
166    }
167
168    /// Read a varint for u128 (LEB128 encoded, up to 19 bytes).
169    fn read_varint_u128(&mut self) -> Result<u128, PostcardError> {
170        let mut result: u128 = 0;
171        let mut shift: u32 = 0;
172
173        loop {
174            let byte = self.read_byte()?;
175            let data = (byte & 0x7F) as u128;
176
177            if shift >= 128 {
178                return Err(PostcardError {
179                    code: codes::VARINT_OVERFLOW,
180                    pos: self.pos,
181                    message: "varint overflow for u128".into(),
182                    source_bytes: None,
183                });
184            }
185
186            result |= data << shift;
187            shift += 7;
188
189            if (byte & 0x80) == 0 {
190                return Ok(result);
191            }
192        }
193    }
194
195    /// Read a signed varint for i128 (ZigZag + LEB128).
196    fn read_signed_varint_i128(&mut self) -> Result<i128, PostcardError> {
197        let unsigned = self.read_varint_u128()?;
198        // ZigZag decode: (n >> 1) ^ -(n & 1)
199        let decoded = ((unsigned >> 1) as i128) ^ -((unsigned & 1) as i128);
200        Ok(decoded)
201    }
202
203    /// Read N bytes as a slice.
204    fn read_bytes(&mut self, len: usize) -> Result<&'de [u8], PostcardError> {
205        if self.pos + len > self.input.len() {
206            return Err(PostcardError {
207                code: codes::UNEXPECTED_EOF,
208                pos: self.pos,
209                message: "unexpected end of input reading bytes".into(),
210                source_bytes: None,
211            });
212        }
213        let bytes = &self.input[self.pos..self.pos + len];
214        self.pos += len;
215        Ok(bytes)
216    }
217
218    /// Get the current parser state (top of stack or Ready).
219    fn current_state(&self) -> &ParserState {
220        self.state_stack.last().unwrap_or(&ParserState::Ready)
221    }
222
223    /// Generate the next event based on current state.
224    fn generate_next_event(&mut self) -> Result<ParseEvent<'de>, PostcardError> {
225        // Check if we have a pending option hint
226        if self.pending_option {
227            self.pending_option = false;
228            let discriminant = self.read_byte()?;
229            match discriminant {
230                0x00 => return Ok(ParseEvent::Scalar(ScalarValue::Null)),
231                0x01 => {
232                    // Some(value) - consumed the discriminant. The deserializer will peek to check
233                    // if it's None, see this is not Null, and then call deserialize_into for the value.
234                    // Return a placeholder event (like OrderedField) to signal "not None".
235                    // The deserializer will then call hint + expect for the inner value.
236                    return Ok(ParseEvent::OrderedField);
237                }
238                _ => {
239                    return Err(PostcardError {
240                        code: codes::INVALID_OPTION_DISCRIMINANT,
241                        pos: self.pos - 1,
242                        message: format!("invalid Option discriminant: {}", discriminant),
243                        source_bytes: None,
244                    });
245                }
246            }
247        }
248
249        // Check if we have a pending dynamic value hint (tagged dynamic values)
250        if self.pending_dynamic {
251            self.pending_dynamic = false;
252            return self.parse_dynamic_tag_event();
253        }
254
255        // Check if we have a pending enum hint
256        if let Some(variants) = self.pending_enum.take() {
257            let variant_index = self.read_varint()? as usize;
258            if variant_index >= variants.len() {
259                return Err(PostcardError {
260                    code: codes::INVALID_ENUM_DISCRIMINANT,
261                    pos: self.pos,
262                    message: format!(
263                        "enum variant index {} out of range (max {})",
264                        variant_index,
265                        variants.len() - 1
266                    ),
267                    source_bytes: None,
268                });
269            }
270            let variant = &variants[variant_index];
271            // Push InEnum state to emit StructStart, FieldKey, content, StructEnd sequence
272            self.state_stack.push(ParserState::InEnum {
273                variant_name: variant.name.clone(),
274                variant_kind: variant.kind,
275                variant_field_count: variant.field_count,
276                field_key_emitted: false,
277                wrapper_start_emitted: false,
278                wrapper_end_emitted: false,
279            });
280            return Ok(ParseEvent::StructStart(ContainerKind::Object));
281        }
282
283        // Check if we have a pending opaque scalar hint (format-specific binary encoding)
284        if let Some(opaque) = self.pending_opaque.take() {
285            return self.parse_opaque_scalar(opaque);
286        }
287
288        // Check if we have a pending scalar type hint
289        if let Some(hint) = self.pending_scalar_type.take() {
290            return self.parse_scalar_with_hint(hint);
291        }
292
293        // Check if we have a pending sequence hint (variable-length, reads count from wire)
294        if self.pending_sequence {
295            self.pending_sequence = false;
296            let count = self.read_varint()?;
297            self.state_stack.push(ParserState::InSequence {
298                remaining_elements: count,
299            });
300            return Ok(ParseEvent::SequenceStart(ContainerKind::Array));
301        }
302
303        // Check if we have a pending byte sequence hint (bulk read for Vec<u8>)
304        if self.pending_byte_sequence {
305            self.pending_byte_sequence = false;
306            let bytes = self.parse_bytes()?;
307            return Ok(ParseEvent::Scalar(ScalarValue::Bytes(Cow::Borrowed(bytes))));
308        }
309
310        // Check if we have a pending fixed-size array hint (length known from type, no wire prefix)
311        if let Some(len) = self.pending_array.take() {
312            self.state_stack.push(ParserState::InSequence {
313                remaining_elements: len as u64,
314            });
315            return Ok(ParseEvent::SequenceStart(ContainerKind::Array));
316        }
317
318        // Check if we have a pending struct hint
319        if let Some(num_fields) = self.pending_struct_fields.take() {
320            self.state_stack.push(ParserState::InStruct {
321                remaining_fields: num_fields,
322            });
323            return Ok(ParseEvent::StructStart(ContainerKind::Object));
324        }
325
326        // Check if we have a pending map hint (maps are length-prefixed sequences of key-value pairs)
327        if self.pending_map {
328            self.pending_map = false;
329            let count = self.read_varint()?;
330            self.state_stack.push(ParserState::InMap {
331                remaining_entries: count,
332            });
333            return Ok(ParseEvent::SequenceStart(ContainerKind::Array));
334        }
335
336        // Check current state
337        match self.current_state().clone() {
338            ParserState::Ready => {
339                // At top level without a hint - error
340                Err(PostcardError {
341                    code: codes::UNSUPPORTED,
342                    pos: self.pos,
343                    message: "postcard parser needs type hints (use hint_scalar_type, hint_struct_fields, or hint_sequence)".into(),
344                    source_bytes: None,
345                })
346            }
347            ParserState::InStruct { remaining_fields } => {
348                if remaining_fields == 0 {
349                    // Struct complete
350                    self.state_stack.pop();
351                    Ok(ParseEvent::StructEnd)
352                } else {
353                    // More fields to go - emit OrderedField and decrement
354                    if let Some(ParserState::InStruct { remaining_fields }) =
355                        self.state_stack.last_mut()
356                    {
357                        *remaining_fields -= 1;
358                    }
359                    Ok(ParseEvent::OrderedField)
360                }
361            }
362            ParserState::InSequence { remaining_elements } => {
363                if remaining_elements == 0 {
364                    // Sequence complete
365                    self.state_stack.pop();
366                    Ok(ParseEvent::SequenceEnd)
367                } else {
368                    // More elements remaining. Return OrderedField as a placeholder to indicate
369                    // "not end yet". The deserializer will then call hint + expect for the next element.
370                    // Decrement the counter after returning the placeholder.
371                    if let Some(ParserState::InSequence { remaining_elements }) =
372                        self.state_stack.last_mut()
373                    {
374                        *remaining_elements -= 1;
375                    }
376                    Ok(ParseEvent::OrderedField)
377                }
378            }
379            ParserState::InEnum {
380                variant_name,
381                variant_kind,
382                variant_field_count,
383                field_key_emitted,
384                wrapper_start_emitted,
385                wrapper_end_emitted,
386            } => {
387                use facet_core::StructKind;
388
389                if !field_key_emitted {
390                    // Step 1: Emit the FieldKey with the variant name
391                    if let Some(ParserState::InEnum {
392                        field_key_emitted, ..
393                    }) = self.state_stack.last_mut()
394                    {
395                        *field_key_emitted = true;
396                    }
397                    Ok(ParseEvent::FieldKey(FieldKey::new(
398                        Cow::Owned(variant_name.clone()),
399                        FieldLocationHint::KeyValue,
400                    )))
401                } else if !wrapper_start_emitted {
402                    // Step 2: After FieldKey, emit wrapper start (if needed)
403                    match variant_kind {
404                        StructKind::Unit => {
405                            // Unit variant - no wrapper, skip directly to StructEnd
406                            self.state_stack.pop();
407                            Ok(ParseEvent::StructEnd)
408                        }
409                        StructKind::Tuple | StructKind::TupleStruct => {
410                            // Check if it's a newtype (single-field) or multi-field tuple
411                            if variant_field_count == 1 {
412                                // Newtype variant - no wrapper, content consumed directly
413                                // Mark wrapper as emitted so we skip directly to final StructEnd
414                                if let Some(ParserState::InEnum {
415                                    wrapper_start_emitted,
416                                    wrapper_end_emitted,
417                                    ..
418                                }) = self.state_stack.last_mut()
419                                {
420                                    *wrapper_start_emitted = true;
421                                    *wrapper_end_emitted = true; // Skip wrapper end emission
422                                }
423                                // Recursively call to get the next event (likely a scalar hint response)
424                                self.generate_next_event()
425                            } else {
426                                // Multi-field tuple variant - emit SequenceStart and push InSequence state
427                                // But unlike regular sequences, tuple enum variants don't use OrderedField placeholders
428                                // The deserializer calls deserialize_into directly for each field
429                                // So we DON'T push InSequence - we track manually via wrapper_end_emitted
430                                if let Some(ParserState::InEnum {
431                                    wrapper_start_emitted,
432                                    ..
433                                }) = self.state_stack.last_mut()
434                                {
435                                    *wrapper_start_emitted = true;
436                                }
437                                Ok(ParseEvent::SequenceStart(ContainerKind::Array))
438                            }
439                        }
440                        StructKind::Struct => {
441                            // Struct variant - mark wrapper start emitted and push InStruct state
442                            // The InStruct state will emit OrderedField events for each field
443                            // (postcard encodes struct fields in order without names)
444                            if let Some(ParserState::InEnum {
445                                wrapper_start_emitted,
446                                ..
447                            }) = self.state_stack.last_mut()
448                            {
449                                *wrapper_start_emitted = true;
450                            }
451                            // Get the field count from the variant
452                            let field_count = if let ParserState::InEnum {
453                                variant_field_count,
454                                ..
455                            } = self.current_state()
456                            {
457                                *variant_field_count
458                            } else {
459                                0
460                            };
461                            self.state_stack.push(ParserState::InStruct {
462                                remaining_fields: field_count,
463                            });
464                            Ok(ParseEvent::StructStart(ContainerKind::Object))
465                        }
466                    }
467                } else if !wrapper_end_emitted {
468                    // Step 3: Emit wrapper end for multi-field variants
469                    match variant_kind {
470                        StructKind::Unit => {
471                            // Already handled above
472                            unreachable!()
473                        }
474                        StructKind::Tuple | StructKind::TupleStruct => {
475                            // For multi-field tuples, emit SequenceEnd
476                            if variant_field_count > 1 {
477                                if let Some(ParserState::InEnum {
478                                    wrapper_end_emitted,
479                                    ..
480                                }) = self.state_stack.last_mut()
481                                {
482                                    *wrapper_end_emitted = true;
483                                }
484                                Ok(ParseEvent::SequenceEnd)
485                            } else {
486                                // Newtype - already marked wrapper_end_emitted=true, skip to final StructEnd
487                                self.state_stack.pop();
488                                Ok(ParseEvent::StructEnd)
489                            }
490                        }
491                        StructKind::Struct => {
492                            // Struct variants use InStruct which already popped, so we're ready for final StructEnd
493                            self.state_stack.pop();
494                            Ok(ParseEvent::StructEnd)
495                        }
496                    }
497                } else {
498                    // Step 4: Emit final outer StructEnd
499                    // This is reached after wrapper end has been emitted
500                    self.state_stack.pop();
501                    Ok(ParseEvent::StructEnd)
502                }
503            }
504            ParserState::InMap { remaining_entries } => {
505                if remaining_entries == 0 {
506                    // Map complete
507                    self.state_stack.pop();
508                    Ok(ParseEvent::SequenceEnd)
509                } else {
510                    // More entries remaining. Return OrderedField as a placeholder to indicate
511                    // "not end yet". The deserializer will call hint + expect for key and value.
512                    // Decrement the counter after returning the placeholder.
513                    if let Some(ParserState::InMap { remaining_entries }) =
514                        self.state_stack.last_mut()
515                    {
516                        *remaining_entries -= 1;
517                    }
518                    Ok(ParseEvent::OrderedField)
519                }
520            }
521            ParserState::InDynamicArray { remaining_elements } => {
522                if remaining_elements == 0 {
523                    self.state_stack.pop();
524                    Ok(ParseEvent::SequenceEnd)
525                } else {
526                    self.parse_dynamic_tag_event()
527                }
528            }
529            ParserState::InDynamicObject {
530                remaining_entries,
531                expecting_key,
532            } => {
533                if remaining_entries == 0 {
534                    self.state_stack.pop();
535                    Ok(ParseEvent::StructEnd)
536                } else if expecting_key {
537                    let key = self.parse_string()?;
538                    if let Some(ParserState::InDynamicObject { expecting_key, .. }) =
539                        self.state_stack.last_mut()
540                    {
541                        *expecting_key = false;
542                    }
543                    Ok(ParseEvent::FieldKey(FieldKey::new(
544                        Cow::Borrowed(key),
545                        FieldLocationHint::KeyValue,
546                    )))
547                } else {
548                    self.parse_dynamic_tag_event()
549                }
550            }
551        }
552    }
553
554    /// Parse a scalar value with the given type hint.
555    fn parse_scalar_with_hint(
556        &mut self,
557        hint: ScalarTypeHint,
558    ) -> Result<ParseEvent<'de>, PostcardError> {
559        let scalar = match hint {
560            ScalarTypeHint::Bool => {
561                let val = self.parse_bool()?;
562                ScalarValue::Bool(val)
563            }
564            ScalarTypeHint::U8 => {
565                let val = self.parse_u8()?;
566                ScalarValue::U64(val as u64)
567            }
568            ScalarTypeHint::U16 => {
569                let val = self.parse_u16()?;
570                ScalarValue::U64(val as u64)
571            }
572            ScalarTypeHint::U32 => {
573                let val = self.parse_u32()?;
574                ScalarValue::U64(val as u64)
575            }
576            ScalarTypeHint::U64 => {
577                let val = self.parse_u64()?;
578                ScalarValue::U64(val)
579            }
580            ScalarTypeHint::U128 => {
581                let val = self.parse_u128()?;
582                ScalarValue::U128(val)
583            }
584            ScalarTypeHint::Usize => {
585                // usize is encoded as varint, decode as u64
586                let val = self.parse_u64()?;
587                ScalarValue::U64(val)
588            }
589            ScalarTypeHint::I8 => {
590                let val = self.parse_i8()?;
591                ScalarValue::I64(val as i64)
592            }
593            ScalarTypeHint::I16 => {
594                let val = self.parse_i16()?;
595                ScalarValue::I64(val as i64)
596            }
597            ScalarTypeHint::I32 => {
598                let val = self.parse_i32()?;
599                ScalarValue::I64(val as i64)
600            }
601            ScalarTypeHint::I64 => {
602                let val = self.parse_i64()?;
603                ScalarValue::I64(val)
604            }
605            ScalarTypeHint::I128 => {
606                let val = self.parse_i128()?;
607                ScalarValue::I128(val)
608            }
609            ScalarTypeHint::Isize => {
610                // isize is encoded as zigzag varint, decode as i64
611                let val = self.parse_i64()?;
612                ScalarValue::I64(val)
613            }
614            ScalarTypeHint::F32 => {
615                let val = self.parse_f32()?;
616                ScalarValue::F64(val as f64)
617            }
618            ScalarTypeHint::F64 => {
619                let val = self.parse_f64()?;
620                ScalarValue::F64(val)
621            }
622            ScalarTypeHint::String => {
623                let val = self.parse_string()?;
624                ScalarValue::Str(Cow::Borrowed(val))
625            }
626            ScalarTypeHint::Bytes => {
627                let val = self.parse_bytes()?;
628                ScalarValue::Bytes(Cow::Borrowed(val))
629            }
630            ScalarTypeHint::Char => {
631                // Per postcard spec: char is encoded as UTF-8 string (length-prefixed UTF-8 bytes)
632                let s = self.parse_string()?;
633                // Validate it's exactly one char
634                let mut chars = s.chars();
635                let c = chars.next().ok_or_else(|| PostcardError {
636                    code: codes::INVALID_UTF8,
637                    pos: self.pos,
638                    message: "empty string for char".into(),
639                    source_bytes: None,
640                })?;
641                if chars.next().is_some() {
642                    return Err(PostcardError {
643                        code: codes::INVALID_UTF8,
644                        pos: self.pos,
645                        message: "string contains more than one char".into(),
646                        source_bytes: None,
647                    });
648                }
649                // Represent as string since ScalarValue doesn't have Char
650                ScalarValue::Str(Cow::Owned(c.to_string()))
651            }
652        };
653        Ok(ParseEvent::Scalar(scalar))
654    }
655
656    /// Parse an opaque scalar value with format-specific binary encoding.
657    ///
658    /// This handles types like UUID (16 raw bytes), ULID (16 raw bytes),
659    /// OrderedFloat (raw float bytes), etc. that have efficient binary
660    /// representations in postcard.
661    fn parse_opaque_scalar(
662        &mut self,
663        opaque: OpaqueScalarHint,
664    ) -> Result<ParseEvent<'de>, PostcardError> {
665        let scalar = match opaque.type_identifier {
666            // UUID/ULID: 16 raw bytes (no length prefix)
667            "Uuid" | "Ulid" => {
668                let bytes = self.read_fixed_bytes(16)?;
669                ScalarValue::Bytes(Cow::Borrowed(bytes))
670            }
671            // OrderedFloat/NotNan: raw float bytes (size depends on inner type)
672            // We handle both f32 and f64 variants by checking the shape's inner field
673            "OrderedFloat" | "NotNan" => {
674                // Check inner shape to determine f32 vs f64
675                if opaque.inner_is_f32 {
676                    let val = self.parse_f32()?;
677                    ScalarValue::F64(val as f64)
678                } else {
679                    // Default to f64
680                    let val = self.parse_f64()?;
681                    ScalarValue::F64(val)
682                }
683            }
684            // Camino Utf8PathBuf/Utf8Path: regular string
685            "Utf8PathBuf" | "Utf8Path" => {
686                let val = self.parse_string()?;
687                ScalarValue::Str(Cow::Borrowed(val))
688            }
689            // Chrono types: RFC3339 strings
690            "DateTime<Utc>"
691            | "DateTime<Local>"
692            | "DateTime<FixedOffset>"
693            | "NaiveDateTime"
694            | "NaiveDate"
695            | "NaiveTime" => {
696                let val = self.parse_string()?;
697                ScalarValue::Str(Cow::Borrowed(val))
698            }
699            // Jiff types: RFC3339/ISO8601 strings
700            "Timestamp" | "Zoned" | "civil::DateTime" | "civil::Date" | "civil::Time" | "Span"
701            | "SignedDuration" => {
702                let val = self.parse_string()?;
703                ScalarValue::Str(Cow::Borrowed(val))
704            }
705            // Time crate types: RFC3339 strings
706            "UtcDateTime" | "OffsetDateTime" | "PrimitiveDateTime" | "Date" | "Time" => {
707                let val = self.parse_string()?;
708                ScalarValue::Str(Cow::Borrowed(val))
709            }
710            // Unknown opaque type - shouldn't happen (hint_opaque_scalar returned true)
711            _ => {
712                return Err(PostcardError {
713                    code: codes::UNSUPPORTED_OPAQUE_TYPE,
714                    pos: self.pos,
715                    message: format!("unsupported opaque type: {}", opaque.type_identifier),
716                    source_bytes: None,
717                });
718            }
719        };
720        Ok(ParseEvent::Scalar(scalar))
721    }
722
723    /// Read exactly N bytes from input without length prefix.
724    fn read_fixed_bytes(&mut self, len: usize) -> Result<&'de [u8], PostcardError> {
725        if self.pos + len > self.input.len() {
726            return Err(PostcardError {
727                code: codes::UNEXPECTED_END_OF_INPUT,
728                pos: self.pos,
729                message: format!(
730                    "expected {} bytes, only {} available",
731                    len,
732                    self.input.len() - self.pos
733                ),
734                source_bytes: None,
735            });
736        }
737        let bytes = &self.input[self.pos..self.pos + len];
738        self.pos += len;
739        Ok(bytes)
740    }
741
742    /// Parse a boolean value.
743    pub fn parse_bool(&mut self) -> Result<bool, PostcardError> {
744        let byte = self.read_byte()?;
745        match byte {
746            0 => Ok(false),
747            1 => Ok(true),
748            _ => Err(PostcardError {
749                code: codes::INVALID_BOOL,
750                pos: self.pos - 1,
751                message: "invalid boolean value".into(),
752                source_bytes: None,
753            }),
754        }
755    }
756
757    /// Parse an unsigned 8-bit integer.
758    pub fn parse_u8(&mut self) -> Result<u8, PostcardError> {
759        self.read_byte()
760    }
761
762    /// Parse an unsigned 16-bit integer (varint).
763    pub fn parse_u16(&mut self) -> Result<u16, PostcardError> {
764        let val = self.read_varint()?;
765        Ok(val as u16)
766    }
767
768    /// Parse an unsigned 32-bit integer (varint).
769    pub fn parse_u32(&mut self) -> Result<u32, PostcardError> {
770        let val = self.read_varint()?;
771        Ok(val as u32)
772    }
773
774    /// Parse an unsigned 64-bit integer (varint).
775    pub fn parse_u64(&mut self) -> Result<u64, PostcardError> {
776        self.read_varint()
777    }
778
779    /// Parse an unsigned 128-bit integer (varint).
780    pub fn parse_u128(&mut self) -> Result<u128, PostcardError> {
781        self.read_varint_u128()
782    }
783
784    /// Parse a signed 8-bit integer (single byte, two's complement).
785    pub fn parse_i8(&mut self) -> Result<i8, PostcardError> {
786        // i8 is encoded as a single byte in two's complement form (not varint)
787        let byte = self.read_byte()?;
788        Ok(byte as i8)
789    }
790
791    /// Parse a signed 16-bit integer (zigzag varint).
792    pub fn parse_i16(&mut self) -> Result<i16, PostcardError> {
793        let val = self.read_signed_varint()?;
794        Ok(val as i16)
795    }
796
797    /// Parse a signed 32-bit integer (zigzag varint).
798    pub fn parse_i32(&mut self) -> Result<i32, PostcardError> {
799        let val = self.read_signed_varint()?;
800        Ok(val as i32)
801    }
802
803    /// Parse a signed 64-bit integer (zigzag varint).
804    pub fn parse_i64(&mut self) -> Result<i64, PostcardError> {
805        self.read_signed_varint()
806    }
807
808    /// Parse a signed 128-bit integer (zigzag varint).
809    pub fn parse_i128(&mut self) -> Result<i128, PostcardError> {
810        self.read_signed_varint_i128()
811    }
812
813    /// Parse a 32-bit float (little-endian).
814    pub fn parse_f32(&mut self) -> Result<f32, PostcardError> {
815        let bytes = self.read_bytes(4)?;
816        Ok(f32::from_le_bytes(bytes.try_into().unwrap()))
817    }
818
819    /// Parse a 64-bit float (little-endian).
820    pub fn parse_f64(&mut self) -> Result<f64, PostcardError> {
821        let bytes = self.read_bytes(8)?;
822        Ok(f64::from_le_bytes(bytes.try_into().unwrap()))
823    }
824
825    /// Parse a string (varint length + UTF-8 bytes).
826    pub fn parse_string(&mut self) -> Result<&'de str, PostcardError> {
827        let len = self.read_varint()? as usize;
828        let bytes = self.read_bytes(len)?;
829        core::str::from_utf8(bytes).map_err(|_| PostcardError {
830            code: codes::INVALID_UTF8,
831            pos: self.pos - len,
832            message: "invalid UTF-8 in string".into(),
833            source_bytes: None,
834        })
835    }
836
837    /// Parse bytes (varint length + raw bytes).
838    pub fn parse_bytes(&mut self) -> Result<&'de [u8], PostcardError> {
839        let len = self.read_varint()? as usize;
840        self.read_bytes(len)
841    }
842
843    /// Begin parsing a sequence, returning the element count.
844    pub fn begin_sequence(&mut self) -> Result<u64, PostcardError> {
845        let count = self.read_varint()?;
846        self.state_stack.push(ParserState::InSequence {
847            remaining_elements: count,
848        });
849        Ok(count)
850    }
851
852    fn parse_dynamic_tag_event(&mut self) -> Result<ParseEvent<'de>, PostcardError> {
853        // If we're inside a dynamic object and expecting a value, advance entry tracking now.
854        if let Some(ParserState::InDynamicObject {
855            remaining_entries,
856            expecting_key,
857        }) = self.state_stack.last_mut()
858            && !*expecting_key
859        {
860            *remaining_entries = remaining_entries.saturating_sub(1);
861            *expecting_key = true;
862        }
863
864        if let Some(ParserState::InDynamicArray { remaining_elements }) =
865            self.state_stack.last_mut()
866        {
867            *remaining_elements = remaining_elements.saturating_sub(1);
868        }
869
870        let tag = self.read_byte()?;
871        match tag {
872            0 => Ok(ParseEvent::Scalar(ScalarValue::Null)),
873            1 => self.parse_scalar_with_hint(ScalarTypeHint::Bool),
874            2 => self.parse_scalar_with_hint(ScalarTypeHint::I64),
875            3 => self.parse_scalar_with_hint(ScalarTypeHint::U64),
876            4 => self.parse_scalar_with_hint(ScalarTypeHint::F64),
877            5 => self.parse_scalar_with_hint(ScalarTypeHint::String),
878            6 => self.parse_scalar_with_hint(ScalarTypeHint::Bytes),
879            7 => {
880                let count = self.read_varint()?;
881                self.state_stack.push(ParserState::InDynamicArray {
882                    remaining_elements: count,
883                });
884                Ok(ParseEvent::SequenceStart(ContainerKind::Array))
885            }
886            8 => {
887                let count = self.read_varint()?;
888                self.state_stack.push(ParserState::InDynamicObject {
889                    remaining_entries: count,
890                    expecting_key: true,
891                });
892                Ok(ParseEvent::StructStart(ContainerKind::Object))
893            }
894            9 => self.parse_scalar_with_hint(ScalarTypeHint::String),
895            _ => Err(PostcardError {
896                code: codes::UNSUPPORTED,
897                pos: self.pos.saturating_sub(1),
898                message: format!("invalid dynamic value tag: {}", tag),
899                source_bytes: None,
900            }),
901        }
902    }
903}
904
905/// Stub probe stream for PostcardParser.
906///
907/// Not used since postcard doesn't support probing (non-self-describing).
908pub struct PostcardProbe;
909
910impl<'de> ProbeStream<'de> for PostcardProbe {
911    type Error = PostcardError;
912
913    fn next(&mut self) -> Result<Option<FieldEvidence<'de>>, Self::Error> {
914        // Postcard doesn't support probing
915        Ok(None)
916    }
917}
918
919impl<'de> FormatParser<'de> for PostcardParser<'de> {
920    type Error = PostcardError;
921    type Probe<'a>
922        = PostcardProbe
923    where
924        Self: 'a;
925
926    fn next_event(&mut self) -> Result<Option<ParseEvent<'de>>, Self::Error> {
927        // Return peeked event if available
928        if let Some(event) = self.peeked.take() {
929            return Ok(Some(event));
930        }
931        Ok(Some(self.generate_next_event()?))
932    }
933
934    fn peek_event(&mut self) -> Result<Option<ParseEvent<'de>>, Self::Error> {
935        if self.peeked.is_none() {
936            self.peeked = Some(self.generate_next_event()?);
937        }
938        Ok(self.peeked.clone())
939    }
940
941    fn skip_value(&mut self) -> Result<(), Self::Error> {
942        // For non-self-describing formats, skipping is complex because
943        // we don't know the type/size of the value.
944        Err(PostcardError {
945            code: codes::UNSUPPORTED,
946            pos: self.pos,
947            message: "skip_value not supported for postcard (non-self-describing)".into(),
948            source_bytes: None,
949        })
950    }
951
952    fn begin_probe(&mut self) -> Result<Self::Probe<'_>, Self::Error> {
953        // Postcard doesn't support probing
954        Ok(PostcardProbe)
955    }
956
957    fn is_self_describing(&self) -> bool {
958        false
959    }
960
961    fn hint_struct_fields(&mut self, num_fields: usize) {
962        self.pending_struct_fields = Some(num_fields);
963        // Clear any peeked OrderedField placeholder for sequences
964        if matches!(self.peeked, Some(ParseEvent::OrderedField)) {
965            self.peeked = None;
966        }
967    }
968
969    fn hint_scalar_type(&mut self, hint: ScalarTypeHint) {
970        self.pending_scalar_type = Some(hint);
971        // Clear any peeked OrderedField placeholder for sequences
972        if matches!(self.peeked, Some(ParseEvent::OrderedField)) {
973            self.peeked = None;
974        }
975    }
976
977    fn hint_sequence(&mut self) {
978        self.pending_sequence = true;
979        // Clear any peeked OrderedField placeholder
980        if matches!(self.peeked, Some(ParseEvent::OrderedField)) {
981            self.peeked = None;
982        }
983    }
984
985    fn hint_byte_sequence(&mut self) -> bool {
986        self.pending_byte_sequence = true;
987        // Clear any peeked OrderedField placeholder
988        if matches!(self.peeked, Some(ParseEvent::OrderedField)) {
989            self.peeked = None;
990        }
991        true // Postcard supports bulk byte reading
992    }
993
994    fn hint_array(&mut self, len: usize) {
995        self.pending_array = Some(len);
996        // Clear any peeked OrderedField placeholder
997        if matches!(self.peeked, Some(ParseEvent::OrderedField)) {
998            self.peeked = None;
999        }
1000    }
1001
1002    fn hint_option(&mut self) {
1003        self.pending_option = true;
1004        // Clear any peeked OrderedField placeholder
1005        if matches!(self.peeked, Some(ParseEvent::OrderedField)) {
1006            self.peeked = None;
1007        }
1008    }
1009
1010    fn hint_enum(&mut self, variants: &[EnumVariantHint]) {
1011        // Store variant metadata, converting to owned strings to avoid lifetime issues.
1012        let metas: Vec<VariantMeta> = variants
1013            .iter()
1014            .map(|v| VariantMeta {
1015                name: v.name.to_string(),
1016                kind: v.kind,
1017                field_count: v.field_count,
1018            })
1019            .collect();
1020        self.pending_enum = Some(metas);
1021        // Clear any peeked OrderedField placeholder for sequences
1022        if matches!(self.peeked, Some(ParseEvent::OrderedField)) {
1023            self.peeked = None;
1024        }
1025    }
1026
1027    fn hint_map(&mut self) {
1028        self.pending_map = true;
1029        // Clear any peeked OrderedField placeholder
1030        if matches!(self.peeked, Some(ParseEvent::OrderedField)) {
1031            self.peeked = None;
1032        }
1033    }
1034
1035    fn hint_dynamic_value(&mut self) {
1036        // Clear any peeked OrderedField placeholder (it's just a "not done yet" signal)
1037        if matches!(self.peeked, Some(ParseEvent::OrderedField)) {
1038            self.peeked = None;
1039        }
1040        // If something else is peeked, don't override it
1041        if self.peeked.is_some() {
1042            return;
1043        }
1044        self.pending_dynamic = true;
1045    }
1046
1047    fn hint_opaque_scalar(
1048        &mut self,
1049        type_identifier: &'static str,
1050        shape: &'static facet_core::Shape,
1051    ) -> bool {
1052        // Check if we handle this type specially in postcard
1053        let handled = matches!(
1054            type_identifier,
1055            // UUID/ULID: 16 raw bytes
1056            "Uuid" | "Ulid"
1057            // OrderedFloat/NotNan: raw float bytes (size determined by inner type)
1058            | "OrderedFloat" | "NotNan"
1059            // Camino paths: strings
1060            | "Utf8PathBuf" | "Utf8Path"
1061            // Chrono types: RFC3339 strings
1062            | "DateTime<Utc>" | "DateTime<Local>" | "DateTime<FixedOffset>"
1063            | "NaiveDateTime" | "NaiveDate" | "NaiveTime"
1064            // Jiff types: RFC3339/ISO8601 strings
1065            | "Timestamp" | "Zoned" | "civil::DateTime" | "civil::Date" | "civil::Time"
1066            | "Span" | "SignedDuration"
1067            // Time crate types: RFC3339 strings
1068            | "UtcDateTime" | "OffsetDateTime" | "PrimitiveDateTime" | "Date" | "Time"
1069        );
1070
1071        if handled {
1072            // Check inner shape for OrderedFloat/NotNan to determine f32 vs f64
1073            let inner_is_f32 = shape
1074                .inner
1075                .map(|inner| inner.is_type::<f32>())
1076                .unwrap_or(false);
1077
1078            self.pending_opaque = Some(OpaqueScalarHint {
1079                type_identifier,
1080                inner_is_f32,
1081            });
1082            // Clear any peeked OrderedField placeholder
1083            if matches!(self.peeked, Some(ParseEvent::OrderedField)) {
1084                self.peeked = None;
1085            }
1086        }
1087        handled
1088    }
1089}
1090
1091#[cfg(feature = "jit")]
1092impl<'de> facet_format::FormatJitParser<'de> for PostcardParser<'de> {
1093    type FormatJit = crate::jit::PostcardJitFormat;
1094
1095    fn jit_input(&self) -> &'de [u8] {
1096        self.input
1097    }
1098
1099    fn jit_pos(&self) -> Option<usize> {
1100        // Only return position if no peeked event (clean state)
1101        if self.peeked.is_some() {
1102            None
1103        } else {
1104            Some(self.pos)
1105        }
1106    }
1107
1108    fn jit_set_pos(&mut self, pos: usize) {
1109        self.pos = pos;
1110        self.peeked = None;
1111        // Clear state when JIT takes over
1112        self.state_stack.clear();
1113        self.pending_struct_fields = None;
1114        self.pending_scalar_type = None;
1115        self.pending_sequence = false;
1116        self.pending_array = None;
1117        self.pending_dynamic = false;
1118    }
1119
1120    fn jit_format(&self) -> Self::FormatJit {
1121        crate::jit::PostcardJitFormat
1122    }
1123
1124    fn jit_error(&self, _input: &'de [u8], error_pos: usize, error_code: i32) -> Self::Error {
1125        PostcardError::from_code(error_code, error_pos)
1126    }
1127}