facet_format/
event.rs

1extern crate alloc;
2
3use alloc::borrow::Cow;
4use core::fmt;
5
6/// Location hint for a serialized field.
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum FieldLocationHint {
9    /// Key/value entry (JSON/YAML/TOML).
10    KeyValue,
11    /// XML attribute.
12    Attribute,
13    /// XML/KDL text node.
14    Text,
15    /// XML/KDL child element/node.
16    Child,
17    /// KDL property.
18    Property,
19    /// KDL positional argument.
20    Argument,
21}
22
23/// Field key with optional namespace (for XML).
24#[derive(Debug, Clone, PartialEq, Eq)]
25pub struct FieldKey<'de> {
26    /// Field name.
27    pub name: Cow<'de, str>,
28    /// Location hint.
29    pub location: FieldLocationHint,
30    /// Optional namespace URI (for XML namespace support).
31    pub namespace: Option<Cow<'de, str>>,
32}
33
34impl<'de> FieldKey<'de> {
35    /// Create a new field key without namespace.
36    pub fn new(name: impl Into<Cow<'de, str>>, location: FieldLocationHint) -> Self {
37        Self {
38            name: name.into(),
39            location,
40            namespace: None,
41        }
42    }
43
44    /// Add a namespace to this field key (builder pattern).
45    pub fn with_namespace(mut self, namespace: impl Into<Cow<'de, str>>) -> Self {
46        self.namespace = Some(namespace.into());
47        self
48    }
49}
50
51/// The kind of container being parsed.
52///
53/// This distinguishes between format-specific container types to enable
54/// better error messages and type checking.
55#[derive(Debug, Clone, Copy, PartialEq, Eq)]
56pub enum ContainerKind {
57    /// JSON/YAML/TOML object: definitely struct-like with key-value pairs.
58    /// Type mismatches (e.g., object where array expected) should produce errors.
59    Object,
60    /// JSON/YAML array: definitely sequence-like.
61    /// Type mismatches (e.g., array where object expected) should produce errors.
62    Array,
63    /// XML/KDL element: semantically ambiguous.
64    /// Could be interpreted as struct, sequence, or scalar wrapper depending on target type.
65    /// The deserializer decides based on what type it's deserializing into.
66    Element,
67}
68
69impl ContainerKind {
70    /// Returns true if this container kind is ambiguous (can be struct or sequence).
71    pub fn is_ambiguous(self) -> bool {
72        matches!(self, ContainerKind::Element)
73    }
74
75    /// Human-readable name for error messages.
76    pub fn name(self) -> &'static str {
77        match self {
78            ContainerKind::Object => "object",
79            ContainerKind::Array => "array",
80            ContainerKind::Element => "element",
81        }
82    }
83}
84
85/// Value classification hint for evidence gathering.
86#[derive(Debug, Clone, Copy, PartialEq, Eq)]
87pub enum ValueTypeHint {
88    /// Null-like values.
89    Null,
90    /// Boolean.
91    Bool,
92    /// Numeric primitive.
93    Number,
94    /// Text string.
95    String,
96    /// Raw bytes (e.g., base64 segments).
97    Bytes,
98    /// Sequence (array/list/tuple).
99    Sequence,
100    /// Map/struct/object.
101    Map,
102}
103
104/// Scalar data extracted from the wire format.
105#[derive(Debug, Clone, PartialEq)]
106pub enum ScalarValue<'de> {
107    /// Null literal.
108    Null,
109    /// Boolean literal.
110    Bool(bool),
111    /// Signed integer literal (fits in i64).
112    I64(i64),
113    /// Unsigned integer literal (fits in u64).
114    U64(u64),
115    /// Signed 128-bit integer literal.
116    I128(i128),
117    /// Unsigned 128-bit integer literal.
118    U128(u128),
119    /// Floating-point literal.
120    F64(f64),
121    /// UTF-8 string literal.
122    Str(Cow<'de, str>),
123    /// Binary literal.
124    Bytes(Cow<'de, [u8]>),
125}
126
127/// Event emitted by a format parser while streaming through input.
128#[derive(Clone, PartialEq)]
129pub enum ParseEvent<'de> {
130    /// Beginning of a struct/object/node.
131    StructStart(ContainerKind),
132    /// End of a struct/object/node.
133    StructEnd,
134    /// Encountered a field key (for self-describing formats like JSON/YAML).
135    FieldKey(FieldKey<'de>),
136    /// Next field value in struct field order (for non-self-describing formats like postcard).
137    ///
138    /// The driver tracks the current field index and uses the schema to determine
139    /// which field this value belongs to. This allows formats without field names
140    /// in the wire format to still support Tier-0 deserialization.
141    OrderedField,
142    /// Beginning of a sequence/array/tuple.
143    SequenceStart(ContainerKind),
144    /// End of a sequence/array/tuple.
145    SequenceEnd,
146    /// Scalar literal.
147    Scalar(ScalarValue<'de>),
148    /// Variant discriminant that needs to be propagated to the solver.
149    VariantTag(&'de str),
150}
151
152impl<'de> fmt::Debug for ParseEvent<'de> {
153    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154        match self {
155            ParseEvent::StructStart(kind) => f.debug_tuple("StructStart").field(kind).finish(),
156            ParseEvent::StructEnd => f.write_str("StructEnd"),
157            ParseEvent::FieldKey(key) => f.debug_tuple("FieldKey").field(key).finish(),
158            ParseEvent::OrderedField => f.write_str("OrderedField"),
159            ParseEvent::SequenceStart(kind) => f.debug_tuple("SequenceStart").field(kind).finish(),
160            ParseEvent::SequenceEnd => f.write_str("SequenceEnd"),
161            ParseEvent::Scalar(value) => f.debug_tuple("Scalar").field(value).finish(),
162            ParseEvent::VariantTag(tag) => f.debug_tuple("VariantTag").field(tag).finish(),
163        }
164    }
165}