1extern crate alloc;
4
5pub mod object_key;
6pub mod record;
7pub mod tuple;
8pub mod union;
9pub mod variant_path;
10
11use indexmap::{IndexMap, IndexSet};
12pub use object_key::ParseObjectKey;
13pub use record::RecordParser;
14pub use tuple::TupleParser;
15pub use union::UnionParser;
16pub use variant_path::VariantPath;
17use alloc::format;
20use alloc::rc::Rc;
21use core::cell::RefCell;
22use num_bigint::BigInt;
23
24use core::marker::PhantomData;
25use std::collections::{BTreeMap, HashMap, HashSet};
26
27use crate::{
28 data_model::VariantRepr,
29 document::node::{Node, NodeArray},
30 identifier::IdentifierError,
31 prelude_internal::*,
32 value::ValueKind,
33};
34
35#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
47pub enum UnionTagMode {
48 #[default]
55 Eure,
56
57 Repr,
64}
65
66pub type AccessedSnapshot = (HashSet<String>, HashSet<Identifier>);
72
73#[derive(Debug, Clone)]
90pub struct AccessedSet(Rc<RefCell<Vec<AccessedSnapshot>>>);
91
92impl AccessedSet {
93 pub fn new() -> Self {
95 Self(Rc::new(RefCell::new(vec![(
97 HashSet::new(),
98 HashSet::new(),
99 )])))
100 }
101
102 pub fn add_field(&self, field: impl Into<String>) {
104 self.0
105 .borrow_mut()
106 .last_mut()
107 .unwrap()
108 .0
109 .insert(field.into());
110 }
111
112 pub fn add_ext(&self, ext: Identifier) {
114 self.0.borrow_mut().last_mut().unwrap().1.insert(ext);
115 }
116
117 pub fn has_field(&self, field: &str) -> bool {
119 self.0.borrow().last().unwrap().0.contains(field)
120 }
121
122 pub fn has_ext(&self, ext: &Identifier) -> bool {
124 self.0.borrow().last().unwrap().1.contains(ext)
125 }
126
127 pub fn push_snapshot(&self) {
130 let mut stack = self.0.borrow_mut();
131 let snapshot = stack.last().unwrap().clone();
132 let len = stack.len();
133 stack.insert(len - 1, snapshot);
134 }
136
137 pub fn restore_to_current_snapshot(&self) {
140 let mut stack = self.0.borrow_mut();
141 if stack.len() >= 2 {
142 let snapshot = stack[stack.len() - 2].clone();
143 *stack.last_mut().unwrap() = snapshot;
144 }
145 }
146
147 pub fn capture_current_state(&self) -> AccessedSnapshot {
149 self.0.borrow().last().unwrap().clone()
150 }
151
152 pub fn restore_to_state(&self, state: AccessedSnapshot) {
154 *self.0.borrow_mut().last_mut().unwrap() = state;
155 }
156
157 pub fn pop_and_restore(&self) {
160 let mut stack = self.0.borrow_mut();
161 if stack.len() >= 2 {
162 stack.pop(); }
164 }
165
166 pub fn pop_without_restore(&self) {
169 let mut stack = self.0.borrow_mut();
170 if stack.len() >= 2 {
171 let snapshot_idx = stack.len() - 2;
172 stack.remove(snapshot_idx); }
174 }
175}
176
177impl Default for AccessedSet {
178 fn default() -> Self {
179 Self::new()
180 }
181}
182
183#[derive(Debug, Clone, Copy, PartialEq, Eq)]
191pub enum ParserScope {
192 Record,
194 Extension,
196}
197
198#[derive(Debug, Clone)]
225pub struct FlattenContext {
226 accessed: AccessedSet,
227 scope: ParserScope,
228}
229
230impl FlattenContext {
231 pub fn new(accessed: AccessedSet, scope: ParserScope) -> Self {
233 Self { accessed, scope }
234 }
235
236 pub fn scope(&self) -> ParserScope {
238 self.scope
239 }
240
241 pub fn accessed_set(&self) -> &AccessedSet {
243 &self.accessed
244 }
245
246 pub fn add_field(&self, field: impl Into<String>) {
248 self.accessed.add_field(field);
249 }
250
251 pub fn add_ext(&self, ext: Identifier) {
253 self.accessed.add_ext(ext);
254 }
255
256 pub fn has_field(&self, field: &str) -> bool {
258 self.accessed.has_field(field)
259 }
260
261 pub fn has_ext(&self, ext: &Identifier) -> bool {
263 self.accessed.has_ext(ext)
264 }
265
266 pub fn push_snapshot(&self) {
268 self.accessed.push_snapshot();
269 }
270
271 pub fn restore_to_current_snapshot(&self) {
273 self.accessed.restore_to_current_snapshot();
274 }
275
276 pub fn capture_current_state(&self) -> AccessedSnapshot {
278 self.accessed.capture_current_state()
279 }
280
281 pub fn restore_to_state(&self, state: AccessedSnapshot) {
283 self.accessed.restore_to_state(state);
284 }
285
286 pub fn pop_and_restore(&self) {
288 self.accessed.pop_and_restore();
289 }
290
291 pub fn pop_without_restore(&self) {
293 self.accessed.pop_without_restore();
294 }
295}
296
297#[derive(Clone, Debug)]
306pub struct ParseContext<'doc> {
307 doc: &'doc EureDocument,
308 node_id: NodeId,
309 variant_path: Option<VariantPath>,
310 flatten_ctx: Option<FlattenContext>,
314 union_tag_mode: UnionTagMode,
316 accessed: AccessedSet,
318}
319
320impl<'doc> ParseContext<'doc> {
321 pub fn new(doc: &'doc EureDocument, node_id: NodeId) -> Self {
323 Self {
324 doc,
325 node_id,
326 variant_path: None,
327 flatten_ctx: None,
328 union_tag_mode: UnionTagMode::default(),
329 accessed: AccessedSet::new(),
330 }
331 }
332
333 pub fn with_union_tag_mode(
335 doc: &'doc EureDocument,
336 node_id: NodeId,
337 mode: UnionTagMode,
338 ) -> Self {
339 Self {
340 doc,
341 node_id,
342 variant_path: None,
343 flatten_ctx: None,
344 union_tag_mode: mode,
345 accessed: AccessedSet::new(),
346 }
347 }
348
349 pub fn with_flatten_ctx(
355 doc: &'doc EureDocument,
356 node_id: NodeId,
357 flatten_ctx: FlattenContext,
358 mode: UnionTagMode,
359 ) -> Self {
360 let accessed = flatten_ctx.accessed_set().clone();
362 Self {
363 doc,
364 node_id,
365 variant_path: None,
366 flatten_ctx: Some(flatten_ctx),
367 union_tag_mode: mode,
368 accessed,
369 }
370 }
371
372 pub fn flatten_ctx(&self) -> Option<&FlattenContext> {
374 self.flatten_ctx.as_ref()
375 }
376
377 pub fn is_flattened(&self) -> bool {
381 self.flatten_ctx.is_some()
382 }
383
384 pub fn parser_scope(&self) -> Option<ParserScope> {
390 self.flatten_ctx.as_ref().map(|fc| fc.scope())
391 }
392
393 pub fn node_id(&self) -> NodeId {
395 self.node_id
396 }
397
398 pub(crate) fn doc(&self) -> &'doc EureDocument {
400 self.doc
401 }
402
403 pub fn node(&self) -> &'doc Node {
405 self.doc.node(self.node_id)
406 }
407
408 pub(crate) fn at(&self, node_id: NodeId) -> Self {
410 Self {
411 doc: self.doc,
412 node_id,
413 variant_path: None,
414 flatten_ctx: None,
415 union_tag_mode: self.union_tag_mode,
416 accessed: AccessedSet::new(),
417 }
418 }
419
420 pub fn flatten(&self) -> Self {
455 let flatten_ctx = match &self.flatten_ctx {
460 Some(fc) => FlattenContext::new(fc.accessed_set().clone(), ParserScope::Record),
461 None => FlattenContext::new(self.accessed.clone(), ParserScope::Record),
462 };
463 Self {
464 doc: self.doc,
465 node_id: self.node_id,
466 variant_path: self.variant_path.clone(),
467 flatten_ctx: Some(flatten_ctx),
468 union_tag_mode: self.union_tag_mode,
469 accessed: self.accessed.clone(),
470 }
471 }
472
473 pub fn union_tag_mode(&self) -> UnionTagMode {
475 self.union_tag_mode
476 }
477
478 pub fn parse<T: ParseDocument<'doc>>(&self) -> Result<T, T::Error> {
480 T::parse(self)
481 }
482
483 pub fn parse_with<T: DocumentParser<'doc>>(
484 &self,
485 mut parser: T,
486 ) -> Result<T::Output, T::Error> {
487 parser.parse(self)
488 }
489
490 pub fn parse_union<T, E>(&self, repr: VariantRepr) -> Result<UnionParser<'doc, '_, T, E>, E>
498 where
499 E: From<ParseError>,
500 {
501 UnionParser::new(self, repr).map_err(Into::into)
502 }
503
504 pub fn parse_record(&self) -> Result<RecordParser<'doc>, ParseError> {
508 self.ensure_no_variant_path()?;
509 RecordParser::new(self)
510 }
511
512 pub fn parse_tuple(&self) -> Result<TupleParser<'doc>, ParseError> {
516 self.ensure_no_variant_path()?;
517 TupleParser::new(self)
518 }
519
520 pub fn parse_primitive(&self) -> Result<&'doc PrimitiveValue, ParseError> {
524 self.ensure_no_variant_path()?;
525 match &self.node().content {
526 NodeValue::Primitive(p) => Ok(p),
527 value => Err(ParseError {
528 node_id: self.node_id,
529 kind: handle_unexpected_node_value(value),
530 }),
531 }
532 }
533
534 pub(crate) fn accessed(&self) -> &AccessedSet {
540 &self.accessed
541 }
542
543 fn mark_ext_accessed(&self, ident: Identifier) {
545 self.accessed.add_ext(ident);
546 }
547
548 pub fn parse_ext<T>(&self, name: &str) -> Result<T, T::Error>
552 where
553 T: ParseDocument<'doc>,
554 T::Error: From<ParseError>,
555 {
556 self.parse_ext_with(name, T::parse)
557 }
558
559 pub fn parse_ext_with<T>(&self, name: &str, mut parser: T) -> Result<T::Output, T::Error>
561 where
562 T: DocumentParser<'doc>,
563 T::Error: From<ParseError>,
564 {
565 let ident: Identifier = name.parse().map_err(|e| ParseError {
566 node_id: self.node_id,
567 kind: ParseErrorKind::InvalidIdentifier(e),
568 })?;
569 self.mark_ext_accessed(ident.clone());
570 let ext_node_id = self
571 .node()
572 .extensions
573 .get(&ident)
574 .ok_or_else(|| ParseError {
575 node_id: self.node_id,
576 kind: ParseErrorKind::MissingExtension(name.to_string()),
577 })?;
578 let ctx = ParseContext::with_union_tag_mode(self.doc, *ext_node_id, self.union_tag_mode);
579 parser.parse(&ctx)
580 }
581
582 pub fn parse_ext_optional<T>(&self, name: &str) -> Result<Option<T>, T::Error>
586 where
587 T: ParseDocument<'doc>,
588 T::Error: From<ParseError>,
589 {
590 self.parse_ext_optional_with(name, T::parse)
591 }
592
593 pub fn parse_ext_optional_with<T>(
597 &self,
598 name: &str,
599 mut parser: T,
600 ) -> Result<Option<T::Output>, T::Error>
601 where
602 T: DocumentParser<'doc>,
603 T::Error: From<ParseError>,
604 {
605 let ident: Identifier = name.parse().map_err(|e| ParseError {
606 node_id: self.node_id,
607 kind: ParseErrorKind::InvalidIdentifier(e),
608 })?;
609 self.mark_ext_accessed(ident.clone());
610 match self.node().extensions.get(&ident) {
611 Some(ext_node_id) => {
612 let ctx =
613 ParseContext::with_union_tag_mode(self.doc, *ext_node_id, self.union_tag_mode);
614 Ok(Some(parser.parse(&ctx)?))
615 }
616 None => Ok(None),
617 }
618 }
619
620 pub fn ext(&self, name: &str) -> Result<ParseContext<'doc>, ParseError> {
625 let ident: Identifier = name.parse().map_err(|e| ParseError {
626 node_id: self.node_id,
627 kind: ParseErrorKind::InvalidIdentifier(e),
628 })?;
629 self.mark_ext_accessed(ident.clone());
630 let ext_node_id =
631 self.node()
632 .extensions
633 .get(&ident)
634 .copied()
635 .ok_or_else(|| ParseError {
636 node_id: self.node_id,
637 kind: ParseErrorKind::MissingExtension(name.to_string()),
638 })?;
639 Ok(ParseContext::with_union_tag_mode(
640 self.doc,
641 ext_node_id,
642 self.union_tag_mode,
643 ))
644 }
645
646 pub fn ext_optional(&self, name: &str) -> Option<ParseContext<'doc>> {
651 let ident: Identifier = name.parse().ok()?;
652 self.mark_ext_accessed(ident.clone());
653 self.node().extensions.get(&ident).map(|&node_id| {
654 ParseContext::with_union_tag_mode(self.doc, node_id, self.union_tag_mode)
655 })
656 }
657
658 pub fn deny_unknown_extensions(&self) -> Result<(), ParseError> {
663 if self.flatten_ctx.is_some() {
665 return Ok(());
666 }
667
668 for (ident, _) in self.node().extensions.iter() {
670 if !self.accessed.has_ext(ident) {
671 return Err(ParseError {
672 node_id: self.node_id,
673 kind: ParseErrorKind::UnknownExtension(ident.clone()),
674 });
675 }
676 }
677 Ok(())
678 }
679
680 pub fn unknown_extensions(
684 &self,
685 ) -> impl Iterator<Item = (&'doc Identifier, ParseContext<'doc>)> + '_ {
686 let doc = self.doc;
687 let mode = self.union_tag_mode;
688 let accessed = self.accessed.clone();
690 self.node()
691 .extensions
692 .iter()
693 .filter_map(move |(ident, &node_id)| {
694 if !accessed.has_ext(ident) {
695 Some((ident, ParseContext::with_union_tag_mode(doc, node_id, mode)))
696 } else {
697 None
698 }
699 })
700 }
701
702 pub fn flatten_ext(&self) -> ParseContext<'doc> {
728 let flatten_ctx = match &self.flatten_ctx {
733 Some(fc) => FlattenContext::new(fc.accessed_set().clone(), ParserScope::Extension),
734 None => FlattenContext::new(self.accessed.clone(), ParserScope::Extension),
735 };
736
737 ParseContext::with_flatten_ctx(self.doc, self.node_id, flatten_ctx, self.union_tag_mode)
738 }
739
740 pub fn is_null(&self) -> bool {
742 matches!(
743 &self.node().content,
744 NodeValue::Primitive(PrimitiveValue::Null)
745 )
746 }
747
748 pub(crate) fn with_variant_rest(&self, rest: Option<VariantPath>) -> Self {
750 Self {
751 doc: self.doc,
752 node_id: self.node_id,
753 variant_path: rest,
754 flatten_ctx: self.flatten_ctx.clone(),
755 union_tag_mode: self.union_tag_mode,
756 accessed: self.accessed.clone(),
757 }
758 }
759
760 pub(crate) fn variant_path(&self) -> Option<&VariantPath> {
762 self.variant_path.as_ref()
763 }
764
765 fn ensure_no_variant_path(&self) -> Result<(), ParseError> {
767 if let Some(vp) = &self.variant_path
768 && !vp.is_empty()
769 {
770 return Err(ParseError {
771 node_id: self.node_id,
772 kind: ParseErrorKind::UnexpectedVariantPath(vp.clone()),
773 });
774 }
775 Ok(())
776 }
777}
778
779pub trait ParseDocument<'doc>: Sized {
803 type Error;
805
806 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error>;
808}
809
810fn handle_unexpected_node_value(node_value: &NodeValue) -> ParseErrorKind {
811 match node_value {
812 NodeValue::Hole(_) => ParseErrorKind::UnexpectedHole,
813 value => value
814 .value_kind()
815 .map(|actual| ParseErrorKind::TypeMismatch {
816 expected: ValueKind::Text,
817 actual,
818 })
819 .unwrap_or_else(|| ParseErrorKind::UnexpectedHole),
820 }
821}
822
823#[derive(Debug, thiserror::Error, Clone, PartialEq)]
824#[error("parse error: {kind}")]
825pub struct ParseError {
826 pub node_id: NodeId,
827 pub kind: ParseErrorKind,
828}
829
830#[derive(Debug, thiserror::Error, Clone, PartialEq)]
832pub enum ParseErrorKind {
833 #[error("unexpected uninitialized value")]
835 UnexpectedHole,
836
837 #[error("type mismatch: expected {expected}, got {actual}")]
839 TypeMismatch {
840 expected: ValueKind,
841 actual: ValueKind,
842 },
843
844 #[error("missing field: {0}")]
846 MissingField(String),
847
848 #[error("missing extension: ${0}")]
850 MissingExtension(String),
851
852 #[error("unknown variant: {0}")]
854 UnknownVariant(String),
855
856 #[error("value out of range: {0}")]
858 OutOfRange(String),
859
860 #[error("invalid {kind}: {reason}")]
866 InvalidPattern { kind: String, reason: String },
867
868 #[error("at {path}: {source}")]
870 Nested {
871 path: String,
872 #[source]
873 source: Box<ParseErrorKind>,
874 },
875
876 #[error("invalid identifier: {0}")]
878 InvalidIdentifier(#[from] IdentifierError),
879
880 #[error("unexpected tuple length: expected {expected}, got {actual}")]
882 UnexpectedTupleLength { expected: usize, actual: usize },
883
884 #[error("unknown field: {0}")]
886 UnknownField(String),
887
888 #[error("unknown extension: ${0}")]
890 UnknownExtension(Identifier),
891
892 #[error("invalid key type in record: expected string key, got {0:?}")]
894 InvalidKeyType(crate::value::ObjectKey),
895
896 #[error("no matching variant{}", variant.as_ref().map(|v| format!(" (variant: {})", v)).unwrap_or_default())]
898 NoMatchingVariant {
899 variant: Option<String>,
901 },
902
903 #[error("conflicting variant tags: $variant = {explicit}, repr = {repr}")]
905 ConflictingVariantTags { explicit: String, repr: String },
906
907 #[error("ambiguous union: {0:?}")]
909 AmbiguousUnion(Vec<String>),
910
911 #[error("literal value mismatch: expected {expected}, got {actual}")]
913 LiteralMismatch { expected: String, actual: String },
915
916 #[error("unexpected variant path: {0}")]
918 UnexpectedVariantPath(VariantPath),
919
920 #[error("$variant must be a string, got {0}")]
922 InvalidVariantType(ValueKind),
923
924 #[error("invalid $variant path syntax: {0}")]
926 InvalidVariantPath(String),
927
928 #[error(
931 "cannot parse record in extension scope: use #[eure(flatten)] instead of #[eure(flatten_ext)]"
932 )]
933 RecordInExtensionScope,
934}
935
936impl ParseErrorKind {
937 pub fn at(self, path: impl Into<String>) -> Self {
939 ParseErrorKind::Nested {
940 path: path.into(),
941 source: Box::new(self),
942 }
943 }
944}
945
946impl<'doc> EureDocument {
947 pub fn parse<T: ParseDocument<'doc>>(&'doc self, node_id: NodeId) -> Result<T, T::Error> {
949 self.parse_with(node_id, T::parse)
950 }
951
952 pub fn parse_with<T: DocumentParser<'doc>>(
953 &'doc self,
954 node_id: NodeId,
955 mut parser: T,
956 ) -> Result<T::Output, T::Error> {
957 parser.parse(&self.parse_context(node_id))
958 }
959
960 pub fn parse_context(&'doc self, node_id: NodeId) -> ParseContext<'doc> {
962 ParseContext::new(self, node_id)
963 }
964
965 pub fn parse_record(&'doc self, node_id: NodeId) -> Result<RecordParser<'doc>, ParseError> {
969 RecordParser::from_doc_and_node(self, node_id)
970 }
971
972 pub fn parse_extension_context(&'doc self, node_id: NodeId) -> ParseContext<'doc> {
977 ParseContext::new(self, node_id)
978 }
979
980 pub fn parse_tuple(&'doc self, node_id: NodeId) -> Result<TupleParser<'doc>, ParseError> {
984 TupleParser::from_doc_and_node(self, node_id)
985 }
986}
987
988impl<'doc> ParseDocument<'doc> for EureDocument {
989 type Error = ParseError;
990
991 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
992 Ok(ctx.doc().node_subtree_to_document(ctx.node_id()))
993 }
994}
995
996impl<'doc> ParseDocument<'doc> for &'doc str {
997 type Error = ParseError;
998
999 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1000 match ctx.parse_primitive()? {
1001 PrimitiveValue::Text(text) => Ok(text.as_str()),
1002 _ => Err(ParseError {
1003 node_id: ctx.node_id(),
1004 kind: ParseErrorKind::TypeMismatch {
1005 expected: ValueKind::Text,
1006 actual: ctx.node().content.value_kind().unwrap_or(ValueKind::Null),
1007 },
1008 }),
1009 }
1010 }
1011}
1012
1013impl ParseDocument<'_> for String {
1014 type Error = ParseError;
1015
1016 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1017 ctx.parse::<&str>().map(String::from)
1018 }
1019}
1020
1021impl ParseDocument<'_> for Text {
1022 type Error = ParseError;
1023
1024 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1025 match ctx.parse_primitive()? {
1026 PrimitiveValue::Text(text) => Ok(text.clone()),
1027 _ => Err(ParseError {
1028 node_id: ctx.node_id(),
1029 kind: ParseErrorKind::TypeMismatch {
1030 expected: ValueKind::Text,
1031 actual: ctx.node().content.value_kind().unwrap_or(ValueKind::Null),
1032 },
1033 }),
1034 }
1035 }
1036}
1037
1038impl ParseDocument<'_> for bool {
1039 type Error = ParseError;
1040
1041 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1042 match ctx.parse_primitive()? {
1043 PrimitiveValue::Bool(b) => Ok(*b),
1044 _ => Err(ParseError {
1045 node_id: ctx.node_id(),
1046 kind: ParseErrorKind::TypeMismatch {
1047 expected: ValueKind::Bool,
1048 actual: ctx.node().content.value_kind().unwrap_or(ValueKind::Null),
1049 },
1050 }),
1051 }
1052 }
1053}
1054
1055impl ParseDocument<'_> for BigInt {
1056 type Error = ParseError;
1057
1058 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1059 match ctx.parse_primitive()? {
1060 PrimitiveValue::Integer(i) => Ok(i.clone()),
1061 _ => Err(ParseError {
1062 node_id: ctx.node_id(),
1063 kind: ParseErrorKind::TypeMismatch {
1064 expected: ValueKind::Integer,
1065 actual: ctx.node().content.value_kind().unwrap_or(ValueKind::Null),
1066 },
1067 }),
1068 }
1069 }
1070}
1071
1072impl ParseDocument<'_> for f32 {
1073 type Error = ParseError;
1074
1075 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1076 match ctx.parse_primitive()? {
1077 PrimitiveValue::F32(f) => Ok(*f),
1078 _ => Err(ParseError {
1079 node_id: ctx.node_id(),
1080 kind: ParseErrorKind::TypeMismatch {
1081 expected: ValueKind::F32,
1082 actual: ctx.node().content.value_kind().unwrap_or(ValueKind::Null),
1083 },
1084 }),
1085 }
1086 }
1087}
1088
1089impl ParseDocument<'_> for f64 {
1090 type Error = ParseError;
1091
1092 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1093 match ctx.parse_primitive()? {
1094 PrimitiveValue::F32(f) => Ok(*f as f64),
1096 PrimitiveValue::F64(f) => Ok(*f),
1097 _ => Err(ParseError {
1098 node_id: ctx.node_id(),
1099 kind: ParseErrorKind::TypeMismatch {
1100 expected: ValueKind::F64,
1101 actual: ctx.node().content.value_kind().unwrap_or(ValueKind::Null),
1102 },
1103 }),
1104 }
1105 }
1106}
1107
1108impl ParseDocument<'_> for u32 {
1109 type Error = ParseError;
1110
1111 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1112 let value: BigInt = ctx.parse()?;
1113 u32::try_from(&value).map_err(|_| ParseError {
1114 node_id: ctx.node_id(),
1115 kind: ParseErrorKind::OutOfRange(format!("value {} out of u32 range", value)),
1116 })
1117 }
1118}
1119
1120impl ParseDocument<'_> for i32 {
1121 type Error = ParseError;
1122
1123 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1124 let value: BigInt = ctx.parse()?;
1125 i32::try_from(&value).map_err(|_| ParseError {
1126 node_id: ctx.node_id(),
1127 kind: ParseErrorKind::OutOfRange(format!("value {} out of i32 range", value)),
1128 })
1129 }
1130}
1131
1132impl ParseDocument<'_> for i64 {
1133 type Error = ParseError;
1134
1135 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1136 let value: BigInt = ctx.parse()?;
1137 i64::try_from(&value).map_err(|_| ParseError {
1138 node_id: ctx.node_id(),
1139 kind: ParseErrorKind::OutOfRange(format!("value {} out of i64 range", value)),
1140 })
1141 }
1142}
1143
1144impl ParseDocument<'_> for u64 {
1145 type Error = ParseError;
1146
1147 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1148 let value: BigInt = ctx.parse()?;
1149 u64::try_from(&value).map_err(|_| ParseError {
1150 node_id: ctx.node_id(),
1151 kind: ParseErrorKind::OutOfRange(format!("value {} out of u64 range", value)),
1152 })
1153 }
1154}
1155
1156impl ParseDocument<'_> for usize {
1157 type Error = ParseError;
1158
1159 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1160 let value: BigInt = ctx.parse()?;
1161 usize::try_from(&value).map_err(|_| ParseError {
1162 node_id: ctx.node_id(),
1163 kind: ParseErrorKind::OutOfRange(format!("value {} out of usize range", value)),
1164 })
1165 }
1166}
1167
1168impl<'doc> ParseDocument<'doc> for &'doc PrimitiveValue {
1169 type Error = ParseError;
1170
1171 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1172 ctx.parse_primitive()
1173 }
1174}
1175
1176impl ParseDocument<'_> for PrimitiveValue {
1177 type Error = ParseError;
1178
1179 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1180 ctx.parse::<&PrimitiveValue>().cloned()
1181 }
1182}
1183
1184impl ParseDocument<'_> for Identifier {
1185 type Error = ParseError;
1186
1187 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1188 match ctx.parse_primitive()? {
1189 PrimitiveValue::Text(text) => text
1190 .content
1191 .parse()
1192 .map_err(ParseErrorKind::InvalidIdentifier)
1193 .map_err(|kind| ParseError {
1194 node_id: ctx.node_id(),
1195 kind,
1196 }),
1197 _ => Err(ParseError {
1198 node_id: ctx.node_id(),
1199 kind: ParseErrorKind::TypeMismatch {
1200 expected: ValueKind::Text,
1201 actual: ctx.node().content.value_kind().unwrap_or(ValueKind::Null),
1202 },
1203 }),
1204 }
1205 }
1206}
1207
1208impl<'doc> ParseDocument<'doc> for &'doc NodeArray {
1209 type Error = ParseError;
1210
1211 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1212 ctx.ensure_no_variant_path()?;
1213 match &ctx.node().content {
1214 NodeValue::Array(array) => Ok(array),
1215 value => Err(ParseError {
1216 node_id: ctx.node_id(),
1217 kind: handle_unexpected_node_value(value),
1218 }),
1219 }
1220 }
1221}
1222
1223impl<'doc, T> ParseDocument<'doc> for Vec<T>
1224where
1225 T: ParseDocument<'doc>,
1226 T::Error: From<ParseError>,
1227{
1228 type Error = T::Error;
1229
1230 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1231 ctx.ensure_no_variant_path()?;
1232 match &ctx.node().content {
1233 NodeValue::Array(array) => array
1234 .iter()
1235 .map(|item| T::parse(&ctx.at(*item)))
1236 .collect::<Result<Vec<_>, _>>(),
1237 value => Err(ParseError {
1238 node_id: ctx.node_id(),
1239 kind: handle_unexpected_node_value(value),
1240 }
1241 .into()),
1242 }
1243 }
1244}
1245
1246impl<'doc, T> ParseDocument<'doc> for IndexSet<T>
1247where
1248 T: ParseDocument<'doc> + Eq + std::hash::Hash,
1249 T::Error: From<ParseError>,
1250{
1251 type Error = T::Error;
1252 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1253 ctx.ensure_no_variant_path()?;
1254 match &ctx.node().content {
1255 NodeValue::Array(array) => array
1256 .iter()
1257 .map(|item| T::parse(&ctx.at(*item)))
1258 .collect::<Result<IndexSet<_>, _>>(),
1259 value => Err(ParseError {
1260 node_id: ctx.node_id(),
1261 kind: handle_unexpected_node_value(value),
1262 }
1263 .into()),
1264 }
1265 }
1266}
1267
1268macro_rules! parse_tuple {
1269 ($n:expr, $($var:ident),*) => {
1270 impl<'doc, $($var),*, Err> ParseDocument<'doc> for ($($var),*,)
1271 where $($var: ParseDocument<'doc, Error = Err>),*,
1272 Err: From<ParseError>,
1273 {
1274 type Error = Err;
1275
1276 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1277 ctx.ensure_no_variant_path()?;
1278 let tuple = match &ctx.node().content {
1279 NodeValue::Tuple(tuple) => tuple,
1280 value => return Err(ParseError { node_id: ctx.node_id(), kind: handle_unexpected_node_value(value) }.into()),
1281 };
1282 if tuple.len() != $n {
1283 return Err(ParseError { node_id: ctx.node_id(), kind: ParseErrorKind::UnexpectedTupleLength { expected: $n, actual: tuple.len() } }.into());
1284 }
1285 let mut iter = tuple.iter();
1286 Ok(($($var::parse(&ctx.at(*iter.next().unwrap()))?),*,))
1287 }
1288 }
1289 }
1290}
1291
1292parse_tuple!(1, A);
1293parse_tuple!(2, A, B);
1294parse_tuple!(3, A, B, C);
1295parse_tuple!(4, A, B, C, D);
1296parse_tuple!(5, A, B, C, D, E);
1297parse_tuple!(6, A, B, C, D, E, F);
1298parse_tuple!(7, A, B, C, D, E, F, G);
1299parse_tuple!(8, A, B, C, D, E, F, G, H);
1300parse_tuple!(9, A, B, C, D, E, F, G, H, I);
1301parse_tuple!(10, A, B, C, D, E, F, G, H, I, J);
1302parse_tuple!(11, A, B, C, D, E, F, G, H, I, J, K);
1303parse_tuple!(12, A, B, C, D, E, F, G, H, I, J, K, L);
1304parse_tuple!(13, A, B, C, D, E, F, G, H, I, J, K, L, M);
1305parse_tuple!(14, A, B, C, D, E, F, G, H, I, J, K, L, M, N);
1306parse_tuple!(15, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
1307parse_tuple!(16, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
1308
1309macro_rules! parse_map {
1310 ($ctx:ident) => {{
1311 $ctx.ensure_no_variant_path()?;
1312
1313 if $ctx.parser_scope() == Some(ParserScope::Extension) {
1315 let node = $ctx.node();
1317 let flatten_ctx = $ctx.flatten_ctx();
1318 let accessed = flatten_ctx.map(|fc| fc.accessed_set());
1319 node.extensions
1320 .iter()
1321 .filter(|(ident, _)| {
1322 accessed.map_or(true, |a| !a.has_ext(ident))
1324 })
1325 .map(|(ident, &node_id)| {
1326 if let Some(fc) = &flatten_ctx {
1328 fc.add_ext((*ident).clone());
1329 }
1330 Ok((
1331 K::from_extension_ident(ident).map_err(|kind| ParseError {
1332 node_id: $ctx.node_id(),
1333 kind,
1334 })?,
1335 T::parse(&$ctx.at(node_id))?,
1336 ))
1337 })
1338 .collect::<Result<_, _>>()
1339 } else {
1340 let map = match &$ctx.node().content {
1342 NodeValue::Map(map) => map,
1343 value => {
1344 return Err(ParseError {
1345 node_id: $ctx.node_id(),
1346 kind: handle_unexpected_node_value(value),
1347 }
1348 .into());
1349 }
1350 };
1351 let flatten_ctx = $ctx
1353 .flatten_ctx()
1354 .filter(|fc| fc.scope() == ParserScope::Record);
1355 let accessed = flatten_ctx.map(|fc| fc.accessed_set().clone());
1356 map.iter()
1357 .filter(|(key, _)| {
1358 match &accessed {
1359 Some(acc) => match key {
1360 ObjectKey::String(s) => !acc.has_field(s),
1361 _ => true, },
1363 None => true, }
1365 })
1366 .map(|(key, value)| {
1367 if let Some(fc) = &flatten_ctx {
1369 if let ObjectKey::String(s) = key {
1370 fc.add_field(s);
1371 }
1372 }
1373 Ok((
1374 K::from_object_key(key).map_err(|kind| ParseError {
1375 node_id: $ctx.node_id(),
1376 kind,
1377 })?,
1378 T::parse(&$ctx.at(*value))?,
1379 ))
1380 })
1381 .collect::<Result<_, _>>()
1382 }
1383 }};
1384}
1385
1386impl<'doc, K, T> ParseDocument<'doc> for Map<K, T>
1387where
1388 K: ParseObjectKey<'doc>,
1389 T: ParseDocument<'doc>,
1390 T::Error: From<ParseError>,
1391{
1392 type Error = T::Error;
1393
1394 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1395 parse_map!(ctx)
1396 }
1397}
1398
1399impl<'doc, K, T> ParseDocument<'doc> for BTreeMap<K, T>
1400where
1401 K: ParseObjectKey<'doc>,
1402 T: ParseDocument<'doc>,
1403 T::Error: From<ParseError>,
1404{
1405 type Error = T::Error;
1406 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1407 parse_map!(ctx)
1408 }
1409}
1410
1411impl<'doc, K, T> ParseDocument<'doc> for HashMap<K, T>
1412where
1413 K: ParseObjectKey<'doc>,
1414 T: ParseDocument<'doc>,
1415 T::Error: From<ParseError>,
1416{
1417 type Error = T::Error;
1418 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1419 parse_map!(ctx)
1420 }
1421}
1422
1423impl<'doc, K, T> ParseDocument<'doc> for IndexMap<K, T>
1424where
1425 K: ParseObjectKey<'doc>,
1426 T: ParseDocument<'doc>,
1427 T::Error: From<ParseError>,
1428{
1429 type Error = T::Error;
1430 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1431 parse_map!(ctx)
1432 }
1433}
1434
1435impl ParseDocument<'_> for regex::Regex {
1436 type Error = ParseError;
1437
1438 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1439 let pattern: &str = ctx.parse()?;
1440 regex::Regex::new(pattern).map_err(|e| ParseError {
1441 node_id: ctx.node_id(),
1442 kind: ParseErrorKind::InvalidPattern {
1443 kind: format!("regex '{}'", pattern),
1444 reason: e.to_string(),
1445 },
1446 })
1447 }
1448}
1449
1450impl<'doc, T> ParseDocument<'doc> for Option<T>
1457where
1458 T: ParseDocument<'doc>,
1459 T::Error: From<ParseError>,
1460{
1461 type Error = T::Error;
1462
1463 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1464 ctx.parse_union::<Option<T>, T::Error>(VariantRepr::default())?
1465 .variant("some", (T::parse).map(Some))
1466 .variant("none", |ctx: &ParseContext<'_>| {
1467 if ctx.is_null() {
1468 Ok(None)
1469 } else {
1470 Err(ParseError {
1471 node_id: ctx.node_id(),
1472 kind: ParseErrorKind::TypeMismatch {
1473 expected: ValueKind::Null,
1474 actual: ctx.node().content.value_kind().unwrap_or(ValueKind::Null),
1475 },
1476 }
1477 .into())
1478 }
1479 })
1480 .parse()
1481 }
1482}
1483
1484impl<'doc, T, E, Err> ParseDocument<'doc> for Result<T, E>
1490where
1491 T: ParseDocument<'doc, Error = Err>,
1492 E: ParseDocument<'doc, Error = Err>,
1493 Err: From<ParseError>,
1494{
1495 type Error = Err;
1496
1497 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1498 ctx.parse_union::<Self, Self::Error>(VariantRepr::default())?
1499 .variant("ok", (T::parse).map(Ok))
1500 .variant("err", (E::parse).map(Err))
1501 .parse()
1502 }
1503}
1504
1505impl ParseDocument<'_> for crate::data_model::VariantRepr {
1506 type Error = ParseError;
1507
1508 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1509 use crate::data_model::VariantRepr;
1510
1511 if let Ok(value) = ctx.parse::<&str>() {
1513 return match value {
1514 "external" => Ok(VariantRepr::External),
1515 "untagged" => Ok(VariantRepr::Untagged),
1516 _ => Err(ParseError {
1517 node_id: ctx.node_id(),
1518 kind: ParseErrorKind::UnknownVariant(value.to_string()),
1519 }),
1520 };
1521 }
1522
1523 let rec = ctx.parse_record()?;
1525
1526 let tag = rec.parse_field_optional::<String>("tag")?;
1527 let content = rec.parse_field_optional::<String>("content")?;
1528
1529 rec.allow_unknown_fields()?;
1530
1531 match (tag, content) {
1532 (Some(tag), Some(content)) => Ok(VariantRepr::Adjacent { tag, content }),
1533 (Some(tag), None) => Ok(VariantRepr::Internal { tag }),
1534 (None, None) => Ok(VariantRepr::External),
1535 (None, Some(_)) => Err(ParseError {
1536 node_id: ctx.node_id(),
1537 kind: ParseErrorKind::MissingField(
1538 "tag (required when content is present)".to_string(),
1539 ),
1540 }),
1541 }
1542 }
1543}
1544
1545impl<'doc> ParseDocument<'doc> for () {
1546 type Error = ParseError;
1547 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1548 ctx.parse_tuple()?.finish()
1549 }
1550}
1551
1552impl<'doc> ParseDocument<'doc> for NodeId {
1553 type Error = ParseError;
1554 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1555 Ok(ctx.node_id())
1556 }
1557}
1558
1559pub trait DocumentParser<'doc> {
1560 type Output;
1561 type Error;
1562 fn parse(&mut self, ctx: &ParseContext<'doc>) -> Result<Self::Output, Self::Error>;
1563}
1564
1565pub struct AlwaysParser<T, E>(T, PhantomData<E>);
1566
1567impl<T, E> AlwaysParser<T, E> {
1568 pub fn new(value: T) -> AlwaysParser<T, E> {
1569 Self(value, PhantomData)
1570 }
1571}
1572
1573impl<'doc, T, E> DocumentParser<'doc> for AlwaysParser<T, E>
1574where
1575 T: Clone,
1576{
1577 type Output = T;
1578 type Error = E;
1579 fn parse(&mut self, _ctx: &ParseContext<'doc>) -> Result<Self::Output, Self::Error> {
1580 Ok(self.0.clone())
1581 }
1582}
1583
1584impl<'doc, T, F, E> DocumentParser<'doc> for F
1585where
1586 F: FnMut(&ParseContext<'doc>) -> Result<T, E>,
1587{
1588 type Output = T;
1589 type Error = E;
1590 fn parse(&mut self, ctx: &ParseContext<'doc>) -> Result<Self::Output, Self::Error> {
1591 (*self)(ctx)
1592 }
1593}
1594
1595pub struct LiteralParser<T>(pub T);
1596
1597impl<'doc, T, E> DocumentParser<'doc> for LiteralParser<T>
1598where
1599 T: ParseDocument<'doc, Error = E> + PartialEq + core::fmt::Debug,
1600 E: From<ParseError>,
1601{
1602 type Output = T;
1603 type Error = E;
1604 fn parse(&mut self, ctx: &ParseContext<'doc>) -> Result<Self::Output, Self::Error> {
1605 let value: T = ctx.parse::<T>()?;
1606 if value == self.0 {
1607 Ok(value)
1608 } else {
1609 Err(ParseError {
1610 node_id: ctx.node_id(),
1611 kind: ParseErrorKind::LiteralMismatch {
1612 expected: format!("{:?}", self.0),
1613 actual: format!("{:?}", value),
1614 },
1615 }
1616 .into())
1617 }
1618 }
1619}
1620
1621pub struct VariantLiteralParser(pub &'static str);
1627
1628impl<'doc> DocumentParser<'doc> for VariantLiteralParser {
1629 type Output = &'static str;
1630 type Error = ParseError;
1631 fn parse(&mut self, ctx: &ParseContext<'doc>) -> Result<Self::Output, Self::Error> {
1632 let value: &str = ctx.parse()?;
1633 if value == self.0 {
1634 Ok(self.0)
1635 } else {
1636 Err(ParseError {
1637 node_id: ctx.node_id(),
1638 kind: ParseErrorKind::UnknownVariant(value.to_string()),
1639 })
1640 }
1641 }
1642}
1643
1644pub struct MapParser<T, F> {
1645 parser: T,
1646 mapper: F,
1647}
1648
1649impl<'doc, T, O, F> DocumentParser<'doc> for MapParser<T, F>
1650where
1651 T: DocumentParser<'doc>,
1652 F: FnMut(T::Output) -> O,
1653{
1654 type Output = O;
1655 type Error = T::Error;
1656 fn parse(&mut self, ctx: &ParseContext<'doc>) -> Result<Self::Output, Self::Error> {
1657 self.parser.parse(ctx).map(|value| (self.mapper)(value))
1658 }
1659}
1660
1661pub struct AndThenParser<T, F> {
1662 parser: T,
1663 mapper: F,
1664}
1665
1666impl<'doc, T, O, F, E> DocumentParser<'doc> for AndThenParser<T, F>
1667where
1668 T: DocumentParser<'doc, Error = E>,
1669 F: Fn(T::Output) -> Result<O, E>,
1670{
1671 type Output = O;
1672 type Error = E;
1673 fn parse(&mut self, ctx: &ParseContext<'doc>) -> Result<Self::Output, Self::Error> {
1674 let value = self.parser.parse(ctx)?;
1675 (self.mapper)(value)
1676 }
1677}
1678
1679pub trait DocumentParserExt<'doc>: DocumentParser<'doc> + Sized {
1680 fn map<O, F>(self, mapper: F) -> MapParser<Self, F>
1681 where
1682 F: Fn(Self::Output) -> O,
1683 {
1684 MapParser {
1685 parser: self,
1686 mapper,
1687 }
1688 }
1689
1690 fn and_then<O, F>(self, mapper: F) -> AndThenParser<Self, F>
1691 where
1692 F: Fn(Self::Output) -> Result<O, Self::Error>,
1693 {
1694 AndThenParser {
1695 parser: self,
1696 mapper,
1697 }
1698 }
1699}
1700
1701impl<'doc, T> DocumentParserExt<'doc> for T where T: DocumentParser<'doc> {}
1702
1703#[cfg(test)]
1704mod tests {
1705 use super::*;
1706 use crate::document::node::NodeValue;
1707 use crate::eure;
1708 use crate::identifier::Identifier;
1709 use crate::text::Text;
1710 use crate::value::ObjectKey;
1711 use num_bigint::BigInt;
1712
1713 fn identifier(s: &str) -> Identifier {
1714 s.parse().unwrap()
1715 }
1716
1717 fn create_record_with_variant(
1719 field_name: &str,
1720 value: NodeValue,
1721 variant: &str,
1722 ) -> EureDocument {
1723 let mut doc = EureDocument::new();
1724 let root_id = doc.get_root_id();
1725
1726 let field_id = doc
1728 .add_map_child(ObjectKey::String(field_name.to_string()), root_id)
1729 .unwrap()
1730 .node_id;
1731 doc.node_mut(field_id).content = value;
1732
1733 let variant_node_id = doc
1735 .add_extension(identifier("variant"), field_id)
1736 .unwrap()
1737 .node_id;
1738 doc.node_mut(variant_node_id).content =
1739 NodeValue::Primitive(PrimitiveValue::Text(Text::plaintext(variant.to_string())));
1740
1741 doc
1742 }
1743
1744 #[test]
1745 fn test_option_some_tagged() {
1746 let doc = create_record_with_variant(
1747 "value",
1748 NodeValue::Primitive(PrimitiveValue::Integer(BigInt::from(42))),
1749 "some",
1750 );
1751 let root_id = doc.get_root_id();
1752 let rec = doc.parse_record(root_id).unwrap();
1753 let value: Option<i32> = rec.parse_field("value").unwrap();
1754 assert_eq!(value, Some(42));
1755 }
1756
1757 #[test]
1758 fn test_option_none_tagged() {
1759 let doc =
1760 create_record_with_variant("value", NodeValue::Primitive(PrimitiveValue::Null), "none");
1761 let root_id = doc.get_root_id();
1762 let rec = doc.parse_record(root_id).unwrap();
1763 let value: Option<i32> = rec.parse_field("value").unwrap();
1764 assert_eq!(value, None);
1765 }
1766
1767 #[test]
1768 fn test_option_some_untagged() {
1769 let doc = eure!({ value = 42 });
1771 let root_id = doc.get_root_id();
1772 let rec = doc.parse_record(root_id).unwrap();
1773 let value: Option<i32> = rec.parse_field("value").unwrap();
1774 assert_eq!(value, Some(42));
1775 }
1776
1777 #[test]
1778 fn test_option_none_untagged() {
1779 let doc = eure!({ value = null });
1781 let root_id = doc.get_root_id();
1782 let rec = doc.parse_record(root_id).unwrap();
1783 let value: Option<i32> = rec.parse_field("value").unwrap();
1784 assert_eq!(value, None);
1785 }
1786
1787 #[test]
1788 fn test_result_ok_tagged() {
1789 let doc = create_record_with_variant(
1790 "value",
1791 NodeValue::Primitive(PrimitiveValue::Integer(BigInt::from(42))),
1792 "ok",
1793 );
1794 let root_id = doc.get_root_id();
1795 let rec = doc.parse_record(root_id).unwrap();
1796 let value: Result<i32, String> = rec.parse_field("value").unwrap();
1797 assert_eq!(value, Ok(42));
1798 }
1799
1800 #[test]
1801 fn test_result_err_tagged() {
1802 let doc = create_record_with_variant(
1803 "value",
1804 NodeValue::Primitive(PrimitiveValue::Text(Text::plaintext(
1805 "error message".to_string(),
1806 ))),
1807 "err",
1808 );
1809 let root_id = doc.get_root_id();
1810 let rec = doc.parse_record(root_id).unwrap();
1811 let value: Result<i32, String> = rec.parse_field("value").unwrap();
1812 assert_eq!(value, Err("error message".to_string()));
1813 }
1814
1815 #[test]
1816 fn test_nested_result_option_ok_some() {
1817 let doc = create_record_with_variant(
1819 "value",
1820 NodeValue::Primitive(PrimitiveValue::Integer(BigInt::from(42))),
1821 "ok.some",
1822 );
1823 let root_id = doc.get_root_id();
1824 let rec = doc.parse_record(root_id).unwrap();
1825 let value: Result<Option<i32>, String> = rec.parse_field("value").unwrap();
1826 assert_eq!(value, Ok(Some(42)));
1827 }
1828
1829 #[test]
1830 fn test_nested_result_option_ok_none() {
1831 let doc = create_record_with_variant(
1833 "value",
1834 NodeValue::Primitive(PrimitiveValue::Null),
1835 "ok.none",
1836 );
1837 let root_id = doc.get_root_id();
1838 let rec = doc.parse_record(root_id).unwrap();
1839 let value: Result<Option<i32>, String> = rec.parse_field("value").unwrap();
1840 assert_eq!(value, Ok(None));
1841 }
1842
1843 #[test]
1844 fn test_nested_result_option_err() {
1845 let doc = create_record_with_variant(
1847 "value",
1848 NodeValue::Primitive(PrimitiveValue::Text(Text::plaintext("error".to_string()))),
1849 "err",
1850 );
1851 let root_id = doc.get_root_id();
1852 let rec = doc.parse_record(root_id).unwrap();
1853 let value: Result<Option<i32>, String> = rec.parse_field("value").unwrap();
1854 assert_eq!(value, Err("error".to_string()));
1855 }
1856
1857 #[test]
1858 fn test_deeply_nested_option_option() {
1859 let doc = create_record_with_variant(
1861 "value",
1862 NodeValue::Primitive(PrimitiveValue::Integer(BigInt::from(42))),
1863 "some.some",
1864 );
1865 let root_id = doc.get_root_id();
1866 let rec = doc.parse_record(root_id).unwrap();
1867 let value: Option<Option<i32>> = rec.parse_field("value").unwrap();
1868 assert_eq!(value, Some(Some(42)));
1869 }
1870
1871 #[test]
1872 fn test_deeply_nested_option_none() {
1873 let doc = create_record_with_variant(
1875 "value",
1876 NodeValue::Primitive(PrimitiveValue::Null),
1877 "some.none",
1878 );
1879 let root_id = doc.get_root_id();
1880 let rec = doc.parse_record(root_id).unwrap();
1881 let value: Option<Option<i32>> = rec.parse_field("value").unwrap();
1882 assert_eq!(value, Some(None));
1883 }
1884
1885 #[test]
1886 fn test_outer_none() {
1887 let doc =
1889 create_record_with_variant("value", NodeValue::Primitive(PrimitiveValue::Null), "none");
1890 let root_id = doc.get_root_id();
1891 let rec = doc.parse_record(root_id).unwrap();
1892 let value: Option<Option<i32>> = rec.parse_field("value").unwrap();
1893 assert_eq!(value, None);
1894 }
1895
1896 #[test]
1903 fn test_flatten_indexmap_marks_fields_as_accessed() {
1904 use indexmap::IndexMap;
1905
1906 let doc = eure!({
1907 name = "test"
1908 foo = "bar"
1909 baz = "qux"
1910 });
1911
1912 let root_id = doc.get_root_id();
1913 let rec = doc.parse_record(root_id).unwrap();
1914
1915 let _name: String = rec.parse_field("name").unwrap();
1917
1918 let extra: IndexMap<String, String> = rec.flatten().parse().unwrap();
1920
1921 assert_eq!(extra.get("foo"), Some(&"bar".to_string()));
1923 assert_eq!(extra.get("baz"), Some(&"qux".to_string()));
1924
1925 rec.deny_unknown_fields().unwrap();
1928 }
1929}