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}