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)]
11pub enum FieldLocationHint {
12 #[default]
14 KeyValue,
15}
16
17#[derive(Debug, Clone, PartialEq, Eq)]
25pub enum FieldKey<'de> {
26 Name(Cow<'de, str>),
28 Full(Box<FullFieldKey<'de>>),
30}
31
32#[derive(Debug, Clone, PartialEq, Eq)]
36pub struct FullFieldKey<'de> {
37 pub name: Option<Cow<'de, str>>,
43 pub location: FieldLocationHint,
45 pub meta: ValueMeta<'de>,
47}
48
49impl<'de> FieldKey<'de> {
50 #[inline]
52 pub fn new(name: impl Into<Cow<'de, str>>, _location: FieldLocationHint) -> Self {
53 FieldKey::Name(name.into())
54 }
55
56 pub fn with_doc(
58 name: impl Into<Cow<'de, str>>,
59 location: FieldLocationHint,
60 doc: Vec<Cow<'de, str>>,
61 ) -> Self {
62 if doc.is_empty() {
63 FieldKey::Name(name.into())
64 } else {
65 FieldKey::Full(Box::new(FullFieldKey {
66 name: Some(name.into()),
67 location,
68 meta: ValueMeta::builder().doc(doc).build(),
69 }))
70 }
71 }
72
73 pub fn tagged(tag: impl Into<Cow<'de, str>>, location: FieldLocationHint) -> Self {
77 FieldKey::Full(Box::new(FullFieldKey {
78 name: None,
79 location,
80 meta: ValueMeta::builder().tag(tag.into()).build(),
81 }))
82 }
83
84 pub fn tagged_with_doc(
86 tag: impl Into<Cow<'de, str>>,
87 location: FieldLocationHint,
88 doc: Vec<Cow<'de, str>>,
89 ) -> Self {
90 FieldKey::Full(Box::new(FullFieldKey {
91 name: None,
92 location,
93 meta: ValueMeta::builder()
94 .tag(tag.into())
95 .maybe_doc(Some(doc))
96 .build(),
97 }))
98 }
99
100 pub fn tagged_with_name(
104 tag: impl Into<Cow<'de, str>>,
105 name: impl Into<Cow<'de, str>>,
106 location: FieldLocationHint,
107 ) -> Self {
108 FieldKey::Full(Box::new(FullFieldKey {
109 name: Some(name.into()),
110 location,
111 meta: ValueMeta::builder().tag(tag.into()).build(),
112 }))
113 }
114
115 pub fn tagged_with_name_and_doc(
117 tag: impl Into<Cow<'de, str>>,
118 name: impl Into<Cow<'de, str>>,
119 location: FieldLocationHint,
120 doc: Vec<Cow<'de, str>>,
121 ) -> Self {
122 FieldKey::Full(Box::new(FullFieldKey {
123 name: Some(name.into()),
124 location,
125 meta: ValueMeta::builder()
126 .tag(tag.into())
127 .maybe_doc(Some(doc))
128 .build(),
129 }))
130 }
131
132 pub fn unit(location: FieldLocationHint) -> Self {
137 FieldKey::Full(Box::new(FullFieldKey {
138 name: None,
139 location,
140 meta: ValueMeta::builder().tag(Cow::Borrowed("")).build(),
141 }))
142 }
143
144 pub fn unit_with_doc(location: FieldLocationHint, doc: Vec<Cow<'de, str>>) -> Self {
146 FieldKey::Full(Box::new(FullFieldKey {
147 name: None,
148 location,
149 meta: ValueMeta::builder()
150 .tag(Cow::Borrowed(""))
151 .maybe_doc(Some(doc))
152 .build(),
153 }))
154 }
155
156 #[inline]
158 pub fn name(&self) -> Option<&Cow<'de, str>> {
159 match self {
160 FieldKey::Name(name) => Some(name),
161 FieldKey::Full(full) => full.name.as_ref(),
162 }
163 }
164
165 #[inline]
167 pub fn doc(&self) -> Option<&[Cow<'de, str>]> {
168 match self {
169 FieldKey::Name(_) => None,
170 FieldKey::Full(full) => full.meta.doc(),
171 }
172 }
173
174 #[inline]
176 pub fn tag(&self) -> Option<&Cow<'de, str>> {
177 match self {
178 FieldKey::Name(_) => None,
179 FieldKey::Full(full) => full.meta.tag(),
180 }
181 }
182
183 #[inline]
185 pub fn meta(&self) -> Option<&ValueMeta<'de>> {
186 match self {
187 FieldKey::Name(_) => None,
188 FieldKey::Full(full) => Some(&full.meta),
189 }
190 }
191
192 #[inline]
194 pub fn location(&self) -> FieldLocationHint {
195 match self {
196 FieldKey::Name(_) => FieldLocationHint::KeyValue,
197 FieldKey::Full(full) => full.location,
198 }
199 }
200}
201
202#[derive(Debug, Clone, Copy, PartialEq, Eq)]
207pub enum ContainerKind {
208 Object,
211 Array,
214}
215
216impl ContainerKind {
217 pub const fn name(self) -> &'static str {
219 match self {
220 ContainerKind::Object => "object",
221 ContainerKind::Array => "array",
222 }
223 }
224}
225
226#[derive(Debug, Clone, Copy, PartialEq, Eq)]
228pub enum ValueTypeHint {
229 Null,
231 Bool,
233 Number,
235 String,
237 Bytes,
239 Sequence,
241 Map,
243}
244
245#[derive(Debug, Clone, PartialEq)]
247pub enum ScalarValue<'de> {
248 Unit,
250 Null,
252 Bool(bool),
254 Char(char),
256 I64(i64),
258 U64(u64),
260 I128(i128),
262 U128(u128),
264 F64(f64),
266 Str(Cow<'de, str>),
268 Bytes(Cow<'de, [u8]>),
270}
271
272impl<'de> ScalarValue<'de> {
273 pub fn to_string_value(&self) -> Option<alloc::string::String> {
278 match self {
279 ScalarValue::Str(s) => Some(s.to_string()),
280 ScalarValue::Bool(b) => Some(b.to_string()),
281 ScalarValue::I64(i) => Some(i.to_string()),
282 ScalarValue::U64(u) => Some(u.to_string()),
283 ScalarValue::I128(i) => Some(i.to_string()),
284 ScalarValue::U128(u) => Some(u.to_string()),
285 ScalarValue::F64(f) => Some(f.to_string()),
286 ScalarValue::Char(c) => Some(c.to_string()),
287 ScalarValue::Null => Some("null".to_string()),
288 ScalarValue::Unit => Some(alloc::string::String::new()),
289 ScalarValue::Bytes(_) => None,
290 }
291 }
292
293 pub fn to_display_string(&self) -> alloc::string::String {
297 match self {
298 ScalarValue::Str(s) => s.to_string(),
299 ScalarValue::Bool(b) => alloc::format!("bool({})", b),
300 ScalarValue::I64(i) => alloc::format!("i64({})", i),
301 ScalarValue::U64(u) => alloc::format!("u64({})", u),
302 ScalarValue::I128(i) => alloc::format!("i128({})", i),
303 ScalarValue::U128(u) => alloc::format!("u128({})", u),
304 ScalarValue::F64(f) => alloc::format!("f64({})", f),
305 ScalarValue::Char(c) => alloc::format!("char({})", c),
306 ScalarValue::Bytes(_) => "bytes".to_string(),
307 ScalarValue::Null => "null".to_string(),
308 ScalarValue::Unit => "unit".to_string(),
309 }
310 }
311
312 #[inline]
314 pub const fn kind_name(&self) -> &'static str {
315 match self {
316 ScalarValue::Unit => "unit",
317 ScalarValue::Null => "null",
318 ScalarValue::Bool(_) => "bool",
319 ScalarValue::Char(_) => "char",
320 ScalarValue::I64(_) => "i64",
321 ScalarValue::U64(_) => "u64",
322 ScalarValue::I128(_) => "i128",
323 ScalarValue::U128(_) => "u128",
324 ScalarValue::F64(_) => "f64",
325 ScalarValue::Str(_) => "string",
326 ScalarValue::Bytes(_) => "bytes",
327 }
328 }
329}
330
331#[derive(Debug, Clone, Default, PartialEq, Eq)]
338#[non_exhaustive]
339pub struct ValueMeta<'a> {
340 doc: Option<Vec<Cow<'a, str>>>,
341 tag: Option<Cow<'a, str>>,
342 span: Option<Span>,
343}
344
345impl<'a> ValueMeta<'a> {
346 pub const fn empty() -> Self {
348 Self {
349 doc: None,
350 tag: None,
351 span: None,
352 }
353 }
354
355 #[inline]
357 pub fn builder() -> ValueMetaBuilder<'a> {
358 ValueMetaBuilder::default()
359 }
360
361 #[inline]
363 pub fn doc(&self) -> Option<&[Cow<'a, str>]> {
364 self.doc.as_deref()
365 }
366
367 #[inline]
369 pub fn tag(&self) -> Option<&Cow<'a, str>> {
370 self.tag.as_ref()
371 }
372
373 #[inline]
375 pub fn span(&self) -> Option<Span> {
376 self.span
377 }
378
379 #[inline]
381 pub fn is_empty(&self) -> bool {
382 self.doc.is_none() && self.tag.is_none() && self.span.is_none()
383 }
384}
385
386#[derive(Debug, Clone, Default)]
388pub struct ValueMetaBuilder<'a> {
389 doc: Option<Vec<Cow<'a, str>>>,
390 tag: Option<Cow<'a, str>>,
391 span: Option<Span>,
392}
393
394impl<'a> ValueMetaBuilder<'a> {
395 #[inline]
397 pub fn doc(mut self, doc: Vec<Cow<'a, str>>) -> Self {
398 if !doc.is_empty() {
399 self.doc = Some(doc);
400 }
401 self
402 }
403
404 #[inline]
406 pub fn maybe_doc(mut self, doc: Option<Vec<Cow<'a, str>>>) -> Self {
407 if let Some(d) = doc
408 && !d.is_empty()
409 {
410 self.doc = Some(d);
411 }
412 self
413 }
414
415 #[inline]
417 pub fn tag(mut self, tag: Cow<'a, str>) -> Self {
418 self.tag = Some(tag);
419 self
420 }
421
422 #[inline]
424 pub fn maybe_tag(mut self, tag: Option<Cow<'a, str>>) -> Self {
425 if tag.is_some() {
426 self.tag = tag;
427 }
428 self
429 }
430
431 #[inline]
433 pub fn span(mut self, span: Span) -> Self {
434 self.span = Some(span);
435 self
436 }
437
438 #[inline]
440 pub fn build(self) -> ValueMeta<'a> {
441 ValueMeta {
442 doc: self.doc,
443 tag: self.tag,
444 span: self.span,
445 }
446 }
447}
448
449#[derive(Clone, PartialEq)]
451pub struct ParseEvent<'de> {
452 pub kind: ParseEventKind<'de>,
454 pub span: facet_reflect::Span,
456 pub meta: Option<ValueMeta<'de>>,
461}
462
463impl<'de> ParseEvent<'de> {
464 #[inline]
466 pub fn new(kind: ParseEventKind<'de>, span: facet_reflect::Span) -> Self {
467 Self {
468 kind,
469 span,
470 meta: None,
471 }
472 }
473
474 #[inline]
481 pub fn with_meta(
482 mut self,
483 f: impl FnOnce(ValueMetaBuilder<'de>) -> ValueMetaBuilder<'de>,
484 ) -> Self {
485 let meta = f(ValueMetaBuilder::default()).build();
486 if !meta.is_empty() {
487 self.meta = Some(meta);
488 }
489 self
490 }
491}
492
493#[derive(Clone, PartialEq)]
495pub enum ParseEventKind<'de> {
496 StructStart(ContainerKind),
498 StructEnd,
500 FieldKey(FieldKey<'de>),
502 OrderedField,
508 SequenceStart(ContainerKind),
510 SequenceEnd,
512 Scalar(ScalarValue<'de>),
514 VariantTag(Option<&'de str>),
522}
523
524impl<'de> fmt::Debug for ParseEvent<'de> {
525 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
526 write!(f, "{:?}@{}", self.kind, self.span)
528 }
529}
530
531impl<'de> fmt::Debug for ParseEventKind<'de> {
532 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
533 match self {
534 ParseEventKind::StructStart(kind) => f.debug_tuple("StructStart").field(kind).finish(),
535 ParseEventKind::StructEnd => f.write_str("StructEnd"),
536 ParseEventKind::FieldKey(key) => f.debug_tuple("FieldKey").field(key).finish(),
537 ParseEventKind::OrderedField => f.write_str("OrderedField"),
538 ParseEventKind::SequenceStart(kind) => {
539 f.debug_tuple("SequenceStart").field(kind).finish()
540 }
541 ParseEventKind::SequenceEnd => f.write_str("SequenceEnd"),
542 ParseEventKind::Scalar(value) => f.debug_tuple("Scalar").field(value).finish(),
543 ParseEventKind::VariantTag(tag) => f.debug_tuple("VariantTag").field(tag).finish(),
544 }
545 }
546}
547
548impl ParseEvent<'_> {
549 #[inline]
551 pub const fn kind_name(&self) -> &'static str {
552 self.kind.kind_name()
553 }
554}
555
556impl ParseEventKind<'_> {
557 #[inline]
559 pub const fn kind_name(&self) -> &'static str {
560 match self {
561 ParseEventKind::StructStart(_) => "struct start",
562 ParseEventKind::StructEnd => "struct end",
563 ParseEventKind::FieldKey(_) => "field key",
564 ParseEventKind::OrderedField => "ordered field",
565 ParseEventKind::SequenceStart(_) => "sequence start",
566 ParseEventKind::SequenceEnd => "sequence end",
567 ParseEventKind::Scalar(_) => "scalar",
568 ParseEventKind::VariantTag(_) => "variant tag",
569 }
570 }
571}