1extern crate alloc;
2
3use alloc::borrow::Cow;
4use alloc::boxed::Box;
5use alloc::vec::Vec;
6use core::fmt;
7use facet_reflect::Span;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
11#[non_exhaustive]
12pub enum FieldLocationHint {
13 #[default]
15 KeyValue,
16}
17
18#[derive(Debug, Clone, PartialEq, Eq)]
26#[non_exhaustive]
27pub enum FieldKey<'de> {
28 Name(Cow<'de, str>),
30 Full(Box<FullFieldKey<'de>>),
32}
33
34#[derive(Debug, Clone, PartialEq, Eq)]
38pub struct FullFieldKey<'de> {
39 pub name: Option<Cow<'de, str>>,
45 pub location: FieldLocationHint,
47 pub meta: ValueMeta<'de>,
49}
50
51impl<'de> FieldKey<'de> {
52 #[inline]
54 pub fn new(name: impl Into<Cow<'de, str>>, _location: FieldLocationHint) -> Self {
55 FieldKey::Name(name.into())
56 }
57
58 pub fn with_doc(
60 name: impl Into<Cow<'de, str>>,
61 location: FieldLocationHint,
62 doc: Vec<Cow<'de, str>>,
63 ) -> Self {
64 if doc.is_empty() {
65 FieldKey::Name(name.into())
66 } else {
67 FieldKey::Full(Box::new(FullFieldKey {
68 name: Some(name.into()),
69 location,
70 meta: ValueMeta::builder().doc(doc).build(),
71 }))
72 }
73 }
74
75 pub fn tagged(tag: impl Into<Cow<'de, str>>, location: FieldLocationHint) -> Self {
79 FieldKey::Full(Box::new(FullFieldKey {
80 name: None,
81 location,
82 meta: ValueMeta::builder().tag(tag.into()).build(),
83 }))
84 }
85
86 pub fn tagged_with_doc(
88 tag: impl Into<Cow<'de, str>>,
89 location: FieldLocationHint,
90 doc: Vec<Cow<'de, str>>,
91 ) -> Self {
92 FieldKey::Full(Box::new(FullFieldKey {
93 name: None,
94 location,
95 meta: ValueMeta::builder()
96 .tag(tag.into())
97 .maybe_doc(Some(doc))
98 .build(),
99 }))
100 }
101
102 pub fn tagged_with_name(
106 tag: impl Into<Cow<'de, str>>,
107 name: impl Into<Cow<'de, str>>,
108 location: FieldLocationHint,
109 ) -> Self {
110 FieldKey::Full(Box::new(FullFieldKey {
111 name: Some(name.into()),
112 location,
113 meta: ValueMeta::builder().tag(tag.into()).build(),
114 }))
115 }
116
117 pub fn tagged_with_name_and_doc(
119 tag: impl Into<Cow<'de, str>>,
120 name: impl Into<Cow<'de, str>>,
121 location: FieldLocationHint,
122 doc: Vec<Cow<'de, str>>,
123 ) -> Self {
124 FieldKey::Full(Box::new(FullFieldKey {
125 name: Some(name.into()),
126 location,
127 meta: ValueMeta::builder()
128 .tag(tag.into())
129 .maybe_doc(Some(doc))
130 .build(),
131 }))
132 }
133
134 pub fn unit(location: FieldLocationHint) -> Self {
139 FieldKey::Full(Box::new(FullFieldKey {
140 name: None,
141 location,
142 meta: ValueMeta::builder().tag(Cow::Borrowed("")).build(),
143 }))
144 }
145
146 pub fn unit_with_doc(location: FieldLocationHint, doc: Vec<Cow<'de, str>>) -> Self {
148 FieldKey::Full(Box::new(FullFieldKey {
149 name: None,
150 location,
151 meta: ValueMeta::builder()
152 .tag(Cow::Borrowed(""))
153 .maybe_doc(Some(doc))
154 .build(),
155 }))
156 }
157
158 #[inline]
160 pub fn name(&self) -> Option<&Cow<'de, str>> {
161 match self {
162 FieldKey::Name(name) => Some(name),
163 FieldKey::Full(full) => full.name.as_ref(),
164 }
165 }
166
167 #[inline]
169 pub fn doc(&self) -> Option<&[Cow<'de, str>]> {
170 match self {
171 FieldKey::Name(_) => None,
172 FieldKey::Full(full) => full.meta.doc(),
173 }
174 }
175
176 #[inline]
178 pub fn tag(&self) -> Option<&Cow<'de, str>> {
179 match self {
180 FieldKey::Name(_) => None,
181 FieldKey::Full(full) => full.meta.tag(),
182 }
183 }
184
185 #[inline]
187 pub fn meta(&self) -> Option<&ValueMeta<'de>> {
188 match self {
189 FieldKey::Name(_) => None,
190 FieldKey::Full(full) => Some(&full.meta),
191 }
192 }
193
194 #[inline]
196 pub fn location(&self) -> FieldLocationHint {
197 match self {
198 FieldKey::Name(_) => FieldLocationHint::KeyValue,
199 FieldKey::Full(full) => full.location,
200 }
201 }
202}
203
204#[derive(Debug, Clone, Copy, PartialEq, Eq)]
209#[non_exhaustive]
210pub enum ContainerKind {
211 Object,
214 Array,
217}
218
219impl ContainerKind {
220 pub const fn name(self) -> &'static str {
222 match self {
223 ContainerKind::Object => "object",
224 ContainerKind::Array => "array",
225 }
226 }
227}
228
229#[derive(Debug, Clone, Copy, PartialEq, Eq)]
231#[non_exhaustive]
232pub enum ValueTypeHint {
233 Null,
235 Bool,
237 Number,
239 String,
241 Bytes,
243 Sequence,
245 Map,
247}
248
249#[derive(Debug, Clone, PartialEq)]
251#[non_exhaustive]
252pub enum ScalarValue<'de> {
253 Unit,
255 Null,
257 Bool(bool),
259 Char(char),
261 I64(i64),
263 U64(u64),
265 I128(i128),
267 U128(u128),
269 F64(f64),
271 Str(Cow<'de, str>),
273 Bytes(Cow<'de, [u8]>),
275}
276
277impl<'de> ScalarValue<'de> {
278 pub fn to_string_value(&self) -> Option<alloc::string::String> {
283 match self {
284 ScalarValue::Str(s) => Some(s.to_string()),
285 ScalarValue::Bool(b) => Some(b.to_string()),
286 ScalarValue::I64(i) => Some(i.to_string()),
287 ScalarValue::U64(u) => Some(u.to_string()),
288 ScalarValue::I128(i) => Some(i.to_string()),
289 ScalarValue::U128(u) => Some(u.to_string()),
290 ScalarValue::F64(f) => Some(f.to_string()),
291 ScalarValue::Char(c) => Some(c.to_string()),
292 ScalarValue::Null => Some("null".to_string()),
293 ScalarValue::Unit => Some(alloc::string::String::new()),
294 ScalarValue::Bytes(_) => None,
295 }
296 }
297
298 pub fn to_display_string(&self) -> alloc::string::String {
302 match self {
303 ScalarValue::Str(s) => s.to_string(),
304 ScalarValue::Bool(b) => alloc::format!("bool({})", b),
305 ScalarValue::I64(i) => alloc::format!("i64({})", i),
306 ScalarValue::U64(u) => alloc::format!("u64({})", u),
307 ScalarValue::I128(i) => alloc::format!("i128({})", i),
308 ScalarValue::U128(u) => alloc::format!("u128({})", u),
309 ScalarValue::F64(f) => alloc::format!("f64({})", f),
310 ScalarValue::Char(c) => alloc::format!("char({})", c),
311 ScalarValue::Bytes(_) => "bytes".to_string(),
312 ScalarValue::Null => "null".to_string(),
313 ScalarValue::Unit => "unit".to_string(),
314 }
315 }
316
317 #[inline]
319 pub const fn kind_name(&self) -> &'static str {
320 match self {
321 ScalarValue::Unit => "unit",
322 ScalarValue::Null => "null",
323 ScalarValue::Bool(_) => "bool",
324 ScalarValue::Char(_) => "char",
325 ScalarValue::I64(_) => "i64",
326 ScalarValue::U64(_) => "u64",
327 ScalarValue::I128(_) => "i128",
328 ScalarValue::U128(_) => "u128",
329 ScalarValue::F64(_) => "f64",
330 ScalarValue::Str(_) => "string",
331 ScalarValue::Bytes(_) => "bytes",
332 }
333 }
334}
335
336#[derive(Debug, Clone, Default, PartialEq, Eq)]
343#[non_exhaustive]
344pub struct ValueMeta<'a> {
345 doc: Option<Vec<Cow<'a, str>>>,
346 tag: Option<Cow<'a, str>>,
347 span: Option<Span>,
348}
349
350impl<'a> ValueMeta<'a> {
351 pub const fn empty() -> Self {
353 Self {
354 doc: None,
355 tag: None,
356 span: None,
357 }
358 }
359
360 #[inline]
362 pub fn builder() -> ValueMetaBuilder<'a> {
363 ValueMetaBuilder::default()
364 }
365
366 #[inline]
368 pub fn doc(&self) -> Option<&[Cow<'a, str>]> {
369 self.doc.as_deref()
370 }
371
372 #[inline]
374 pub fn tag(&self) -> Option<&Cow<'a, str>> {
375 self.tag.as_ref()
376 }
377
378 #[inline]
380 pub fn span(&self) -> Option<Span> {
381 self.span
382 }
383
384 #[inline]
386 pub fn is_empty(&self) -> bool {
387 self.doc.is_none() && self.tag.is_none() && self.span.is_none()
388 }
389}
390
391#[derive(Debug, Clone, Default)]
393pub struct ValueMetaBuilder<'a> {
394 doc: Option<Vec<Cow<'a, str>>>,
395 tag: Option<Cow<'a, str>>,
396 span: Option<Span>,
397}
398
399impl<'a> ValueMetaBuilder<'a> {
400 #[inline]
402 pub fn doc(mut self, doc: Vec<Cow<'a, str>>) -> Self {
403 if !doc.is_empty() {
404 self.doc = Some(doc);
405 }
406 self
407 }
408
409 #[inline]
411 pub fn maybe_doc(mut self, doc: Option<Vec<Cow<'a, str>>>) -> Self {
412 if let Some(d) = doc
413 && !d.is_empty()
414 {
415 self.doc = Some(d);
416 }
417 self
418 }
419
420 #[inline]
422 pub fn tag(mut self, tag: Cow<'a, str>) -> Self {
423 self.tag = Some(tag);
424 self
425 }
426
427 #[inline]
429 pub fn maybe_tag(mut self, tag: Option<Cow<'a, str>>) -> Self {
430 if tag.is_some() {
431 self.tag = tag;
432 }
433 self
434 }
435
436 #[inline]
438 pub fn span(mut self, span: Span) -> Self {
439 self.span = Some(span);
440 self
441 }
442
443 #[inline]
445 pub fn build(self) -> ValueMeta<'a> {
446 ValueMeta {
447 doc: self.doc,
448 tag: self.tag,
449 span: self.span,
450 }
451 }
452}
453
454#[derive(Clone, PartialEq)]
456pub struct ParseEvent<'de> {
457 pub kind: ParseEventKind<'de>,
459 pub span: facet_reflect::Span,
461 pub meta: Option<ValueMeta<'de>>,
466}
467
468impl<'de> ParseEvent<'de> {
469 #[inline]
471 pub fn new(kind: ParseEventKind<'de>, span: facet_reflect::Span) -> Self {
472 Self {
473 kind,
474 span,
475 meta: None,
476 }
477 }
478
479 #[inline]
486 pub fn with_meta(
487 mut self,
488 f: impl FnOnce(ValueMetaBuilder<'de>) -> ValueMetaBuilder<'de>,
489 ) -> Self {
490 let meta = f(ValueMetaBuilder::default()).build();
491 if !meta.is_empty() {
492 self.meta = Some(meta);
493 }
494 self
495 }
496}
497
498#[derive(Clone, PartialEq)]
500#[non_exhaustive]
501pub enum ParseEventKind<'de> {
502 StructStart(ContainerKind),
504 StructEnd,
506 FieldKey(FieldKey<'de>),
508 OrderedField,
514 SequenceStart(ContainerKind),
516 SequenceEnd,
518 Scalar(ScalarValue<'de>),
520 VariantTag(Option<&'de str>),
528}
529
530impl<'de> fmt::Debug for ParseEvent<'de> {
531 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
532 write!(f, "{:?}@{}", self.kind, self.span)
534 }
535}
536
537impl<'de> fmt::Debug for ParseEventKind<'de> {
538 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
539 match self {
540 ParseEventKind::StructStart(kind) => f.debug_tuple("StructStart").field(kind).finish(),
541 ParseEventKind::StructEnd => f.write_str("StructEnd"),
542 ParseEventKind::FieldKey(key) => f.debug_tuple("FieldKey").field(key).finish(),
543 ParseEventKind::OrderedField => f.write_str("OrderedField"),
544 ParseEventKind::SequenceStart(kind) => {
545 f.debug_tuple("SequenceStart").field(kind).finish()
546 }
547 ParseEventKind::SequenceEnd => f.write_str("SequenceEnd"),
548 ParseEventKind::Scalar(value) => f.debug_tuple("Scalar").field(value).finish(),
549 ParseEventKind::VariantTag(tag) => f.debug_tuple("VariantTag").field(tag).finish(),
550 }
551 }
552}
553
554impl ParseEvent<'_> {
555 #[inline]
557 pub const fn kind_name(&self) -> &'static str {
558 self.kind.kind_name()
559 }
560}
561
562impl ParseEventKind<'_> {
563 #[inline]
565 pub const fn kind_name(&self) -> &'static str {
566 match self {
567 ParseEventKind::StructStart(_) => "struct start",
568 ParseEventKind::StructEnd => "struct end",
569 ParseEventKind::FieldKey(_) => "field key",
570 ParseEventKind::OrderedField => "ordered field",
571 ParseEventKind::SequenceStart(_) => "sequence start",
572 ParseEventKind::SequenceEnd => "sequence end",
573 ParseEventKind::Scalar(_) => "scalar",
574 ParseEventKind::VariantTag(_) => "variant tag",
575 }
576 }
577}