1extern crate alloc;
4
5pub mod object_key;
6pub mod record;
7pub mod tuple;
8pub mod union;
9pub mod variant_path;
10
11use alloc::borrow::{Cow, ToOwned};
12use indexmap::{IndexMap, IndexSet};
13pub use object_key::ParseObjectKey;
14pub use record::RecordParser;
15pub use tuple::TupleParser;
16pub use union::UnionParser;
17pub use variant_path::VariantPath;
18use alloc::format;
21use alloc::rc::Rc;
22use core::cell::RefCell;
23use num_bigint::BigInt;
24
25use core::marker::PhantomData;
26use std::collections::{BTreeMap, HashMap, HashSet};
27
28use crate::{
29 data_model::VariantRepr,
30 document::node::{Node, NodeArray},
31 identifier::IdentifierError,
32 prelude_internal::*,
33 value::ValueKind,
34};
35
36#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
48pub enum UnionTagMode {
49 #[default]
56 Eure,
57
58 Repr,
65}
66
67pub type AccessedSnapshot = (HashSet<String>, HashSet<Identifier>);
73
74#[derive(Debug, Clone)]
91pub struct AccessedSet(Rc<RefCell<Vec<AccessedSnapshot>>>);
92
93impl AccessedSet {
94 pub fn new() -> Self {
96 Self(Rc::new(RefCell::new(vec![(
98 HashSet::new(),
99 HashSet::new(),
100 )])))
101 }
102
103 pub fn add_field(&self, field: impl Into<String>) {
105 self.0
106 .borrow_mut()
107 .last_mut()
108 .unwrap()
109 .0
110 .insert(field.into());
111 }
112
113 pub fn add_ext(&self, ext: Identifier) {
115 self.0.borrow_mut().last_mut().unwrap().1.insert(ext);
116 }
117
118 pub fn has_field(&self, field: &str) -> bool {
120 self.0.borrow().last().unwrap().0.contains(field)
121 }
122
123 pub fn has_ext(&self, ext: &Identifier) -> bool {
125 self.0.borrow().last().unwrap().1.contains(ext)
126 }
127
128 pub fn get_accessed_exts(&self) -> HashSet<Identifier> {
130 self.0.borrow().last().unwrap().1.clone()
131 }
132
133 pub fn push_snapshot(&self) {
136 let mut stack = self.0.borrow_mut();
137 let snapshot = stack.last().unwrap().clone();
138 let len = stack.len();
139 stack.insert(len - 1, snapshot);
140 }
142
143 pub fn restore_to_current_snapshot(&self) {
146 let mut stack = self.0.borrow_mut();
147 if stack.len() >= 2 {
148 let snapshot = stack[stack.len() - 2].clone();
149 *stack.last_mut().unwrap() = snapshot;
150 }
151 }
152
153 pub fn capture_current_state(&self) -> AccessedSnapshot {
155 self.0.borrow().last().unwrap().clone()
156 }
157
158 pub fn restore_to_state(&self, state: AccessedSnapshot) {
160 *self.0.borrow_mut().last_mut().unwrap() = state;
161 }
162
163 pub fn pop_and_restore(&self) {
166 let mut stack = self.0.borrow_mut();
167 if stack.len() >= 2 {
168 stack.pop(); }
170 }
171
172 pub fn pop_without_restore(&self) {
175 let mut stack = self.0.borrow_mut();
176 if stack.len() >= 2 {
177 let snapshot_idx = stack.len() - 2;
178 stack.remove(snapshot_idx); }
180 }
181}
182
183impl Default for AccessedSet {
184 fn default() -> Self {
185 Self::new()
186 }
187}
188
189#[derive(Debug, Clone, Copy, PartialEq, Eq)]
197pub enum ParserScope {
198 Record,
200 Extension,
202}
203
204#[derive(Debug, Clone)]
231pub struct FlattenContext {
232 accessed: AccessedSet,
233 scope: ParserScope,
234}
235
236impl FlattenContext {
237 pub fn new(accessed: AccessedSet, scope: ParserScope) -> Self {
239 Self { accessed, scope }
240 }
241
242 pub fn scope(&self) -> ParserScope {
244 self.scope
245 }
246
247 pub fn accessed_set(&self) -> &AccessedSet {
249 &self.accessed
250 }
251
252 pub fn add_field(&self, field: impl Into<String>) {
254 self.accessed.add_field(field);
255 }
256
257 pub fn add_ext(&self, ext: Identifier) {
259 self.accessed.add_ext(ext);
260 }
261
262 pub fn has_field(&self, field: &str) -> bool {
264 self.accessed.has_field(field)
265 }
266
267 pub fn has_ext(&self, ext: &Identifier) -> bool {
269 self.accessed.has_ext(ext)
270 }
271
272 pub fn push_snapshot(&self) {
274 self.accessed.push_snapshot();
275 }
276
277 pub fn restore_to_current_snapshot(&self) {
279 self.accessed.restore_to_current_snapshot();
280 }
281
282 pub fn capture_current_state(&self) -> AccessedSnapshot {
284 self.accessed.capture_current_state()
285 }
286
287 pub fn restore_to_state(&self, state: AccessedSnapshot) {
289 self.accessed.restore_to_state(state);
290 }
291
292 pub fn pop_and_restore(&self) {
294 self.accessed.pop_and_restore();
295 }
296
297 pub fn pop_without_restore(&self) {
299 self.accessed.pop_without_restore();
300 }
301}
302
303#[derive(Clone, Debug)]
312pub struct ParseContext<'doc> {
313 doc: &'doc EureDocument,
314 node_id: NodeId,
315 variant_path: Option<VariantPath>,
316 flatten_ctx: Option<FlattenContext>,
320 union_tag_mode: UnionTagMode,
322 accessed: AccessedSet,
324}
325
326impl<'doc> ParseContext<'doc> {
327 pub fn new(doc: &'doc EureDocument, node_id: NodeId) -> Self {
329 Self {
330 doc,
331 node_id,
332 variant_path: None,
333 flatten_ctx: None,
334 union_tag_mode: UnionTagMode::default(),
335 accessed: AccessedSet::new(),
336 }
337 }
338
339 pub fn with_union_tag_mode(
341 doc: &'doc EureDocument,
342 node_id: NodeId,
343 mode: UnionTagMode,
344 ) -> Self {
345 Self {
346 doc,
347 node_id,
348 variant_path: None,
349 flatten_ctx: None,
350 union_tag_mode: mode,
351 accessed: AccessedSet::new(),
352 }
353 }
354
355 pub fn with_flatten_ctx(
361 doc: &'doc EureDocument,
362 node_id: NodeId,
363 flatten_ctx: FlattenContext,
364 mode: UnionTagMode,
365 ) -> Self {
366 let accessed = flatten_ctx.accessed_set().clone();
368 Self {
369 doc,
370 node_id,
371 variant_path: None,
372 flatten_ctx: Some(flatten_ctx),
373 union_tag_mode: mode,
374 accessed,
375 }
376 }
377
378 pub fn flatten_ctx(&self) -> Option<&FlattenContext> {
380 self.flatten_ctx.as_ref()
381 }
382
383 pub fn is_flattened(&self) -> bool {
387 self.flatten_ctx.is_some()
388 }
389
390 pub fn parser_scope(&self) -> Option<ParserScope> {
396 self.flatten_ctx.as_ref().map(|fc| fc.scope())
397 }
398
399 pub fn node_id(&self) -> NodeId {
401 self.node_id
402 }
403
404 pub(crate) fn doc(&self) -> &'doc EureDocument {
406 self.doc
407 }
408
409 pub fn node(&self) -> &'doc Node {
411 self.doc.node(self.node_id)
412 }
413
414 pub(crate) fn at(&self, node_id: NodeId) -> Self {
416 Self {
417 doc: self.doc,
418 node_id,
419 variant_path: None,
420 flatten_ctx: None,
421 union_tag_mode: self.union_tag_mode,
422 accessed: AccessedSet::new(),
423 }
424 }
425
426 pub fn flatten(&self) -> Self {
461 let flatten_ctx = match &self.flatten_ctx {
466 Some(fc) => FlattenContext::new(fc.accessed_set().clone(), ParserScope::Record),
467 None => FlattenContext::new(self.accessed.clone(), ParserScope::Record),
468 };
469 Self {
470 doc: self.doc,
471 node_id: self.node_id,
472 variant_path: self.variant_path.clone(),
473 flatten_ctx: Some(flatten_ctx),
474 union_tag_mode: self.union_tag_mode,
475 accessed: self.accessed.clone(),
476 }
477 }
478
479 pub fn union_tag_mode(&self) -> UnionTagMode {
481 self.union_tag_mode
482 }
483
484 pub fn parse<T: FromEure<'doc, T>>(&self) -> Result<T, T::Error> {
486 T::parse(self)
487 }
488
489 pub fn parse_via<M, T>(&self) -> Result<T, M::Error>
494 where
495 M: FromEure<'doc, T>,
496 {
497 M::parse(self)
498 }
499
500 pub fn parse_with<T: DocumentParser<'doc>>(
501 &self,
502 mut parser: T,
503 ) -> Result<T::Output, T::Error> {
504 parser.parse(self)
505 }
506
507 pub fn parse_union<T, E>(&self, repr: VariantRepr) -> Result<UnionParser<'doc, '_, T, E>, E>
515 where
516 E: From<ParseError>,
517 {
518 UnionParser::new(self, repr).map_err(Into::into)
519 }
520
521 pub fn parse_record(&self) -> Result<RecordParser<'doc>, ParseError> {
525 self.ensure_no_variant_path()?;
526 RecordParser::new(self)
527 }
528
529 pub fn parse_tuple(&self) -> Result<TupleParser<'doc>, ParseError> {
533 self.ensure_no_variant_path()?;
534 TupleParser::new(self)
535 }
536
537 pub fn parse_primitive(&self) -> Result<&'doc PrimitiveValue, ParseError> {
542 self.ensure_no_variant_path()?;
543 match &self.node().content {
544 NodeValue::Primitive(p) => Ok(p),
545 _ => Err(ParseError {
546 node_id: self.node_id(),
547 kind: ParseErrorKind::NotPrimitive {
548 actual: self.node().content.value_kind(),
549 },
550 }),
551 }
552 }
553
554 pub(crate) fn accessed(&self) -> &AccessedSet {
560 &self.accessed
561 }
562
563 pub fn node_subtree_to_document_excluding_accessed(&self) -> EureDocument {
570 let mut doc = self.doc.node_subtree_to_document(self.node_id);
571 let root_id = doc.get_root_id();
572 let accessed_exts = self.accessed.get_accessed_exts();
573 for ext in accessed_exts {
574 doc.node_mut(root_id).extensions.remove_fast(&ext);
575 }
576 doc
577 }
578
579 fn mark_ext_accessed(&self, ident: Identifier) {
581 self.accessed.add_ext(ident);
582 }
583
584 pub fn parse_ext<T>(&self, name: &str) -> Result<T, T::Error>
588 where
589 T: FromEure<'doc>,
590 T::Error: From<ParseError>,
591 {
592 self.parse_ext_with(name, T::parse)
593 }
594
595 pub fn parse_ext_with<T>(&self, name: &str, mut parser: T) -> Result<T::Output, T::Error>
597 where
598 T: DocumentParser<'doc>,
599 T::Error: From<ParseError>,
600 {
601 let ident: Identifier = name.parse().map_err(|e| ParseError {
602 node_id: self.node_id,
603 kind: ParseErrorKind::InvalidIdentifier(e),
604 })?;
605 self.mark_ext_accessed(ident.clone());
606 let ext_node_id = self
607 .node()
608 .extensions
609 .get(&ident)
610 .ok_or_else(|| ParseError {
611 node_id: self.node_id,
612 kind: ParseErrorKind::MissingExtension(name.to_string()),
613 })?;
614 let ctx = ParseContext::with_union_tag_mode(self.doc, *ext_node_id, self.union_tag_mode);
615 parser.parse(&ctx)
616 }
617
618 pub fn parse_ext_optional<T>(&self, name: &str) -> Result<Option<T>, T::Error>
622 where
623 T: FromEure<'doc>,
624 T::Error: From<ParseError>,
625 {
626 self.parse_ext_optional_with(name, T::parse)
627 }
628
629 pub fn parse_ext_optional_with<T>(
633 &self,
634 name: &str,
635 mut parser: T,
636 ) -> Result<Option<T::Output>, T::Error>
637 where
638 T: DocumentParser<'doc>,
639 T::Error: From<ParseError>,
640 {
641 let ident: Identifier = name.parse().map_err(|e| ParseError {
642 node_id: self.node_id,
643 kind: ParseErrorKind::InvalidIdentifier(e),
644 })?;
645 self.mark_ext_accessed(ident.clone());
646 match self.node().extensions.get(&ident) {
647 Some(ext_node_id) => {
648 let ctx =
649 ParseContext::with_union_tag_mode(self.doc, *ext_node_id, self.union_tag_mode);
650 Ok(Some(parser.parse(&ctx)?))
651 }
652 None => Ok(None),
653 }
654 }
655
656 pub fn ext(&self, name: &str) -> Result<ParseContext<'doc>, ParseError> {
661 let ident: Identifier = name.parse().map_err(|e| ParseError {
662 node_id: self.node_id,
663 kind: ParseErrorKind::InvalidIdentifier(e),
664 })?;
665 self.mark_ext_accessed(ident.clone());
666 let ext_node_id =
667 self.node()
668 .extensions
669 .get(&ident)
670 .copied()
671 .ok_or_else(|| ParseError {
672 node_id: self.node_id,
673 kind: ParseErrorKind::MissingExtension(name.to_string()),
674 })?;
675 Ok(ParseContext::with_union_tag_mode(
676 self.doc,
677 ext_node_id,
678 self.union_tag_mode,
679 ))
680 }
681
682 pub fn ext_optional(&self, name: &str) -> Option<ParseContext<'doc>> {
687 let ident: Identifier = name.parse().ok()?;
688 self.mark_ext_accessed(ident.clone());
689 self.node().extensions.get(&ident).map(|&node_id| {
690 ParseContext::with_union_tag_mode(self.doc, node_id, self.union_tag_mode)
691 })
692 }
693
694 pub fn deny_unknown_extensions(&self) -> Result<(), ParseError> {
699 if self.flatten_ctx.is_some() {
701 return Ok(());
702 }
703
704 for (ident, _) in self.node().extensions.iter() {
706 if !self.accessed.has_ext(ident) {
707 return Err(ParseError {
708 node_id: self.node_id,
709 kind: ParseErrorKind::UnknownExtension(ident.clone()),
710 });
711 }
712 }
713 Ok(())
714 }
715
716 pub fn unknown_extensions(
720 &self,
721 ) -> impl Iterator<Item = (&'doc Identifier, ParseContext<'doc>)> + '_ {
722 let doc = self.doc;
723 let mode = self.union_tag_mode;
724 let accessed = self.accessed.clone();
726 self.node()
727 .extensions
728 .iter()
729 .filter_map(move |(ident, &node_id)| {
730 if !accessed.has_ext(ident) {
731 Some((ident, ParseContext::with_union_tag_mode(doc, node_id, mode)))
732 } else {
733 None
734 }
735 })
736 }
737
738 pub fn flatten_ext(&self) -> ParseContext<'doc> {
764 let flatten_ctx = match &self.flatten_ctx {
769 Some(fc) => FlattenContext::new(fc.accessed_set().clone(), ParserScope::Extension),
770 None => FlattenContext::new(self.accessed.clone(), ParserScope::Extension),
771 };
772
773 ParseContext::with_flatten_ctx(self.doc, self.node_id, flatten_ctx, self.union_tag_mode)
774 }
775
776 pub fn is_null(&self) -> bool {
778 matches!(
779 &self.node().content,
780 NodeValue::Primitive(PrimitiveValue::Null)
781 )
782 }
783
784 pub(crate) fn with_variant_rest(&self, rest: Option<VariantPath>) -> Self {
786 Self {
787 doc: self.doc,
788 node_id: self.node_id,
789 variant_path: rest,
790 flatten_ctx: self.flatten_ctx.clone(),
791 union_tag_mode: self.union_tag_mode,
792 accessed: self.accessed.clone(),
793 }
794 }
795
796 pub(crate) fn variant_path(&self) -> Option<&VariantPath> {
798 self.variant_path.as_ref()
799 }
800
801 fn ensure_no_variant_path(&self) -> Result<(), ParseError> {
803 if let Some(vp) = &self.variant_path
804 && !vp.is_empty()
805 {
806 return Err(ParseError {
807 node_id: self.node_id,
808 kind: ParseErrorKind::UnexpectedVariantPath(vp.clone()),
809 });
810 }
811 Ok(())
812 }
813
814 fn unexpected_kind(&self, expected: ValueKind) -> ParseError {
815 ParseError {
816 node_id: self.node_id(),
817 kind: ParseErrorKind::TypeMismatch {
818 expected,
819 actual: self.node().content.value_kind(),
820 },
821 }
822 }
823}
824
825#[diagnostic::on_unimplemented(
877 message = "`{Self}` cannot be parsed from Eure document",
878 label = "this type does not implement `FromEure`",
879 note = "consider adding `#[derive(FromEure)]` to `{Self}`"
880)]
881pub trait FromEure<'doc, T = Self>: Sized {
882 type Error;
884
885 fn parse(ctx: &ParseContext<'doc>) -> Result<T, Self::Error>;
887}
888
889#[derive(Debug, thiserror::Error, Clone, PartialEq)]
890#[error("parse error: {kind}")]
891pub struct ParseError {
892 pub node_id: NodeId,
893 pub kind: ParseErrorKind,
894}
895
896#[derive(Debug, thiserror::Error, Clone, PartialEq)]
898pub enum ParseErrorKind {
899 #[error("unexpected uninitialized value")]
901 UnexpectedHole,
902
903 #[error("type mismatch: expected {expected}, got {actual}")]
905 TypeMismatch {
906 expected: ValueKind,
907 actual: ValueKind,
908 },
909
910 #[error("missing field: {0}")]
912 MissingField(String),
913
914 #[error("missing extension: ${0}")]
916 MissingExtension(String),
917
918 #[error("unknown variant: {0}")]
920 UnknownVariant(String),
921
922 #[error("value out of range: {0}")]
924 OutOfRange(String),
925
926 #[error("invalid {kind}: {reason}")]
932 InvalidPattern { kind: String, reason: String },
933
934 #[error("at {path}: {source}")]
936 Nested {
937 path: String,
938 #[source]
939 source: Box<ParseErrorKind>,
940 },
941
942 #[error("invalid identifier: {0}")]
944 InvalidIdentifier(#[from] IdentifierError),
945
946 #[error("unexpected tuple length: expected {expected}, got {actual}")]
948 UnexpectedTupleLength { expected: usize, actual: usize },
949
950 #[error("unknown field: {0}")]
952 UnknownField(String),
953
954 #[error("unknown extension: ${0}")]
956 UnknownExtension(Identifier),
957
958 #[error("invalid key type in record: expected string key, got {0:?}")]
960 InvalidKeyType(crate::value::ObjectKey),
961
962 #[error("no matching variant{}", variant.as_ref().map(|v| format!(" (variant: {})", v)).unwrap_or_default())]
964 NoMatchingVariant {
965 variant: Option<String>,
967 },
968
969 #[error("conflicting variant tags: $variant = {explicit}, repr = {repr}")]
971 ConflictingVariantTags { explicit: String, repr: String },
972
973 #[error("ambiguous union: {0:?}")]
975 AmbiguousUnion(Vec<String>),
976
977 #[error("literal value mismatch: expected {expected}, got {actual}")]
979 LiteralMismatch { expected: String, actual: String },
981
982 #[error("unexpected variant path: {0}")]
984 UnexpectedVariantPath(VariantPath),
985
986 #[error("$variant must be a string, got {0}")]
988 InvalidVariantType(ValueKind),
989
990 #[error("invalid $variant path syntax: {0}")]
992 InvalidVariantPath(String),
993
994 #[error(
997 "cannot parse record in extension scope: use #[eure(flatten)] instead of #[eure(flatten_ext)]"
998 )]
999 RecordInExtensionScope,
1000
1001 #[error("unexpected array length: expected {expected}, got {actual}")]
1003 UnexpectedArrayLength { expected: usize, actual: usize },
1004
1005 #[error("expected primitive value, got {actual}")]
1007 NotPrimitive { actual: ValueKind },
1008}
1009
1010impl ParseErrorKind {
1011 pub fn at(self, path: impl Into<String>) -> Self {
1013 ParseErrorKind::Nested {
1014 path: path.into(),
1015 source: Box::new(self),
1016 }
1017 }
1018}
1019
1020impl<'doc> EureDocument {
1021 pub fn parse<T: FromEure<'doc, T>>(&'doc self, node_id: NodeId) -> Result<T, T::Error> {
1023 self.parse_with(node_id, T::parse)
1024 }
1025
1026 pub fn parse_via<M, T>(&'doc self, node_id: NodeId) -> Result<T, M::Error>
1031 where
1032 M: FromEure<'doc, T>,
1033 {
1034 let ctx = self.parse_context(node_id);
1035 M::parse(&ctx)
1036 }
1037
1038 pub fn parse_with<T: DocumentParser<'doc>>(
1039 &'doc self,
1040 node_id: NodeId,
1041 mut parser: T,
1042 ) -> Result<T::Output, T::Error> {
1043 parser.parse(&self.parse_context(node_id))
1044 }
1045
1046 pub fn parse_context(&'doc self, node_id: NodeId) -> ParseContext<'doc> {
1048 ParseContext::new(self, node_id)
1049 }
1050
1051 pub fn parse_record(&'doc self, node_id: NodeId) -> Result<RecordParser<'doc>, ParseError> {
1055 RecordParser::from_doc_and_node(self, node_id)
1056 }
1057
1058 pub fn parse_extension_context(&'doc self, node_id: NodeId) -> ParseContext<'doc> {
1063 ParseContext::new(self, node_id)
1064 }
1065
1066 pub fn parse_tuple(&'doc self, node_id: NodeId) -> Result<TupleParser<'doc>, ParseError> {
1070 TupleParser::from_doc_and_node(self, node_id)
1071 }
1072}
1073
1074impl<'doc> FromEure<'doc> for EureDocument {
1075 type Error = ParseError;
1076
1077 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1078 Ok(ctx.doc().node_subtree_to_document(ctx.node_id()))
1079 }
1080}
1081
1082impl<'doc> FromEure<'doc> for &'doc str {
1083 type Error = ParseError;
1084
1085 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1086 if let PrimitiveValue::Text(text) = ctx.parse_primitive()? {
1087 return Ok(text.as_str());
1088 }
1089 Err(ctx.unexpected_kind(ValueKind::Text))
1090 }
1091}
1092
1093impl FromEure<'_> for String {
1094 type Error = ParseError;
1095
1096 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1097 ctx.parse::<&str>().map(String::from)
1098 }
1099}
1100
1101#[diagnostic::do_not_recommend]
1102impl<'doc, T> FromEure<'doc> for Cow<'static, T>
1103where
1104 T: ToOwned + ?Sized,
1105 T::Owned: FromEure<'doc>,
1106{
1107 type Error = <T::Owned as FromEure<'doc>>::Error;
1108
1109 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1110 <T::Owned as FromEure<'doc>>::parse(ctx).map(Cow::Owned)
1111 }
1112}
1113
1114impl FromEure<'_> for Text {
1115 type Error = ParseError;
1116
1117 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1118 if let PrimitiveValue::Text(text) = ctx.parse_primitive()? {
1119 return Ok(text.clone());
1120 }
1121 Err(ctx.unexpected_kind(ValueKind::Text))
1122 }
1123}
1124
1125impl FromEure<'_> for bool {
1126 type Error = ParseError;
1127
1128 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1129 if let PrimitiveValue::Bool(b) = ctx.parse_primitive()? {
1130 return Ok(*b);
1131 }
1132 Err(ctx.unexpected_kind(ValueKind::Bool))
1133 }
1134}
1135
1136impl FromEure<'_> for BigInt {
1137 type Error = ParseError;
1138
1139 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1140 if let PrimitiveValue::Integer(i) = ctx.parse_primitive()? {
1141 return Ok(i.clone());
1142 }
1143 Err(ctx.unexpected_kind(ValueKind::Integer))
1144 }
1145}
1146
1147impl FromEure<'_> for f32 {
1148 type Error = ParseError;
1149
1150 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1151 if let PrimitiveValue::F32(f) = ctx.parse_primitive()? {
1152 return Ok(*f);
1153 }
1154 Err(ctx.unexpected_kind(ValueKind::F32))
1155 }
1156}
1157
1158impl FromEure<'_> for f64 {
1159 type Error = ParseError;
1160
1161 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1162 match ctx.parse_primitive()? {
1163 PrimitiveValue::F32(f) => Ok(*f as f64),
1164 PrimitiveValue::F64(f) => Ok(*f),
1165 _ => Err(ctx.unexpected_kind(ValueKind::F64)),
1166 }
1167 }
1168}
1169
1170macro_rules! impl_from_eure_int {
1171 ($($ty:ty),*) => {
1172 $(
1173 impl FromEure<'_> for $ty {
1174 type Error = ParseError;
1175
1176 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1177 let value: BigInt = ctx.parse()?;
1178 <$ty>::try_from(&value).map_err(|_| ParseError {
1179 node_id: ctx.node_id(),
1180 kind: ParseErrorKind::OutOfRange(
1181 format!("value {} out of {} range", value, stringify!($ty)),
1182 ),
1183 })
1184 }
1185 }
1186 )*
1187 };
1188}
1189
1190impl_from_eure_int!(
1191 u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize
1192);
1193
1194impl<'doc> FromEure<'doc> for &'doc PrimitiveValue {
1195 type Error = ParseError;
1196
1197 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1198 ctx.parse_primitive()
1199 }
1200}
1201
1202impl FromEure<'_> for PrimitiveValue {
1203 type Error = ParseError;
1204
1205 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1206 ctx.parse::<&PrimitiveValue>().cloned()
1207 }
1208}
1209
1210impl FromEure<'_> for Identifier {
1211 type Error = ParseError;
1212
1213 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1214 if let PrimitiveValue::Text(text) = ctx.parse_primitive()? {
1215 return text
1216 .content
1217 .parse()
1218 .map_err(ParseErrorKind::InvalidIdentifier)
1219 .map_err(|kind| ParseError {
1220 node_id: ctx.node_id(),
1221 kind,
1222 });
1223 }
1224 Err(ctx.unexpected_kind(ValueKind::Text))
1225 }
1226}
1227
1228impl<'doc> FromEure<'doc> for &'doc NodeArray {
1229 type Error = ParseError;
1230
1231 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1232 ctx.ensure_no_variant_path()?;
1233 match &ctx.node().content {
1234 NodeValue::Array(array) => Ok(array),
1235 _ => Err(ctx.unexpected_kind(ValueKind::Array)),
1236 }
1237 }
1238}
1239
1240#[diagnostic::do_not_recommend]
1245impl<'doc, M, T> FromEure<'doc, Vec<T>> for Vec<M>
1246where
1247 M: FromEure<'doc, T>,
1248 M::Error: From<ParseError>,
1249{
1250 type Error = M::Error;
1251
1252 fn parse(ctx: &ParseContext<'doc>) -> Result<Vec<T>, Self::Error> {
1253 ctx.ensure_no_variant_path()?;
1254 match &ctx.node().content {
1255 NodeValue::Array(array) => array
1256 .iter()
1257 .map(|item| M::parse(&ctx.at(*item)))
1258 .collect::<Result<Vec<_>, _>>(),
1259 _ => Err(ctx.unexpected_kind(ValueKind::Array).into()),
1260 }
1261 }
1262}
1263
1264#[diagnostic::do_not_recommend]
1269impl<'doc, M, T, const N: usize> FromEure<'doc, [T; N]> for [M; N]
1270where
1271 M: FromEure<'doc, T>,
1272 M::Error: From<ParseError>,
1273{
1274 type Error = M::Error;
1275
1276 fn parse(ctx: &ParseContext<'doc>) -> Result<[T; N], Self::Error> {
1277 ctx.ensure_no_variant_path()?;
1278 match &ctx.node().content {
1279 NodeValue::Array(array) => {
1280 let node_ids: [NodeId; N] = array.try_into_array().ok_or_else(|| ParseError {
1281 node_id: ctx.node_id(),
1282 kind: ParseErrorKind::UnexpectedArrayLength {
1283 expected: N,
1284 actual: array.len(),
1285 },
1286 })?;
1287 let mut parsed = Vec::with_capacity(N);
1288 for id in node_ids {
1289 parsed.push(M::parse(&ctx.at(id))?);
1290 }
1291 let parsed: [T; N] = parsed
1292 .try_into()
1293 .unwrap_or_else(|_| unreachable!("length was asserted previously"));
1294 Ok(parsed)
1295 }
1296 _ => Err(ctx.unexpected_kind(ValueKind::Array).into()),
1297 }
1298 }
1299}
1300
1301#[diagnostic::do_not_recommend]
1303impl<'doc, M, T> FromEure<'doc, IndexSet<T>> for IndexSet<M>
1304where
1305 M: FromEure<'doc, T>,
1306 T: Eq + std::hash::Hash,
1307 M::Error: From<ParseError>,
1308{
1309 type Error = M::Error;
1310 fn parse(ctx: &ParseContext<'doc>) -> Result<IndexSet<T>, Self::Error> {
1311 ctx.ensure_no_variant_path()?;
1312 match &ctx.node().content {
1313 NodeValue::Array(array) => array
1314 .iter()
1315 .map(|item| M::parse(&ctx.at(*item)))
1316 .collect::<Result<IndexSet<_>, _>>(),
1317 _ => Err(ctx.unexpected_kind(ValueKind::Array).into()),
1318 }
1319 }
1320}
1321
1322macro_rules! parse_tuple {
1323 ($n:expr, $($var:ident),*) => {
1324 #[diagnostic::do_not_recommend]
1325 impl<'doc, $($var),*, Err> FromEure<'doc> for ($($var),*,)
1326 where $($var: FromEure<'doc, Error = Err>),*,
1327 Err: From<ParseError>,
1328 {
1329 type Error = Err;
1330
1331 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1332 ctx.ensure_no_variant_path()?;
1333 let tuple = match &ctx.node().content {
1334 NodeValue::Tuple(tuple) => tuple,
1335 _ => return Err(ctx.unexpected_kind(ValueKind::Tuple).into()),
1336 };
1337 if tuple.len() != $n {
1338 return Err(ParseError { node_id: ctx.node_id(), kind: ParseErrorKind::UnexpectedTupleLength { expected: $n, actual: tuple.len() } }.into());
1339 }
1340 let mut iter = tuple.iter();
1341 Ok(($($var::parse(&ctx.at(*iter.next().unwrap()))?),*,))
1342 }
1343 }
1344 }
1345}
1346
1347parse_tuple!(1, A);
1348parse_tuple!(2, A, B);
1349parse_tuple!(3, A, B, C);
1350parse_tuple!(4, A, B, C, D);
1351parse_tuple!(5, A, B, C, D, E);
1352parse_tuple!(6, A, B, C, D, E, F);
1353parse_tuple!(7, A, B, C, D, E, F, G);
1354parse_tuple!(8, A, B, C, D, E, F, G, H);
1355parse_tuple!(9, A, B, C, D, E, F, G, H, I);
1356parse_tuple!(10, A, B, C, D, E, F, G, H, I, J);
1357parse_tuple!(11, A, B, C, D, E, F, G, H, I, J, K);
1358parse_tuple!(12, A, B, C, D, E, F, G, H, I, J, K, L);
1359parse_tuple!(13, A, B, C, D, E, F, G, H, I, J, K, L, M);
1360parse_tuple!(14, A, B, C, D, E, F, G, H, I, J, K, L, M, N);
1361parse_tuple!(15, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
1362parse_tuple!(16, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
1363
1364macro_rules! parse_map {
1369 ($ctx:ident, $M:ty, $T:ty) => {{
1370 $ctx.ensure_no_variant_path()?;
1371
1372 if $ctx.parser_scope() == Some(ParserScope::Extension) {
1374 let node = $ctx.node();
1376 let flatten_ctx = $ctx.flatten_ctx();
1377 let accessed = flatten_ctx.map(|fc| fc.accessed_set());
1378 node.extensions
1379 .iter()
1380 .filter(|(ident, _)| {
1381 accessed.map_or(true, |a| !a.has_ext(ident))
1383 })
1384 .map(|(ident, &node_id)| {
1385 if let Some(fc) = &flatten_ctx {
1387 fc.add_ext((*ident).clone());
1388 }
1389 Ok((
1390 K::from_extension_ident(ident).map_err(|kind| ParseError {
1391 node_id: $ctx.node_id(),
1392 kind,
1393 })?,
1394 <$M as FromEure<'doc, $T>>::parse(&$ctx.at(node_id))?,
1395 ))
1396 })
1397 .collect::<Result<_, _>>()
1398 } else {
1399 let map = match &$ctx.node().content {
1401 NodeValue::Map(map) => map,
1402 _ => {
1403 return Err($ctx.unexpected_kind(ValueKind::Map).into());
1404 }
1405 };
1406 let flatten_ctx = $ctx
1408 .flatten_ctx()
1409 .filter(|fc| fc.scope() == ParserScope::Record);
1410 let accessed = flatten_ctx.map(|fc| fc.accessed_set().clone());
1411 map.iter()
1412 .filter(|(key, _)| {
1413 match &accessed {
1414 Some(acc) => match key {
1415 ObjectKey::String(s) => !acc.has_field(s),
1416 _ => true, },
1418 None => true, }
1420 })
1421 .map(|(key, value)| {
1422 if let Some(fc) = &flatten_ctx {
1424 if let ObjectKey::String(s) = key {
1425 fc.add_field(s);
1426 }
1427 }
1428 Ok((
1429 K::from_object_key(key).map_err(|kind| ParseError {
1430 node_id: $ctx.node_id(),
1431 kind,
1432 })?,
1433 <$M as FromEure<'doc, $T>>::parse(&$ctx.at(*value))?,
1434 ))
1435 })
1436 .collect::<Result<_, _>>()
1437 }
1438 }};
1439}
1440
1441#[diagnostic::do_not_recommend]
1443impl<'doc, K, M, T> FromEure<'doc, Map<K, T>> for Map<K, M>
1444where
1445 K: ParseObjectKey<'doc>,
1446 M: FromEure<'doc, T>,
1447 M::Error: From<ParseError>,
1448{
1449 type Error = M::Error;
1450
1451 fn parse(ctx: &ParseContext<'doc>) -> Result<Map<K, T>, Self::Error> {
1452 parse_map!(ctx, M, T)
1453 }
1454}
1455
1456#[diagnostic::do_not_recommend]
1458impl<'doc, K, M, T> FromEure<'doc, BTreeMap<K, T>> for BTreeMap<K, M>
1459where
1460 K: ParseObjectKey<'doc>,
1461 M: FromEure<'doc, T>,
1462 M::Error: From<ParseError>,
1463{
1464 type Error = M::Error;
1465 fn parse(ctx: &ParseContext<'doc>) -> Result<BTreeMap<K, T>, Self::Error> {
1466 parse_map!(ctx, M, T)
1467 }
1468}
1469
1470#[diagnostic::do_not_recommend]
1472impl<'doc, K, M, T> FromEure<'doc, HashMap<K, T>> for HashMap<K, M>
1473where
1474 K: ParseObjectKey<'doc>,
1475 M: FromEure<'doc, T>,
1476 M::Error: From<ParseError>,
1477{
1478 type Error = M::Error;
1479 fn parse(ctx: &ParseContext<'doc>) -> Result<HashMap<K, T>, Self::Error> {
1480 parse_map!(ctx, M, T)
1481 }
1482}
1483
1484#[diagnostic::do_not_recommend]
1486impl<'doc, K, M, T> FromEure<'doc, IndexMap<K, T>> for IndexMap<K, M>
1487where
1488 K: ParseObjectKey<'doc>,
1489 M: FromEure<'doc, T>,
1490 M::Error: From<ParseError>,
1491{
1492 type Error = M::Error;
1493 fn parse(ctx: &ParseContext<'doc>) -> Result<IndexMap<K, T>, Self::Error> {
1494 parse_map!(ctx, M, T)
1495 }
1496}
1497
1498impl FromEure<'_> for regex::Regex {
1499 type Error = ParseError;
1500
1501 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1502 let pattern: &str = ctx.parse()?;
1503 regex::Regex::new(pattern).map_err(|e| ParseError {
1504 node_id: ctx.node_id(),
1505 kind: ParseErrorKind::InvalidPattern {
1506 kind: format!("regex '{}'", pattern),
1507 reason: e.to_string(),
1508 },
1509 })
1510 }
1511}
1512
1513#[diagnostic::do_not_recommend]
1523impl<'doc, M, T> FromEure<'doc, Option<T>> for Option<M>
1524where
1525 M: FromEure<'doc, T>,
1526 M::Error: From<ParseError>,
1527{
1528 type Error = M::Error;
1529
1530 fn parse(ctx: &ParseContext<'doc>) -> Result<Option<T>, Self::Error> {
1531 ctx.parse_union::<Option<T>, M::Error>(VariantRepr::default())?
1532 .variant("some", (M::parse).map(Some))
1533 .variant("none", |ctx: &ParseContext<'_>| {
1534 if ctx.is_null() {
1535 Ok(None)
1536 } else {
1537 Err(ParseError {
1538 node_id: ctx.node_id(),
1539 kind: ParseErrorKind::TypeMismatch {
1540 expected: ValueKind::Null,
1541 actual: ctx.node().content.value_kind(),
1542 },
1543 }
1544 .into())
1545 }
1546 })
1547 .parse()
1548 }
1549}
1550
1551#[diagnostic::do_not_recommend]
1560impl<'doc, MT, T, ME, E, Err> FromEure<'doc, Result<T, E>> for Result<MT, ME>
1561where
1562 MT: FromEure<'doc, T, Error = Err>,
1563 ME: FromEure<'doc, E, Error = Err>,
1564 Err: From<ParseError>,
1565{
1566 type Error = Err;
1567
1568 fn parse(ctx: &ParseContext<'doc>) -> Result<Result<T, E>, Self::Error> {
1569 ctx.parse_union::<Result<T, E>, Self::Error>(VariantRepr::default())?
1570 .variant("ok", (MT::parse).map(Ok))
1571 .variant("err", (ME::parse).map(Err))
1572 .parse()
1573 }
1574}
1575
1576impl FromEure<'_> for crate::data_model::VariantRepr {
1577 type Error = ParseError;
1578
1579 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1580 use crate::data_model::VariantRepr;
1581
1582 if let Ok(value) = ctx.parse::<&str>() {
1584 return match value {
1585 "external" => Ok(VariantRepr::External),
1586 "untagged" => Ok(VariantRepr::Untagged),
1587 _ => Err(ParseError {
1588 node_id: ctx.node_id(),
1589 kind: ParseErrorKind::UnknownVariant(value.to_string()),
1590 }),
1591 };
1592 }
1593
1594 let rec = ctx.parse_record()?;
1596
1597 let tag = rec.parse_field_optional::<String>("tag")?;
1598 let content = rec.parse_field_optional::<String>("content")?;
1599
1600 rec.allow_unknown_fields()?;
1601
1602 match (tag, content) {
1603 (Some(tag), Some(content)) => Ok(VariantRepr::Adjacent { tag, content }),
1604 (Some(tag), None) => Ok(VariantRepr::Internal { tag }),
1605 (None, None) => Ok(VariantRepr::External),
1606 (None, Some(_)) => Err(ParseError {
1607 node_id: ctx.node_id(),
1608 kind: ParseErrorKind::MissingField(
1609 "tag (required when content is present)".to_string(),
1610 ),
1611 }),
1612 }
1613 }
1614}
1615
1616#[diagnostic::do_not_recommend]
1617impl<'doc> FromEure<'doc> for () {
1618 type Error = ParseError;
1619 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1620 ctx.parse_tuple()?.finish()
1621 }
1622}
1623
1624impl<'doc> FromEure<'doc> for NodeId {
1625 type Error = ParseError;
1626 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1627 Ok(ctx.node_id())
1628 }
1629}
1630
1631pub trait DocumentParser<'doc> {
1632 type Output;
1633 type Error;
1634 fn parse(&mut self, ctx: &ParseContext<'doc>) -> Result<Self::Output, Self::Error>;
1635}
1636
1637pub struct AlwaysParser<T, E>(T, PhantomData<E>);
1638
1639impl<T, E> AlwaysParser<T, E> {
1640 pub fn new(value: T) -> AlwaysParser<T, E> {
1641 Self(value, PhantomData)
1642 }
1643}
1644
1645impl<'doc, T, E> DocumentParser<'doc> for AlwaysParser<T, E>
1646where
1647 T: Clone,
1648{
1649 type Output = T;
1650 type Error = E;
1651 fn parse(&mut self, _ctx: &ParseContext<'doc>) -> Result<Self::Output, Self::Error> {
1652 Ok(self.0.clone())
1653 }
1654}
1655
1656impl<'doc, T, F, E> DocumentParser<'doc> for F
1657where
1658 F: FnMut(&ParseContext<'doc>) -> Result<T, E>,
1659{
1660 type Output = T;
1661 type Error = E;
1662 fn parse(&mut self, ctx: &ParseContext<'doc>) -> Result<Self::Output, Self::Error> {
1663 (*self)(ctx)
1664 }
1665}
1666
1667pub struct LiteralParser<T>(pub T);
1668
1669impl<'doc, T, E> DocumentParser<'doc> for LiteralParser<T>
1670where
1671 T: FromEure<'doc, Error = E> + PartialEq + core::fmt::Debug,
1672 E: From<ParseError>,
1673{
1674 type Output = T;
1675 type Error = E;
1676 fn parse(&mut self, ctx: &ParseContext<'doc>) -> Result<Self::Output, Self::Error> {
1677 let value: T = ctx.parse::<T>()?;
1678 if value == self.0 {
1679 Ok(value)
1680 } else {
1681 Err(ParseError {
1682 node_id: ctx.node_id(),
1683 kind: ParseErrorKind::LiteralMismatch {
1684 expected: format!("{:?}", self.0),
1685 actual: format!("{:?}", value),
1686 },
1687 }
1688 .into())
1689 }
1690 }
1691}
1692
1693pub struct VariantLiteralParser(pub &'static str);
1699
1700impl<'doc> DocumentParser<'doc> for VariantLiteralParser {
1701 type Output = &'static str;
1702 type Error = ParseError;
1703 fn parse(&mut self, ctx: &ParseContext<'doc>) -> Result<Self::Output, Self::Error> {
1704 let value: &str = ctx.parse()?;
1705 if value == self.0 {
1706 Ok(self.0)
1707 } else {
1708 Err(ParseError {
1709 node_id: ctx.node_id(),
1710 kind: ParseErrorKind::UnknownVariant(value.to_string()),
1711 })
1712 }
1713 }
1714}
1715
1716pub struct MapParser<T, F> {
1717 parser: T,
1718 mapper: F,
1719}
1720
1721impl<'doc, T, O, F> DocumentParser<'doc> for MapParser<T, F>
1722where
1723 T: DocumentParser<'doc>,
1724 F: FnMut(T::Output) -> O,
1725{
1726 type Output = O;
1727 type Error = T::Error;
1728 fn parse(&mut self, ctx: &ParseContext<'doc>) -> Result<Self::Output, Self::Error> {
1729 self.parser.parse(ctx).map(|value| (self.mapper)(value))
1730 }
1731}
1732
1733pub struct AndThenParser<T, F> {
1734 parser: T,
1735 mapper: F,
1736}
1737
1738impl<'doc, T, O, F, E> DocumentParser<'doc> for AndThenParser<T, F>
1739where
1740 T: DocumentParser<'doc, Error = E>,
1741 F: Fn(T::Output) -> Result<O, E>,
1742{
1743 type Output = O;
1744 type Error = E;
1745 fn parse(&mut self, ctx: &ParseContext<'doc>) -> Result<Self::Output, Self::Error> {
1746 let value = self.parser.parse(ctx)?;
1747 (self.mapper)(value)
1748 }
1749}
1750
1751pub trait DocumentParserExt<'doc>: DocumentParser<'doc> + Sized {
1752 fn map<O, F>(self, mapper: F) -> MapParser<Self, F>
1753 where
1754 F: Fn(Self::Output) -> O,
1755 {
1756 MapParser {
1757 parser: self,
1758 mapper,
1759 }
1760 }
1761
1762 fn and_then<O, F>(self, mapper: F) -> AndThenParser<Self, F>
1763 where
1764 F: Fn(Self::Output) -> Result<O, Self::Error>,
1765 {
1766 AndThenParser {
1767 parser: self,
1768 mapper,
1769 }
1770 }
1771}
1772
1773impl<'doc, T> DocumentParserExt<'doc> for T where T: DocumentParser<'doc> {}
1774
1775#[cfg(test)]
1776mod tests {
1777 use super::*;
1778 use crate::document::node::NodeValue;
1779 use crate::eure;
1780 use crate::identifier::Identifier;
1781 use crate::text::Text;
1782 use crate::value::ObjectKey;
1783 use num_bigint::BigInt;
1784
1785 fn identifier(s: &str) -> Identifier {
1786 s.parse().unwrap()
1787 }
1788
1789 fn create_record_with_variant(
1791 field_name: &str,
1792 value: NodeValue,
1793 variant: &str,
1794 ) -> EureDocument {
1795 let mut doc = EureDocument::new();
1796 let root_id = doc.get_root_id();
1797
1798 let field_id = doc
1800 .add_map_child(ObjectKey::String(field_name.to_string()), root_id)
1801 .unwrap()
1802 .node_id;
1803 doc.node_mut(field_id).content = value;
1804
1805 let variant_node_id = doc
1807 .add_extension(identifier("variant"), field_id)
1808 .unwrap()
1809 .node_id;
1810 doc.node_mut(variant_node_id).content =
1811 NodeValue::Primitive(PrimitiveValue::Text(Text::plaintext(variant.to_string())));
1812
1813 doc
1814 }
1815
1816 #[test]
1817 fn test_option_some_tagged() {
1818 let doc = create_record_with_variant(
1819 "value",
1820 NodeValue::Primitive(PrimitiveValue::Integer(BigInt::from(42))),
1821 "some",
1822 );
1823 let root_id = doc.get_root_id();
1824 let rec = doc.parse_record(root_id).unwrap();
1825 let value: Option<i32> = rec.parse_field("value").unwrap();
1826 assert_eq!(value, Some(42));
1827 }
1828
1829 #[test]
1830 fn test_option_none_tagged() {
1831 let doc =
1832 create_record_with_variant("value", NodeValue::Primitive(PrimitiveValue::Null), "none");
1833 let root_id = doc.get_root_id();
1834 let rec = doc.parse_record(root_id).unwrap();
1835 let value: Option<i32> = rec.parse_field("value").unwrap();
1836 assert_eq!(value, None);
1837 }
1838
1839 #[test]
1840 fn test_option_some_untagged() {
1841 let doc = eure!({ value = 42 });
1843 let root_id = doc.get_root_id();
1844 let rec = doc.parse_record(root_id).unwrap();
1845 let value: Option<i32> = rec.parse_field("value").unwrap();
1846 assert_eq!(value, Some(42));
1847 }
1848
1849 #[test]
1850 fn test_option_none_untagged() {
1851 let doc = eure!({ value = null });
1853 let root_id = doc.get_root_id();
1854 let rec = doc.parse_record(root_id).unwrap();
1855 let value: Option<i32> = rec.parse_field("value").unwrap();
1856 assert_eq!(value, None);
1857 }
1858
1859 #[test]
1860 fn test_result_ok_tagged() {
1861 let doc = create_record_with_variant(
1862 "value",
1863 NodeValue::Primitive(PrimitiveValue::Integer(BigInt::from(42))),
1864 "ok",
1865 );
1866 let root_id = doc.get_root_id();
1867 let rec = doc.parse_record(root_id).unwrap();
1868 let value: Result<i32, String> = rec.parse_field("value").unwrap();
1869 assert_eq!(value, Ok(42));
1870 }
1871
1872 #[test]
1873 fn test_result_err_tagged() {
1874 let doc = create_record_with_variant(
1875 "value",
1876 NodeValue::Primitive(PrimitiveValue::Text(Text::plaintext(
1877 "error message".to_string(),
1878 ))),
1879 "err",
1880 );
1881 let root_id = doc.get_root_id();
1882 let rec = doc.parse_record(root_id).unwrap();
1883 let value: Result<i32, String> = rec.parse_field("value").unwrap();
1884 assert_eq!(value, Err("error message".to_string()));
1885 }
1886
1887 #[test]
1888 fn test_nested_result_option_ok_some() {
1889 let doc = create_record_with_variant(
1891 "value",
1892 NodeValue::Primitive(PrimitiveValue::Integer(BigInt::from(42))),
1893 "ok.some",
1894 );
1895 let root_id = doc.get_root_id();
1896 let rec = doc.parse_record(root_id).unwrap();
1897 let value: Result<Option<i32>, String> = rec.parse_field("value").unwrap();
1898 assert_eq!(value, Ok(Some(42)));
1899 }
1900
1901 #[test]
1902 fn test_nested_result_option_ok_none() {
1903 let doc = create_record_with_variant(
1905 "value",
1906 NodeValue::Primitive(PrimitiveValue::Null),
1907 "ok.none",
1908 );
1909 let root_id = doc.get_root_id();
1910 let rec = doc.parse_record(root_id).unwrap();
1911 let value: Result<Option<i32>, String> = rec.parse_field("value").unwrap();
1912 assert_eq!(value, Ok(None));
1913 }
1914
1915 #[test]
1916 fn test_nested_result_option_err() {
1917 let doc = create_record_with_variant(
1919 "value",
1920 NodeValue::Primitive(PrimitiveValue::Text(Text::plaintext("error".to_string()))),
1921 "err",
1922 );
1923 let root_id = doc.get_root_id();
1924 let rec = doc.parse_record(root_id).unwrap();
1925 let value: Result<Option<i32>, String> = rec.parse_field("value").unwrap();
1926 assert_eq!(value, Err("error".to_string()));
1927 }
1928
1929 #[test]
1930 fn test_deeply_nested_option_option() {
1931 let doc = create_record_with_variant(
1933 "value",
1934 NodeValue::Primitive(PrimitiveValue::Integer(BigInt::from(42))),
1935 "some.some",
1936 );
1937 let root_id = doc.get_root_id();
1938 let rec = doc.parse_record(root_id).unwrap();
1939 let value: Option<Option<i32>> = rec.parse_field("value").unwrap();
1940 assert_eq!(value, Some(Some(42)));
1941 }
1942
1943 #[test]
1944 fn test_deeply_nested_option_none() {
1945 let doc = create_record_with_variant(
1947 "value",
1948 NodeValue::Primitive(PrimitiveValue::Null),
1949 "some.none",
1950 );
1951 let root_id = doc.get_root_id();
1952 let rec = doc.parse_record(root_id).unwrap();
1953 let value: Option<Option<i32>> = rec.parse_field("value").unwrap();
1954 assert_eq!(value, Some(None));
1955 }
1956
1957 #[test]
1958 fn test_outer_none() {
1959 let doc =
1961 create_record_with_variant("value", NodeValue::Primitive(PrimitiveValue::Null), "none");
1962 let root_id = doc.get_root_id();
1963 let rec = doc.parse_record(root_id).unwrap();
1964 let value: Option<Option<i32>> = rec.parse_field("value").unwrap();
1965 assert_eq!(value, None);
1966 }
1967
1968 #[test]
1975 fn test_flatten_indexmap_marks_fields_as_accessed() {
1976 use indexmap::IndexMap;
1977
1978 let doc = eure!({
1979 name = "test"
1980 foo = "bar"
1981 baz = "qux"
1982 });
1983
1984 let root_id = doc.get_root_id();
1985 let rec = doc.parse_record(root_id).unwrap();
1986
1987 let _name: String = rec.parse_field("name").unwrap();
1989
1990 let extra: IndexMap<String, String> = rec.flatten().parse().unwrap();
1992
1993 assert_eq!(extra.get("foo"), Some(&"bar".to_string()));
1995 assert_eq!(extra.get("baz"), Some(&"qux".to_string()));
1996
1997 rec.deny_unknown_fields().unwrap();
2000 }
2001
2002 #[derive(Debug, PartialEq)]
2008 struct RemoteDuration {
2009 secs: u64,
2010 nanos: u32,
2011 }
2012
2013 struct RemoteDurationDef;
2015
2016 impl<'doc> FromEure<'doc, RemoteDuration> for RemoteDurationDef {
2017 type Error = ParseError;
2018
2019 fn parse(ctx: &ParseContext<'doc>) -> Result<RemoteDuration, Self::Error> {
2020 let rec = ctx.parse_record()?;
2021 let secs: u64 = rec.parse_field("secs")?;
2022 let nanos: u32 = rec.parse_field("nanos")?;
2023 rec.deny_unknown_fields()?;
2024 Ok(RemoteDuration { secs, nanos })
2025 }
2026 }
2027
2028 #[test]
2029 fn test_remote_type_basic_parsing() {
2030 let doc = eure!({ secs = 10, nanos = 500 });
2031 let root_id = doc.get_root_id();
2032
2033 let duration: RemoteDuration = doc.parse_via::<RemoteDurationDef, _>(root_id).unwrap();
2035
2036 assert_eq!(
2037 duration,
2038 RemoteDuration {
2039 secs: 10,
2040 nanos: 500
2041 }
2042 );
2043 }
2044
2045 #[test]
2046 fn test_remote_type_in_option() {
2047 let doc = eure!({ secs = 5, nanos = 0 });
2050 let root_id = doc.get_root_id();
2051
2052 let duration: Option<RemoteDuration> = doc
2054 .parse_via::<Option<RemoteDurationDef>, _>(root_id)
2055 .unwrap();
2056
2057 assert_eq!(duration, Some(RemoteDuration { secs: 5, nanos: 0 }));
2058 }
2059
2060 #[test]
2061 fn test_remote_type_in_option_none() {
2062 let doc = eure!({ = null });
2063 let root_id = doc.get_root_id();
2064
2065 let duration: Option<RemoteDuration> = doc
2066 .parse_via::<Option<RemoteDurationDef>, _>(root_id)
2067 .unwrap();
2068
2069 assert_eq!(duration, None);
2070 }
2071
2072 #[test]
2073 fn test_remote_type_in_vec() {
2074 let doc = eure!({
2075 items[] { secs = 1, nanos = 0 }
2076 items[] { secs = 2, nanos = 100 }
2077 });
2078 let root_id = doc.get_root_id();
2079 let rec = doc.parse_record(root_id).unwrap();
2080 let items_ctx = rec.field("items").unwrap();
2081
2082 let durations: Vec<RemoteDuration> =
2084 items_ctx.parse_via::<Vec<RemoteDurationDef>, _>().unwrap();
2085
2086 assert_eq!(
2087 durations,
2088 vec![
2089 RemoteDuration { secs: 1, nanos: 0 },
2090 RemoteDuration {
2091 secs: 2,
2092 nanos: 100
2093 },
2094 ]
2095 );
2096 }
2097
2098 #[test]
2099 fn test_remote_type_in_indexmap() {
2100 let doc = eure!({
2101 short { secs = 1, nanos = 0 }
2102 long { secs = 10, nanos = 0 }
2103 });
2104 let root_id = doc.get_root_id();
2105
2106 let durations: IndexMap<String, RemoteDuration> = doc
2108 .parse_via::<IndexMap<String, RemoteDurationDef>, _>(root_id)
2109 .unwrap();
2110
2111 assert_eq!(durations.len(), 2);
2112 assert_eq!(
2113 durations.get("short"),
2114 Some(&RemoteDuration { secs: 1, nanos: 0 })
2115 );
2116 assert_eq!(
2117 durations.get("long"),
2118 Some(&RemoteDuration { secs: 10, nanos: 0 })
2119 );
2120 }
2121
2122 #[test]
2123 fn test_remote_type_in_nested_containers() {
2124 let doc = eure!({
2126 items[] { secs = 1, nanos = 0 }
2127 });
2128 let root_id = doc.get_root_id();
2129 let rec = doc.parse_record(root_id).unwrap();
2130 let items_ctx = rec.field("items").unwrap();
2131
2132 let durations: Option<Vec<RemoteDuration>> = items_ctx
2134 .parse_via::<Option<Vec<RemoteDurationDef>>, _>()
2135 .unwrap();
2136
2137 assert_eq!(durations, Some(vec![RemoteDuration { secs: 1, nanos: 0 }]));
2138 }
2139
2140 #[test]
2141 fn test_parse_context_parse_via() {
2142 let doc = eure!({ secs = 42, nanos = 123 });
2143 let root_id = doc.get_root_id();
2144 let ctx = doc.parse_context(root_id);
2145
2146 let duration: RemoteDuration = ctx.parse_via::<RemoteDurationDef, _>().unwrap();
2148
2149 assert_eq!(
2150 duration,
2151 RemoteDuration {
2152 secs: 42,
2153 nanos: 123
2154 }
2155 );
2156 }
2157
2158 #[test]
2163 fn test_array_basic_parsing() {
2164 let doc = eure!({ items = [1, 2, 3] });
2165 let root_id = doc.get_root_id();
2166 let rec = doc.parse_record(root_id).unwrap();
2167 let items: [i32; 3] = rec.parse_field("items").unwrap();
2168 assert_eq!(items, [1, 2, 3]);
2169 }
2170
2171 #[test]
2172 fn test_array_empty() {
2173 let doc = eure!({ items = [] });
2174 let root_id = doc.get_root_id();
2175 let rec = doc.parse_record(root_id).unwrap();
2176 let items: [i32; 0] = rec.parse_field("items").unwrap();
2177 assert_eq!(items, []);
2178 }
2179
2180 #[test]
2181 fn test_array_length_mismatch_too_few() {
2182 let doc = eure!({ items = [1, 2] });
2183 let root_id = doc.get_root_id();
2184 let rec = doc.parse_record(root_id).unwrap();
2185 let result: Result<[i32; 3], _> = rec.parse_field("items");
2186 assert!(result.is_err());
2187 let err = result.unwrap_err();
2188 assert!(matches!(
2189 err.kind,
2190 ParseErrorKind::UnexpectedArrayLength {
2191 expected: 3,
2192 actual: 2
2193 }
2194 ));
2195 }
2196
2197 #[test]
2198 fn test_array_length_mismatch_too_many() {
2199 let doc = eure!({ items = [1, 2, 3, 4] });
2200 let root_id = doc.get_root_id();
2201 let rec = doc.parse_record(root_id).unwrap();
2202 let result: Result<[i32; 3], _> = rec.parse_field("items");
2203 assert!(result.is_err());
2204 let err = result.unwrap_err();
2205 assert!(matches!(
2206 err.kind,
2207 ParseErrorKind::UnexpectedArrayLength {
2208 expected: 3,
2209 actual: 4
2210 }
2211 ));
2212 }
2213
2214 #[test]
2215 fn test_array_nested_types() {
2216 let doc = eure!({ items = ["a", "b"] });
2217 let root_id = doc.get_root_id();
2218 let rec = doc.parse_record(root_id).unwrap();
2219 let items: [String; 2] = rec.parse_field("items").unwrap();
2220 assert_eq!(items, ["a".to_string(), "b".to_string()]);
2221 }
2222
2223 #[test]
2224 fn test_array_in_option() {
2225 let doc = eure!({ items = [1, 2, 3] });
2226 let root_id = doc.get_root_id();
2227 let rec = doc.parse_record(root_id).unwrap();
2228 let items: Option<[i32; 3]> = rec.parse_field("items").unwrap();
2229 assert_eq!(items, Some([1, 2, 3]));
2230 }
2231
2232 #[test]
2233 fn test_array_of_arrays() {
2234 let doc = eure!({ matrix = [[1, 2], [3, 4]] });
2235 let root_id = doc.get_root_id();
2236 let rec = doc.parse_record(root_id).unwrap();
2237 let matrix: [[i32; 2]; 2] = rec.parse_field("matrix").unwrap();
2238 assert_eq!(matrix, [[1, 2], [3, 4]]);
2239 }
2240
2241 #[test]
2242 fn test_array_remote_type() {
2243 let doc = eure!({
2244 items[] { secs = 1, nanos = 0 }
2245 items[] { secs = 2, nanos = 100 }
2246 });
2247 let root_id = doc.get_root_id();
2248 let rec = doc.parse_record(root_id).unwrap();
2249 let items_ctx = rec.field("items").unwrap();
2250
2251 let durations: [RemoteDuration; 2] =
2253 items_ctx.parse_via::<[RemoteDurationDef; 2], _>().unwrap();
2254
2255 assert_eq!(
2256 durations,
2257 [
2258 RemoteDuration { secs: 1, nanos: 0 },
2259 RemoteDuration {
2260 secs: 2,
2261 nanos: 100
2262 },
2263 ]
2264 );
2265 }
2266
2267 #[test]
2272 fn test_cow_static_str_from_eure() {
2273 use alloc::borrow::Cow;
2274
2275 let doc = eure!({ name = "hello" });
2276 let root_id = doc.get_root_id();
2277 let rec = doc.parse_record(root_id).unwrap();
2278 let value: Cow<'static, str> = rec.parse_field("name").unwrap();
2279 assert_eq!(value, Cow::<str>::Owned("hello".to_string()));
2280 }
2281}