1use alloc::string::String;
11use alloc::vec::Vec;
12use core::convert::Infallible;
13use core::fmt;
14use core::ops::{Index, IndexMut};
15use core::ptr::eq as ptr_eq;
16
17use smol_str::SmolStr;
18
19use crate::IdentDisplay;
20use crate::writer::Writer;
21
22pub mod iter;
23pub mod number;
24
25fn option_debug<T: fmt::Debug>(value: Option<&T>) -> &dyn fmt::Debug {
27 match value {
28 Some(value) => value,
29 None => &None::<Infallible>,
30 }
31}
32
33#[derive(Default, Clone, PartialEq, Eq, Hash)]
35pub struct Document {
36 pub nodes: Vec<Node>,
38}
39
40impl Document {
41 pub const fn new() -> Self { Self { nodes: Vec::new() } }
43 pub fn get(&self, name: &str) -> impl Iterator<Item = &Node> {
45 self.nodes.iter().filter(move |node| node.name() == name)
46 }
47 pub fn get_mut(&mut self, name: &str) -> impl Iterator<Item = &mut Node> {
49 self.nodes
50 .iter_mut()
51 .filter(move |node| node.name() == name)
52 }
53 pub fn iter(&self) -> iter::Iter<'_> { self.into_iter() }
55 #[cfg(feature = "std")]
59 pub fn normalize(&mut self) {
60 for node in &mut self.nodes {
61 node.normalize();
62 }
63 }
64}
65
66impl fmt::Debug for Document {
67 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68 f.write_str("Document ")?;
69 f.debug_list().entries(&self.nodes).finish()
70 }
71}
72impl fmt::Display for Document {
73 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
74 let mut writer = Writer::new(f);
75 for event in self {
76 writer.push(&event)?;
77 }
78 Ok(())
79 }
80}
81
82impl From<Vec<Node>> for Document {
83 fn from(nodes: Vec<Node>) -> Self { Self { nodes } }
84}
85impl From<Document> for Vec<Node> {
86 fn from(value: Document) -> Self { value.nodes }
87}
88
89#[derive(Clone, PartialEq, Eq, Hash)]
91pub struct Node {
92 pub r#type: Option<SmolStr>,
94 pub name: SmolStr,
96 pub entries: Vec<Entry>,
100 pub children: Option<Document>,
102}
103
104impl Default for Node {
106 fn default() -> Self {
107 Self {
108 r#type: None,
109 name: SmolStr::new_inline("-"),
110 entries: Vec::new(),
111 children: None,
112 }
113 }
114}
115
116impl Node {
117 pub fn new<I: Into<SmolStr>>(name: I) -> Self {
119 Self {
120 r#type: None,
121 name: name.into(),
122 entries: Vec::new(),
123 children: None,
124 }
125 }
126 pub fn name(&self) -> &str { &self.name }
128 pub fn set_name<T: Into<SmolStr>>(&mut self, name: T) { self.name = name.into(); }
130 pub fn type_hint(&self) -> Option<&str> { self.r#type.as_deref() }
132 pub fn set_type_hint<T: Into<SmolStr>>(&mut self, r#type: Option<T>) {
134 self.r#type = r#type.map(Into::into);
135 }
136 pub fn entry<'key, T: Into<EntryKey<'key>>>(&self, key: T) -> Option<&Entry> {
138 key.into()
139 .seek(self.entries.iter(), |ent| ent.name.as_deref())
140 }
141 pub fn entry_mut<'key, T: Into<EntryKey<'key>>>(&mut self, key: T) -> Option<&mut Entry> {
143 key.into()
144 .seek(self.entries.iter_mut(), |ent| ent.name.as_deref())
145 }
146 pub fn iter(&self) -> iter::Iter<'_> { self.into_iter() }
148 #[cfg(feature = "std")]
153 pub fn normalize(&mut self) {
154 use std::collections::HashSet;
155 if let Some(children) = &mut self.children {
156 if children.nodes.is_empty() {
157 self.children = None;
158 } else {
159 children.normalize();
160 }
161 }
162 let marker = SmolStr::new_static(&"\0temp"[5..]);
166 let mut seen = HashSet::new();
168 for entry in self.entries.iter_mut().rev() {
169 if let Some(name) = &mut entry.name {
170 if seen.contains(&**name) {
171 *name = marker.clone();
172 } else {
173 seen.insert(&**name);
174 }
175 }
176 }
177 drop(seen);
178 self.entries.retain(|ent| {
180 !ent.name
181 .as_ref()
182 .is_some_and(|name| ptr_eq(name.as_ptr(), marker.as_ptr()) && name.is_empty())
183 });
184 }
185}
186
187impl fmt::Debug for Node {
188 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
189 f.debug_struct("Node")
190 .field("type", option_debug(self.type_hint().as_ref()))
191 .field("name", &self.name)
192 .field("entries", &self.entries)
193 .field("children", option_debug(self.children.as_ref()))
194 .finish()
195 }
196}
197impl fmt::Display for Node {
198 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
199 let mut writer = Writer::new(f);
200 for event in self {
201 writer.push(&event)?;
202 }
203 Ok(())
204 }
205}
206impl<'key, T: Into<EntryKey<'key>>> Index<T> for Node {
207 type Output = Entry;
208 fn index(&self, index: T) -> &Self::Output {
209 let key = index.into();
210 self.entry(key)
211 .unwrap_or_else(|| panic!("Key {key:?} does not exist in node"))
212 }
213}
214impl<'key, T: Into<EntryKey<'key>>> IndexMut<T> for Node {
215 fn index_mut(&mut self, index: T) -> &mut Self::Output {
216 let key = index.into();
217 self.entry_mut(key)
218 .unwrap_or_else(|| panic!("Key {key:?} does not exist in node"))
219 }
220}
221
222#[derive(Clone, PartialEq, Eq, Hash)]
224pub struct Entry {
225 pub name: Option<SmolStr>,
227 pub r#type: Option<SmolStr>,
229 pub value: Value,
231}
232
233impl Entry {
234 pub fn new_value(value: Value) -> Self {
236 Self {
237 name: None,
238 r#type: None,
239 value,
240 }
241 }
242 pub fn new_prop<T: Into<SmolStr>>(name: T, value: Value) -> Self {
244 Self {
245 name: Some(name.into()),
246 r#type: None,
247 value,
248 }
249 }
250 pub fn name(&self) -> Option<&str> { self.name.as_deref() }
252 pub fn set_name<T: Into<SmolStr>>(&mut self, name: Option<T>) {
254 self.name = name.map(Into::into);
255 }
256 pub fn type_hint(&self) -> Option<&str> { self.r#type.as_deref() }
258 pub fn set_type_hint<T: Into<SmolStr>>(&mut self, r#type: Option<T>) {
260 self.r#type = r#type.map(Into::into);
261 }
262}
263
264impl fmt::Debug for Entry {
265 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
266 f.debug_struct("Entry")
267 .field("name", &self.name)
268 .field("type", option_debug(self.type_hint().as_ref()))
269 .field("value", &self.value)
270 .finish()
271 }
272}
273impl fmt::Display for Entry {
274 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
275 if let Some(name) = &self.name {
276 write!(f, "{}=", IdentDisplay(name))?;
277 }
278 if let Some(r#type) = &self.r#type {
279 write!(f, "({})", IdentDisplay(r#type))?;
280 }
281 fmt::Display::fmt(&self.value, f)
282 }
283}
284impl<K: Into<SmolStr>, V: Into<Value>> From<(K, V)> for Entry {
285 fn from((name, value): (K, V)) -> Self { Self::new_prop(name.into(), value.into()) }
286}
287impl<V: Into<Value>> From<V> for Entry {
288 fn from(value: V) -> Self { Self::new_value(value.into()) }
289}
290
291#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
293pub enum EntryKey<'key> {
294 Value(usize),
296 Property(&'key str),
298}
299impl EntryKey<'_> {
300 fn seek<T>(
301 self,
302 mut iter: impl DoubleEndedIterator<Item = T>,
303 name: impl Fn(&T) -> Option<&str>,
304 ) -> Option<T> {
305 match self {
306 EntryKey::Value(key) => iter.filter(|ent| name(ent).is_none()).nth(key),
307 EntryKey::Property(key) => iter.rfind(|ent| name(ent) == Some(key)),
309 }
310 }
311}
312impl From<usize> for EntryKey<'_> {
313 fn from(value: usize) -> Self { Self::Value(value) }
314}
315impl<'key> From<&'key str> for EntryKey<'key> {
316 fn from(value: &'key str) -> Self { Self::Property(value) }
317}
318
319#[derive(Default, Clone, PartialEq, Eq, Hash)]
321pub enum Value {
322 String(SmolStr),
324 Number(Number),
326 Bool(bool),
328 #[default]
330 Null,
331}
332
333macro_rules! valutil {
335 (into $self:ident $ty:ident) => {
336 match $self {
337 Value::$ty(value) => Ok(value),
338 this => Err(this),
339 }
340 };
341 (to $self:ident $ty:ident) => {
342 match $self {
343 Value::$ty(value) => Some(value),
344 _ => None,
345 }
346 };
347}
348
349impl Value {
350 #[expect(clippy::missing_errors_doc, reason = "not an error")]
352 pub fn into_string(self) -> Result<SmolStr, Self> { valutil!(into self String) }
353 #[expect(clippy::missing_errors_doc, reason = "not an error")]
355 pub fn into_number(self) -> Result<Number, Self> { valutil!(into self Number) }
356 pub fn to_string(&self) -> Option<&SmolStr> { valutil!(to self String) }
358 pub fn to_number(&self) -> Option<&Number> { valutil!(to self Number) }
360 pub fn to_bool(&self) -> Option<bool> { valutil!(to self Bool).copied() }
362 pub fn is_string(&self) -> bool { matches!(self, Self::String(_)) }
364 pub fn is_number(&self) -> bool { matches!(self, Self::Number(_)) }
366 pub fn is_bool(&self) -> bool { matches!(self, Self::Bool(_)) }
368 pub fn is_null(&self) -> bool { matches!(self, Self::Null) }
370}
371
372impl fmt::Debug for Value {
373 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
374 match self {
375 Self::String(value) => fmt::Debug::fmt(&**value, f),
376 Self::Number(value) => fmt::Debug::fmt(value, f),
377 Self::Bool(true) => f.write_str("#true"),
378 Self::Bool(false) => f.write_str("#false"),
379 Self::Null => f.write_str("#null"),
380 }
381 }
382}
383impl fmt::Display for Value {
384 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
385 match self {
386 Self::String(value) => fmt::Display::fmt(&IdentDisplay(value), f),
387 Self::Number(value) => fmt::Display::fmt(value, f),
388 Self::Bool(true) => f.write_str("#true"),
389 Self::Bool(false) => f.write_str("#false"),
390 Self::Null => f.write_str("#null"),
391 }
392 }
393}
394impl<'text> From<&'text str> for Value {
395 fn from(value: &'text str) -> Self { Self::String(value.into()) }
396}
397impl From<SmolStr> for Value {
398 fn from(value: SmolStr) -> Self { Self::String(value) }
399}
400impl From<String> for Value {
401 fn from(value: String) -> Self { Self::String(value.into()) }
402}
403impl<T: Into<Number>> From<T> for Value {
404 fn from(value: T) -> Self { Self::Number(value.into()) }
405}
406impl From<bool> for Value {
407 fn from(value: bool) -> Self { Self::Bool(value) }
408}
409impl From<()> for Value {
410 fn from((): ()) -> Self { Self::Null }
411}
412impl<T: Into<Value>> From<Option<T>> for Value {
413 fn from(value: Option<T>) -> Self {
414 match value {
415 Some(v) => v.into(),
416 _ => Self::Null,
417 }
418 }
419}
420
421#[derive(Clone, Debug, PartialEq, Eq, Hash)]
425pub struct Number(SmolStr);
426
427#[derive(Clone, PartialEq, Eq, Hash)]
429pub enum Event {
430 Node {
432 r#type: Option<SmolStr>,
434 name: SmolStr,
436 },
437 Entry(Entry),
439 Children,
441 End,
443}
444
445impl fmt::Debug for Event {
446 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
447 match self {
448 Self::Node { r#type, name } => f
449 .debug_struct("Node")
450 .field("type", option_debug(r#type.as_ref()))
451 .field("name", name)
452 .finish(),
453 Self::Entry(entry) => fmt::Debug::fmt(entry, f),
454 Self::Children => f.write_str("Children"),
455 Self::End => f.write_str("End"),
456 }
457 }
458}