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 alloc::string::String;
13use indexmap::{IndexMap, IndexSet};
14pub use object_key::ParseObjectKey;
15pub use record::RecordParser;
16pub use tuple::TupleParser;
17pub use union::UnionParser;
18pub use variant_path::VariantPath;
19
20use 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 document::node::{Node, NodeArray},
30 identifier::IdentifierError,
31 prelude_internal::*,
32 value::ValueKind,
33};
34
35pub type AccessedSnapshot = (HashSet<String>, HashSet<Identifier>);
41
42#[derive(Debug, Clone)]
59pub struct AccessedSet(Rc<RefCell<Vec<AccessedSnapshot>>>);
60
61impl AccessedSet {
62 pub fn new() -> Self {
64 Self(Rc::new(RefCell::new(vec![(
66 HashSet::new(),
67 HashSet::new(),
68 )])))
69 }
70
71 pub fn add_field(&self, field: impl Into<String>) {
73 self.0
74 .borrow_mut()
75 .last_mut()
76 .unwrap()
77 .0
78 .insert(field.into());
79 }
80
81 pub fn add_ext(&self, ext: Identifier) {
83 self.0.borrow_mut().last_mut().unwrap().1.insert(ext);
84 }
85
86 pub fn has_field(&self, field: &str) -> bool {
88 self.0.borrow().last().unwrap().0.contains(field)
89 }
90
91 pub fn has_ext(&self, ext: &Identifier) -> bool {
93 self.0.borrow().last().unwrap().1.contains(ext)
94 }
95
96 pub fn get_accessed_exts(&self) -> HashSet<Identifier> {
98 self.0.borrow().last().unwrap().1.clone()
99 }
100
101 pub fn push_snapshot(&self) {
104 let mut stack = self.0.borrow_mut();
105 let snapshot = stack.last().unwrap().clone();
106 let len = stack.len();
107 stack.insert(len - 1, snapshot);
108 }
110
111 pub fn restore_to_current_snapshot(&self) {
114 let mut stack = self.0.borrow_mut();
115 if stack.len() >= 2 {
116 let snapshot = stack[stack.len() - 2].clone();
117 *stack.last_mut().unwrap() = snapshot;
118 }
119 }
120
121 pub fn capture_current_state(&self) -> AccessedSnapshot {
123 self.0.borrow().last().unwrap().clone()
124 }
125
126 pub fn restore_to_state(&self, state: AccessedSnapshot) {
128 *self.0.borrow_mut().last_mut().unwrap() = state;
129 }
130
131 pub fn pop_and_restore(&self) {
134 let mut stack = self.0.borrow_mut();
135 if stack.len() >= 2 {
136 stack.pop(); }
138 }
139
140 pub fn pop_without_restore(&self) {
143 let mut stack = self.0.borrow_mut();
144 if stack.len() >= 2 {
145 let snapshot_idx = stack.len() - 2;
146 stack.remove(snapshot_idx); }
148 }
149}
150
151impl Default for AccessedSet {
152 fn default() -> Self {
153 Self::new()
154 }
155}
156
157#[derive(Debug, Clone, Copy, PartialEq, Eq)]
165pub enum ParserScope {
166 Record,
168 Extension,
170}
171
172#[derive(Debug, Clone)]
199pub struct FlattenContext {
200 accessed: AccessedSet,
201 scope: ParserScope,
202}
203
204impl FlattenContext {
205 pub fn new(accessed: AccessedSet, scope: ParserScope) -> Self {
207 Self { accessed, scope }
208 }
209
210 pub fn scope(&self) -> ParserScope {
212 self.scope
213 }
214
215 pub fn accessed_set(&self) -> &AccessedSet {
217 &self.accessed
218 }
219
220 pub fn add_field(&self, field: impl Into<String>) {
222 self.accessed.add_field(field);
223 }
224
225 pub fn add_ext(&self, ext: Identifier) {
227 self.accessed.add_ext(ext);
228 }
229
230 pub fn has_field(&self, field: &str) -> bool {
232 self.accessed.has_field(field)
233 }
234
235 pub fn has_ext(&self, ext: &Identifier) -> bool {
237 self.accessed.has_ext(ext)
238 }
239
240 pub fn push_snapshot(&self) {
242 self.accessed.push_snapshot();
243 }
244
245 pub fn restore_to_current_snapshot(&self) {
247 self.accessed.restore_to_current_snapshot();
248 }
249
250 pub fn capture_current_state(&self) -> AccessedSnapshot {
252 self.accessed.capture_current_state()
253 }
254
255 pub fn restore_to_state(&self, state: AccessedSnapshot) {
257 self.accessed.restore_to_state(state);
258 }
259
260 pub fn pop_and_restore(&self) {
262 self.accessed.pop_and_restore();
263 }
264
265 pub fn pop_without_restore(&self) {
267 self.accessed.pop_without_restore();
268 }
269}
270
271#[derive(Clone, Debug)]
280pub struct ParseContext<'doc> {
281 doc: &'doc EureDocument,
282 node_id: NodeId,
283 variant_path: Option<VariantPath>,
284 flatten_ctx: Option<FlattenContext>,
288 accessed: AccessedSet,
290}
291
292impl<'doc> ParseContext<'doc> {
293 pub fn new(doc: &'doc EureDocument, node_id: NodeId) -> Self {
295 Self {
296 doc,
297 node_id,
298 variant_path: None,
299 flatten_ctx: None,
300 accessed: AccessedSet::new(),
301 }
302 }
303
304 pub fn with_flatten_ctx(
310 doc: &'doc EureDocument,
311 node_id: NodeId,
312 flatten_ctx: FlattenContext,
313 ) -> Self {
314 let accessed = flatten_ctx.accessed_set().clone();
316 Self {
317 doc,
318 node_id,
319 variant_path: None,
320 flatten_ctx: Some(flatten_ctx),
321 accessed,
322 }
323 }
324
325 pub fn flatten_ctx(&self) -> Option<&FlattenContext> {
327 self.flatten_ctx.as_ref()
328 }
329
330 pub fn is_flattened(&self) -> bool {
334 self.flatten_ctx.is_some()
335 }
336
337 pub fn parser_scope(&self) -> Option<ParserScope> {
343 self.flatten_ctx.as_ref().map(|fc| fc.scope())
344 }
345
346 pub fn node_id(&self) -> NodeId {
348 self.node_id
349 }
350
351 pub(crate) fn doc(&self) -> &'doc EureDocument {
353 self.doc
354 }
355
356 pub fn node(&self) -> &'doc Node {
358 self.doc.node(self.node_id)
359 }
360
361 pub(crate) fn at(&self, node_id: NodeId) -> Self {
363 Self {
364 doc: self.doc,
365 node_id,
366 variant_path: None,
367 flatten_ctx: None,
368 accessed: AccessedSet::new(),
369 }
370 }
371
372 pub fn flatten(&self) -> Self {
407 let flatten_ctx = match &self.flatten_ctx {
412 Some(fc) => FlattenContext::new(fc.accessed_set().clone(), ParserScope::Record),
413 None => FlattenContext::new(self.accessed.clone(), ParserScope::Record),
414 };
415 Self {
416 doc: self.doc,
417 node_id: self.node_id,
418 variant_path: self.variant_path.clone(),
419 flatten_ctx: Some(flatten_ctx),
420 accessed: self.accessed.clone(),
421 }
422 }
423
424 pub fn parse<T: FromEure<'doc, T>>(&self) -> Result<T, T::Error> {
426 T::parse(self)
427 }
428
429 pub fn parse_via<M, T>(&self) -> Result<T, M::Error>
434 where
435 M: FromEure<'doc, T>,
436 {
437 M::parse(self)
438 }
439
440 pub fn parse_with<T: DocumentParser<'doc>>(
441 &self,
442 mut parser: T,
443 ) -> Result<T::Output, T::Error> {
444 parser.parse(self)
445 }
446
447 pub fn parse_union<T, E>(&self) -> Result<UnionParser<'doc, '_, T, E>, E>
451 where
452 E: UnionParseError,
453 {
454 UnionParser::new(self).map_err(Into::into)
455 }
456
457 pub fn parse_record(&self) -> Result<RecordParser<'doc>, ParseError> {
461 self.ensure_no_variant_path()?;
462 RecordParser::new(self)
463 }
464
465 pub fn parse_tuple(&self) -> Result<TupleParser<'doc>, ParseError> {
469 self.ensure_no_variant_path()?;
470 TupleParser::new(self)
471 }
472
473 pub fn parse_primitive(&self) -> Result<&'doc PrimitiveValue, ParseError> {
478 self.ensure_no_variant_path()?;
479 match &self.node().content {
480 NodeValue::Primitive(p) => Ok(p),
481 _ => Err(ParseError {
482 node_id: self.node_id(),
483 kind: ParseErrorKind::NotPrimitive {
484 actual: self.node().content.value_kind(),
485 },
486 }),
487 }
488 }
489
490 pub(crate) fn accessed(&self) -> &AccessedSet {
496 &self.accessed
497 }
498
499 pub fn node_subtree_to_document_excluding_accessed(&self) -> EureDocument {
506 let mut doc = self.doc.node_subtree_to_document(self.node_id);
507 let root_id = doc.get_root_id();
508 let accessed_exts = self.accessed.get_accessed_exts();
509 for ext in accessed_exts {
510 doc.node_mut(root_id).extensions.remove_fast(&ext);
511 }
512 doc
513 }
514
515 fn mark_ext_accessed(&self, ident: Identifier) {
517 self.accessed.add_ext(ident);
518 }
519
520 pub fn parse_ext<T>(&self, name: &str) -> Result<T, T::Error>
524 where
525 T: FromEure<'doc>,
526 T::Error: From<ParseError>,
527 {
528 self.parse_ext_with(name, T::parse)
529 }
530
531 pub fn parse_ext_with<T>(&self, name: &str, mut parser: T) -> Result<T::Output, T::Error>
533 where
534 T: DocumentParser<'doc>,
535 T::Error: From<ParseError>,
536 {
537 let ident: Identifier = name.parse().map_err(|e| ParseError {
538 node_id: self.node_id,
539 kind: ParseErrorKind::InvalidIdentifier(e),
540 })?;
541 self.mark_ext_accessed(ident.clone());
542 let ext_node_id = self
543 .node()
544 .extensions
545 .get(&ident)
546 .ok_or_else(|| ParseError {
547 node_id: self.node_id,
548 kind: ParseErrorKind::MissingExtension(name.to_string()),
549 })?;
550 let ctx = ParseContext::new(self.doc, *ext_node_id);
551 parser.parse(&ctx)
552 }
553
554 pub fn parse_ext_optional<T>(&self, name: &str) -> Result<Option<T>, T::Error>
558 where
559 T: FromEure<'doc>,
560 T::Error: From<ParseError>,
561 {
562 self.parse_ext_optional_with(name, T::parse)
563 }
564
565 pub fn parse_ext_optional_with<T>(
569 &self,
570 name: &str,
571 mut parser: T,
572 ) -> Result<Option<T::Output>, T::Error>
573 where
574 T: DocumentParser<'doc>,
575 T::Error: From<ParseError>,
576 {
577 let ident: Identifier = name.parse().map_err(|e| ParseError {
578 node_id: self.node_id,
579 kind: ParseErrorKind::InvalidIdentifier(e),
580 })?;
581 self.mark_ext_accessed(ident.clone());
582 match self.node().extensions.get(&ident) {
583 Some(ext_node_id) => {
584 let ctx = ParseContext::new(self.doc, *ext_node_id);
585 Ok(Some(parser.parse(&ctx)?))
586 }
587 None => Ok(None),
588 }
589 }
590
591 pub fn ext(&self, name: &str) -> Result<ParseContext<'doc>, ParseError> {
596 let ident: Identifier = name.parse().map_err(|e| ParseError {
597 node_id: self.node_id,
598 kind: ParseErrorKind::InvalidIdentifier(e),
599 })?;
600 self.mark_ext_accessed(ident.clone());
601 let ext_node_id =
602 self.node()
603 .extensions
604 .get(&ident)
605 .copied()
606 .ok_or_else(|| ParseError {
607 node_id: self.node_id,
608 kind: ParseErrorKind::MissingExtension(name.to_string()),
609 })?;
610 Ok(ParseContext::new(self.doc, ext_node_id))
611 }
612
613 pub fn ext_optional(&self, name: &str) -> Option<ParseContext<'doc>> {
618 let ident: Identifier = name.parse().ok()?;
619 self.mark_ext_accessed(ident.clone());
620 self.node()
621 .extensions
622 .get(&ident)
623 .map(|&node_id| ParseContext::new(self.doc, node_id))
624 }
625
626 pub fn deny_unknown_extensions(&self) -> Result<(), ParseError> {
631 if self.flatten_ctx.is_some() {
633 return Ok(());
634 }
635
636 for (ident, _) in self.node().extensions.iter() {
638 if !self.accessed.has_ext(ident) {
639 return Err(ParseError {
640 node_id: self.node_id,
641 kind: ParseErrorKind::UnknownExtension(ident.clone()),
642 });
643 }
644 }
645 Ok(())
646 }
647
648 pub fn unknown_extensions(
652 &self,
653 ) -> impl Iterator<Item = (&'doc Identifier, ParseContext<'doc>)> + '_ {
654 let doc = self.doc;
655 let accessed = self.accessed.clone();
657 self.node()
658 .extensions
659 .iter()
660 .filter_map(move |(ident, &node_id)| {
661 if !accessed.has_ext(ident) {
662 Some((ident, ParseContext::new(doc, node_id)))
663 } else {
664 None
665 }
666 })
667 }
668
669 pub fn flatten_ext(&self) -> ParseContext<'doc> {
695 let flatten_ctx = match &self.flatten_ctx {
700 Some(fc) => FlattenContext::new(fc.accessed_set().clone(), ParserScope::Extension),
701 None => FlattenContext::new(self.accessed.clone(), ParserScope::Extension),
702 };
703
704 ParseContext::with_flatten_ctx(self.doc, self.node_id, flatten_ctx)
705 }
706
707 pub fn is_null(&self) -> bool {
709 matches!(
710 &self.node().content,
711 NodeValue::Primitive(PrimitiveValue::Null)
712 )
713 }
714
715 pub(crate) fn with_variant_rest(&self, rest: Option<VariantPath>) -> Self {
717 Self {
718 doc: self.doc,
719 node_id: self.node_id,
720 variant_path: rest,
721 flatten_ctx: self.flatten_ctx.clone(),
722 accessed: self.accessed.clone(),
723 }
724 }
725
726 pub(crate) fn variant_path(&self) -> Option<&VariantPath> {
728 self.variant_path.as_ref()
729 }
730
731 fn ensure_no_variant_path(&self) -> Result<(), ParseError> {
733 if let Some(vp) = &self.variant_path
734 && !vp.is_empty()
735 {
736 return Err(ParseError {
737 node_id: self.node_id,
738 kind: ParseErrorKind::UnexpectedVariantPath(vp.clone()),
739 });
740 }
741 Ok(())
742 }
743
744 fn unexpected_kind(&self, expected: ValueKind) -> ParseError {
745 ParseError {
746 node_id: self.node_id(),
747 kind: ParseErrorKind::TypeMismatch {
748 expected,
749 actual: self.node().content.value_kind(),
750 },
751 }
752 }
753}
754
755#[diagnostic::on_unimplemented(
807 message = "`{Self}` cannot be parsed from Eure document",
808 label = "this type does not implement `FromEure`",
809 note = "consider adding `#[derive(FromEure)]` to `{Self}`"
810)]
811pub trait FromEure<'doc, T = Self>: Sized {
812 type Error;
814
815 fn parse(ctx: &ParseContext<'doc>) -> Result<T, Self::Error>;
817}
818
819pub trait UnionParseError: From<ParseError> {
825 fn as_parse_error(&self) -> Option<&ParseError>;
827
828 fn from_no_matching_variant(
830 node_id: NodeId,
831 variant: Option<String>,
832 best_match: Option<BestParseVariantMatch>,
833 _failures: &[(String, Self)],
834 ) -> Self {
835 ParseError {
836 node_id,
837 kind: ParseErrorKind::NoMatchingVariant {
838 variant,
839 best_match: best_match.map(Box::new),
840 },
841 }
842 .into()
843 }
844}
845
846impl UnionParseError for ParseError {
847 fn as_parse_error(&self) -> Option<&ParseError> {
848 Some(self)
849 }
850}
851
852#[derive(Debug, Clone, PartialEq)]
854pub struct BestParseVariantMatch {
855 pub variant_name: String,
857 pub error: Box<ParseError>,
859}
860
861#[derive(Debug, thiserror::Error, Clone, PartialEq)]
862#[error("parse error: {kind}")]
863pub struct ParseError {
864 pub node_id: NodeId,
865 pub kind: ParseErrorKind,
866}
867
868#[derive(Debug, thiserror::Error, Clone, PartialEq)]
870pub enum ParseErrorKind {
871 #[error("unexpected uninitialized value")]
873 UnexpectedHole,
874
875 #[error("type mismatch: expected {expected}, got {actual}")]
877 TypeMismatch {
878 expected: ValueKind,
879 actual: ValueKind,
880 },
881
882 #[error("missing field: {0}")]
884 MissingField(String),
885
886 #[error("missing extension: ${0}")]
888 MissingExtension(String),
889
890 #[error("unknown variant: {0}")]
892 UnknownVariant(String),
893
894 #[error("value out of range: {0}")]
896 OutOfRange(String),
897
898 #[error("invalid {kind}: {reason}")]
904 InvalidPattern { kind: String, reason: String },
905
906 #[error("at {path}: {source}")]
908 Nested {
909 path: String,
910 #[source]
911 source: Box<ParseErrorKind>,
912 },
913
914 #[error("invalid identifier: {0}")]
916 InvalidIdentifier(#[from] IdentifierError),
917
918 #[error("unexpected tuple length: expected {expected}, got {actual}")]
920 UnexpectedTupleLength { expected: usize, actual: usize },
921
922 #[error("unknown field: {0}")]
924 UnknownField(String),
925
926 #[error("unknown extension: ${0}")]
928 UnknownExtension(Identifier),
929
930 #[error("invalid key type in record: expected string key, got {0:?}")]
932 InvalidKeyType(crate::value::ObjectKey),
933
934 #[error("{}", format_no_matching_variant(variant, best_match))]
936 NoMatchingVariant {
937 variant: Option<String>,
939 best_match: Option<Box<BestParseVariantMatch>>,
941 },
942
943 #[error("conflicting variant tags: $variant = {explicit}, repr = {repr}")]
945 ConflictingVariantTags { explicit: String, repr: String },
946
947 #[error("ambiguous union: {0:?}")]
949 AmbiguousUnion(Vec<String>),
950
951 #[error("literal value mismatch: expected {expected}, got {actual}")]
953 LiteralMismatch { expected: String, actual: String },
955
956 #[error("unexpected variant path: {0}")]
958 UnexpectedVariantPath(VariantPath),
959
960 #[error("$variant must be a string, got {0}")]
962 InvalidVariantType(ValueKind),
963
964 #[error("invalid $variant path syntax: {0}")]
966 InvalidVariantPath(String),
967
968 #[error(
971 "cannot parse record in extension scope: use #[eure(flatten)] instead of #[eure(flatten_ext)]"
972 )]
973 RecordInExtensionScope,
974
975 #[error("unexpected array length: expected {expected}, got {actual}")]
977 UnexpectedArrayLength { expected: usize, actual: usize },
978
979 #[error("expected primitive value, got {actual}")]
981 NotPrimitive { actual: ValueKind },
982}
983
984impl ParseErrorKind {
985 pub fn at(self, path: impl Into<String>) -> Self {
987 ParseErrorKind::Nested {
988 path: path.into(),
989 source: Box::new(self),
990 }
991 }
992}
993
994fn format_no_matching_variant(
995 variant: &Option<String>,
996 best_match: &Option<Box<BestParseVariantMatch>>,
997) -> String {
998 let mut message = "no matching variant".to_string();
999 if let Some(variant) = variant {
1000 message.push_str(&format!(" (variant: {variant})"));
1001 }
1002 if let Some(best_match) = best_match {
1003 message.push_str(&format!(
1004 " (based on nearest variant '{}')",
1005 best_match.variant_name
1006 ));
1007 }
1008 message
1009}
1010
1011fn unwrap_best_variant_error<E: UnionParseError>(error: E) -> E {
1012 if let Some(ParseError {
1013 kind:
1014 ParseErrorKind::NoMatchingVariant {
1015 best_match: Some(best_match),
1016 ..
1017 },
1018 ..
1019 }) = error.as_parse_error()
1020 {
1021 return E::from(best_match.error.as_ref().clone());
1022 }
1023 error
1024}
1025
1026impl<'doc> EureDocument {
1027 pub fn parse<T: FromEure<'doc, T>>(&'doc self, node_id: NodeId) -> Result<T, T::Error> {
1029 self.parse_with(node_id, T::parse)
1030 }
1031
1032 pub fn parse_via<M, T>(&'doc self, node_id: NodeId) -> Result<T, M::Error>
1037 where
1038 M: FromEure<'doc, T>,
1039 {
1040 let ctx = self.parse_context(node_id);
1041 M::parse(&ctx)
1042 }
1043
1044 pub fn parse_with<T: DocumentParser<'doc>>(
1045 &'doc self,
1046 node_id: NodeId,
1047 mut parser: T,
1048 ) -> Result<T::Output, T::Error> {
1049 parser.parse(&self.parse_context(node_id))
1050 }
1051
1052 pub fn parse_context(&'doc self, node_id: NodeId) -> ParseContext<'doc> {
1054 ParseContext::new(self, node_id)
1055 }
1056
1057 pub fn parse_record(&'doc self, node_id: NodeId) -> Result<RecordParser<'doc>, ParseError> {
1061 RecordParser::from_doc_and_node(self, node_id)
1062 }
1063
1064 pub fn parse_extension_context(&'doc self, node_id: NodeId) -> ParseContext<'doc> {
1069 ParseContext::new(self, node_id)
1070 }
1071
1072 pub fn parse_tuple(&'doc self, node_id: NodeId) -> Result<TupleParser<'doc>, ParseError> {
1076 TupleParser::from_doc_and_node(self, node_id)
1077 }
1078}
1079
1080impl<'doc> FromEure<'doc> for EureDocument {
1081 type Error = ParseError;
1082
1083 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1084 Ok(ctx.doc().node_subtree_to_document(ctx.node_id()))
1085 }
1086}
1087
1088impl<'doc> FromEure<'doc> for &'doc str {
1089 type Error = ParseError;
1090
1091 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1092 if let PrimitiveValue::Text(text) = ctx.parse_primitive()? {
1093 return Ok(text.as_str());
1094 }
1095 Err(ctx.unexpected_kind(ValueKind::Text))
1096 }
1097}
1098
1099impl FromEure<'_> for String {
1100 type Error = ParseError;
1101
1102 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1103 ctx.parse::<&str>().map(String::from)
1104 }
1105}
1106
1107impl FromEure<'_> for crate::plan::Form {
1108 type Error = ParseError;
1109
1110 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1111 let value: &str = ctx.parse()?;
1112 match value {
1113 "inline" => Ok(crate::plan::Form::Inline),
1114 "binding-block" => Ok(crate::plan::Form::BindingBlock),
1115 "binding-value-block" => Ok(crate::plan::Form::BindingValueBlock),
1116 "section" => Ok(crate::plan::Form::Section),
1117 "section-block" => Ok(crate::plan::Form::SectionBlock),
1118 "section-value-block" => Ok(crate::plan::Form::SectionValueBlock),
1119 "flatten" => Ok(crate::plan::Form::Flatten),
1120 other => Err(ParseError {
1121 node_id: ctx.node_id(),
1122 kind: ParseErrorKind::UnknownVariant(other.to_string()),
1123 }),
1124 }
1125 }
1126}
1127
1128#[diagnostic::do_not_recommend]
1129impl<'doc, T> FromEure<'doc> for Cow<'static, T>
1130where
1131 T: ToOwned + ?Sized,
1132 T::Owned: FromEure<'doc>,
1133{
1134 type Error = <T::Owned as FromEure<'doc>>::Error;
1135
1136 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1137 <T::Owned as FromEure<'doc>>::parse(ctx).map(Cow::Owned)
1138 }
1139}
1140
1141impl FromEure<'_> for Text {
1142 type Error = ParseError;
1143
1144 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1145 if let PrimitiveValue::Text(text) = ctx.parse_primitive()? {
1146 return Ok(text.clone());
1147 }
1148 Err(ctx.unexpected_kind(ValueKind::Text))
1149 }
1150}
1151
1152impl FromEure<'_> for bool {
1153 type Error = ParseError;
1154
1155 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1156 if let PrimitiveValue::Bool(b) = ctx.parse_primitive()? {
1157 return Ok(*b);
1158 }
1159 Err(ctx.unexpected_kind(ValueKind::Bool))
1160 }
1161}
1162
1163impl FromEure<'_> for BigInt {
1164 type Error = ParseError;
1165
1166 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1167 if let PrimitiveValue::Integer(i) = ctx.parse_primitive()? {
1168 return Ok(i.clone());
1169 }
1170 Err(ctx.unexpected_kind(ValueKind::Integer))
1171 }
1172}
1173
1174impl FromEure<'_> for f32 {
1175 type Error = ParseError;
1176
1177 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1178 if let PrimitiveValue::F32(f) = ctx.parse_primitive()? {
1179 return Ok(*f);
1180 }
1181 Err(ctx.unexpected_kind(ValueKind::F32))
1182 }
1183}
1184
1185impl FromEure<'_> for f64 {
1186 type Error = ParseError;
1187
1188 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1189 match ctx.parse_primitive()? {
1190 PrimitiveValue::F32(f) => Ok(*f as f64),
1191 PrimitiveValue::F64(f) => Ok(*f),
1192 _ => Err(ctx.unexpected_kind(ValueKind::F64)),
1193 }
1194 }
1195}
1196
1197macro_rules! impl_from_eure_int {
1198 ($($ty:ty),*) => {
1199 $(
1200 impl FromEure<'_> for $ty {
1201 type Error = ParseError;
1202
1203 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1204 let value: BigInt = ctx.parse()?;
1205 <$ty>::try_from(&value).map_err(|_| ParseError {
1206 node_id: ctx.node_id(),
1207 kind: ParseErrorKind::OutOfRange(
1208 format!("value {} out of {} range", value, stringify!($ty)),
1209 ),
1210 })
1211 }
1212 }
1213 )*
1214 };
1215}
1216
1217impl_from_eure_int!(
1218 u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize
1219);
1220
1221impl<'doc> FromEure<'doc> for &'doc PrimitiveValue {
1222 type Error = ParseError;
1223
1224 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1225 ctx.parse_primitive()
1226 }
1227}
1228
1229impl FromEure<'_> for PrimitiveValue {
1230 type Error = ParseError;
1231
1232 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1233 ctx.parse::<&PrimitiveValue>().cloned()
1234 }
1235}
1236
1237impl FromEure<'_> for Identifier {
1238 type Error = ParseError;
1239
1240 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1241 if let PrimitiveValue::Text(text) = ctx.parse_primitive()? {
1242 return text
1243 .content
1244 .parse()
1245 .map_err(ParseErrorKind::InvalidIdentifier)
1246 .map_err(|kind| ParseError {
1247 node_id: ctx.node_id(),
1248 kind,
1249 });
1250 }
1251 Err(ctx.unexpected_kind(ValueKind::Text))
1252 }
1253}
1254
1255impl<'doc> FromEure<'doc> for &'doc NodeArray {
1256 type Error = ParseError;
1257
1258 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1259 ctx.ensure_no_variant_path()?;
1260 match &ctx.node().content {
1261 NodeValue::Array(array) => Ok(array),
1262 _ => Err(ctx.unexpected_kind(ValueKind::Array)),
1263 }
1264 }
1265}
1266
1267#[diagnostic::do_not_recommend]
1272impl<'doc, M, T> FromEure<'doc, Vec<T>> for Vec<M>
1273where
1274 M: FromEure<'doc, T>,
1275 M::Error: From<ParseError>,
1276{
1277 type Error = M::Error;
1278
1279 fn parse(ctx: &ParseContext<'doc>) -> Result<Vec<T>, Self::Error> {
1280 ctx.ensure_no_variant_path()?;
1281 match &ctx.node().content {
1282 NodeValue::Array(array) => array
1283 .iter()
1284 .map(|item| M::parse(&ctx.at(*item)))
1285 .collect::<Result<Vec<_>, _>>(),
1286 _ => Err(ctx.unexpected_kind(ValueKind::Array).into()),
1287 }
1288 }
1289}
1290
1291#[diagnostic::do_not_recommend]
1296impl<'doc, M, T, const N: usize> FromEure<'doc, [T; N]> for [M; N]
1297where
1298 M: FromEure<'doc, T>,
1299 M::Error: From<ParseError>,
1300{
1301 type Error = M::Error;
1302
1303 fn parse(ctx: &ParseContext<'doc>) -> Result<[T; N], Self::Error> {
1304 ctx.ensure_no_variant_path()?;
1305 match &ctx.node().content {
1306 NodeValue::Array(array) => {
1307 let node_ids: [NodeId; N] = array.try_into_array().ok_or_else(|| ParseError {
1308 node_id: ctx.node_id(),
1309 kind: ParseErrorKind::UnexpectedArrayLength {
1310 expected: N,
1311 actual: array.len(),
1312 },
1313 })?;
1314 let mut parsed = Vec::with_capacity(N);
1315 for id in node_ids {
1316 parsed.push(M::parse(&ctx.at(id))?);
1317 }
1318 let parsed: [T; N] = parsed
1319 .try_into()
1320 .unwrap_or_else(|_| unreachable!("length was asserted previously"));
1321 Ok(parsed)
1322 }
1323 _ => Err(ctx.unexpected_kind(ValueKind::Array).into()),
1324 }
1325 }
1326}
1327
1328#[diagnostic::do_not_recommend]
1330impl<'doc, M, T> FromEure<'doc, IndexSet<T>> for IndexSet<M>
1331where
1332 M: FromEure<'doc, T>,
1333 T: Eq + std::hash::Hash,
1334 M::Error: From<ParseError>,
1335{
1336 type Error = M::Error;
1337 fn parse(ctx: &ParseContext<'doc>) -> Result<IndexSet<T>, Self::Error> {
1338 ctx.ensure_no_variant_path()?;
1339 match &ctx.node().content {
1340 NodeValue::Array(array) => array
1341 .iter()
1342 .map(|item| M::parse(&ctx.at(*item)))
1343 .collect::<Result<IndexSet<_>, _>>(),
1344 _ => Err(ctx.unexpected_kind(ValueKind::Array).into()),
1345 }
1346 }
1347}
1348
1349macro_rules! parse_tuple {
1350 ($n:expr, $($var:ident),*) => {
1351 #[diagnostic::do_not_recommend]
1352 impl<'doc, $($var),*, Err> FromEure<'doc> for ($($var),*,)
1353 where $($var: FromEure<'doc, Error = Err>),*,
1354 Err: From<ParseError>,
1355 {
1356 type Error = Err;
1357
1358 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1359 ctx.ensure_no_variant_path()?;
1360 let tuple = match &ctx.node().content {
1361 NodeValue::Tuple(tuple) => tuple,
1362 _ => return Err(ctx.unexpected_kind(ValueKind::Tuple).into()),
1363 };
1364 if tuple.len() != $n {
1365 return Err(ParseError { node_id: ctx.node_id(), kind: ParseErrorKind::UnexpectedTupleLength { expected: $n, actual: tuple.len() } }.into());
1366 }
1367 let mut iter = tuple.iter();
1368 Ok(($($var::parse(&ctx.at(*iter.next().unwrap()))?),*,))
1369 }
1370 }
1371 }
1372}
1373
1374parse_tuple!(1, A);
1375parse_tuple!(2, A, B);
1376parse_tuple!(3, A, B, C);
1377parse_tuple!(4, A, B, C, D);
1378parse_tuple!(5, A, B, C, D, E);
1379parse_tuple!(6, A, B, C, D, E, F);
1380parse_tuple!(7, A, B, C, D, E, F, G);
1381parse_tuple!(8, A, B, C, D, E, F, G, H);
1382parse_tuple!(9, A, B, C, D, E, F, G, H, I);
1383parse_tuple!(10, A, B, C, D, E, F, G, H, I, J);
1384parse_tuple!(11, A, B, C, D, E, F, G, H, I, J, K);
1385parse_tuple!(12, A, B, C, D, E, F, G, H, I, J, K, L);
1386parse_tuple!(13, A, B, C, D, E, F, G, H, I, J, K, L, M);
1387parse_tuple!(14, A, B, C, D, E, F, G, H, I, J, K, L, M, N);
1388parse_tuple!(15, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
1389parse_tuple!(16, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
1390
1391macro_rules! parse_map {
1396 ($ctx:ident, $M:ty, $T:ty) => {{
1397 $ctx.ensure_no_variant_path()?;
1398
1399 if $ctx.parser_scope() == Some(ParserScope::Extension) {
1401 let node = $ctx.node();
1403 let flatten_ctx = $ctx.flatten_ctx();
1404 let accessed = flatten_ctx.map(|fc| fc.accessed_set());
1405 node.extensions
1406 .iter()
1407 .filter(|(ident, _)| {
1408 accessed.map_or(true, |a| !a.has_ext(ident))
1410 })
1411 .map(|(ident, &node_id)| {
1412 if let Some(fc) = &flatten_ctx {
1414 fc.add_ext((*ident).clone());
1415 }
1416 Ok((
1417 K::from_extension_ident(ident).map_err(|kind| ParseError {
1418 node_id: $ctx.node_id(),
1419 kind,
1420 })?,
1421 <$M as FromEure<'doc, $T>>::parse(&$ctx.at(node_id))?,
1422 ))
1423 })
1424 .collect::<Result<_, _>>()
1425 } else {
1426 let map = match &$ctx.node().content {
1428 NodeValue::Map(map) => map,
1429 _ => {
1430 return Err($ctx.unexpected_kind(ValueKind::Map).into());
1431 }
1432 };
1433 let flatten_ctx = $ctx
1435 .flatten_ctx()
1436 .filter(|fc| fc.scope() == ParserScope::Record);
1437 let accessed = flatten_ctx.map(|fc| fc.accessed_set().clone());
1438 map.iter()
1439 .filter(|(key, _)| {
1440 match &accessed {
1441 Some(acc) => match key {
1442 ObjectKey::String(s) => !acc.has_field(s),
1443 _ => true, },
1445 None => true, }
1447 })
1448 .map(|(key, value)| {
1449 if let Some(fc) = &flatten_ctx {
1451 if let ObjectKey::String(s) = key {
1452 fc.add_field(s);
1453 }
1454 }
1455 Ok((
1456 K::from_object_key(key).map_err(|kind| ParseError {
1457 node_id: $ctx.node_id(),
1458 kind,
1459 })?,
1460 <$M as FromEure<'doc, $T>>::parse(&$ctx.at(*value))?,
1461 ))
1462 })
1463 .collect::<Result<_, _>>()
1464 }
1465 }};
1466}
1467
1468#[diagnostic::do_not_recommend]
1470impl<'doc, K, M, T> FromEure<'doc, Map<K, T>> for Map<K, M>
1471where
1472 K: ParseObjectKey<'doc>,
1473 M: FromEure<'doc, T>,
1474 M::Error: From<ParseError>,
1475{
1476 type Error = M::Error;
1477
1478 fn parse(ctx: &ParseContext<'doc>) -> Result<Map<K, T>, Self::Error> {
1479 parse_map!(ctx, M, T)
1480 }
1481}
1482
1483#[diagnostic::do_not_recommend]
1485impl<'doc, K, M, T> FromEure<'doc, BTreeMap<K, T>> for BTreeMap<K, M>
1486where
1487 K: ParseObjectKey<'doc>,
1488 M: FromEure<'doc, T>,
1489 M::Error: From<ParseError>,
1490{
1491 type Error = M::Error;
1492 fn parse(ctx: &ParseContext<'doc>) -> Result<BTreeMap<K, T>, Self::Error> {
1493 parse_map!(ctx, M, T)
1494 }
1495}
1496
1497#[diagnostic::do_not_recommend]
1499impl<'doc, K, M, T> FromEure<'doc, HashMap<K, T>> for HashMap<K, M>
1500where
1501 K: ParseObjectKey<'doc>,
1502 M: FromEure<'doc, T>,
1503 M::Error: From<ParseError>,
1504{
1505 type Error = M::Error;
1506 fn parse(ctx: &ParseContext<'doc>) -> Result<HashMap<K, T>, Self::Error> {
1507 parse_map!(ctx, M, T)
1508 }
1509}
1510
1511#[diagnostic::do_not_recommend]
1513impl<'doc, K, M, T> FromEure<'doc, IndexMap<K, T>> for IndexMap<K, M>
1514where
1515 K: ParseObjectKey<'doc>,
1516 M: FromEure<'doc, T>,
1517 M::Error: From<ParseError>,
1518{
1519 type Error = M::Error;
1520 fn parse(ctx: &ParseContext<'doc>) -> Result<IndexMap<K, T>, Self::Error> {
1521 parse_map!(ctx, M, T)
1522 }
1523}
1524
1525impl FromEure<'_> for regex::Regex {
1526 type Error = ParseError;
1527
1528 fn parse(ctx: &ParseContext<'_>) -> Result<Self, Self::Error> {
1529 let pattern: &str = ctx.parse()?;
1530 regex::Regex::new(pattern).map_err(|e| ParseError {
1531 node_id: ctx.node_id(),
1532 kind: ParseErrorKind::InvalidPattern {
1533 kind: format!("regex '{}'", pattern),
1534 reason: e.to_string(),
1535 },
1536 })
1537 }
1538}
1539
1540#[diagnostic::do_not_recommend]
1550impl<'doc, M, T> FromEure<'doc, Option<T>> for Option<M>
1551where
1552 M: FromEure<'doc, T>,
1553 M::Error: UnionParseError,
1554{
1555 type Error = M::Error;
1556
1557 fn parse(ctx: &ParseContext<'doc>) -> Result<Option<T>, Self::Error> {
1558 ctx.parse_union::<Option<T>, M::Error>()?
1559 .variant("some", (M::parse).map(Some))
1560 .variant("none", |ctx: &ParseContext<'_>| {
1561 if ctx.is_null() {
1562 Ok(None)
1563 } else {
1564 Err(ParseError {
1565 node_id: ctx.node_id(),
1566 kind: ParseErrorKind::TypeMismatch {
1567 expected: ValueKind::Null,
1568 actual: ctx.node().content.value_kind(),
1569 },
1570 }
1571 .into())
1572 }
1573 })
1574 .parse()
1575 .map_err(unwrap_best_variant_error)
1576 }
1577}
1578
1579#[diagnostic::do_not_recommend]
1588impl<'doc, MT, T, ME, E, Err> FromEure<'doc, Result<T, E>> for Result<MT, ME>
1589where
1590 MT: FromEure<'doc, T, Error = Err>,
1591 ME: FromEure<'doc, E, Error = Err>,
1592 Err: UnionParseError,
1593{
1594 type Error = Err;
1595
1596 fn parse(ctx: &ParseContext<'doc>) -> Result<Result<T, E>, Self::Error> {
1597 ctx.parse_union::<Result<T, E>, Self::Error>()?
1598 .variant("ok", (MT::parse).map(Ok))
1599 .variant("err", (ME::parse).map(Err))
1600 .parse()
1601 .map_err(unwrap_best_variant_error)
1602 }
1603}
1604
1605#[diagnostic::do_not_recommend]
1606impl<'doc> FromEure<'doc> for () {
1607 type Error = ParseError;
1608 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1609 ctx.parse_tuple()?.finish()
1610 }
1611}
1612
1613impl<'doc> FromEure<'doc> for NodeId {
1614 type Error = ParseError;
1615 fn parse(ctx: &ParseContext<'doc>) -> Result<Self, Self::Error> {
1616 Ok(ctx.node_id())
1617 }
1618}
1619
1620pub trait DocumentParser<'doc> {
1621 type Output;
1622 type Error;
1623 fn parse(&mut self, ctx: &ParseContext<'doc>) -> Result<Self::Output, Self::Error>;
1624}
1625
1626pub struct AlwaysParser<T, E>(T, PhantomData<E>);
1627
1628impl<T, E> AlwaysParser<T, E> {
1629 pub fn new(value: T) -> AlwaysParser<T, E> {
1630 Self(value, PhantomData)
1631 }
1632}
1633
1634impl<'doc, T, E> DocumentParser<'doc> for AlwaysParser<T, E>
1635where
1636 T: Clone,
1637{
1638 type Output = T;
1639 type Error = E;
1640 fn parse(&mut self, _ctx: &ParseContext<'doc>) -> Result<Self::Output, Self::Error> {
1641 Ok(self.0.clone())
1642 }
1643}
1644
1645impl<'doc, T, F, E> DocumentParser<'doc> for F
1646where
1647 F: FnMut(&ParseContext<'doc>) -> Result<T, E>,
1648{
1649 type Output = T;
1650 type Error = E;
1651 fn parse(&mut self, ctx: &ParseContext<'doc>) -> Result<Self::Output, Self::Error> {
1652 (*self)(ctx)
1653 }
1654}
1655
1656pub struct LiteralParser<T>(pub T);
1657
1658impl<'doc, T, E> DocumentParser<'doc> for LiteralParser<T>
1659where
1660 T: FromEure<'doc, Error = E> + PartialEq + core::fmt::Debug,
1661 E: From<ParseError>,
1662{
1663 type Output = T;
1664 type Error = E;
1665 fn parse(&mut self, ctx: &ParseContext<'doc>) -> Result<Self::Output, Self::Error> {
1666 let value: T = ctx.parse::<T>()?;
1667 if value == self.0 {
1668 Ok(value)
1669 } else {
1670 Err(ParseError {
1671 node_id: ctx.node_id(),
1672 kind: ParseErrorKind::LiteralMismatch {
1673 expected: format!("{:?}", self.0),
1674 actual: format!("{:?}", value),
1675 },
1676 }
1677 .into())
1678 }
1679 }
1680}
1681
1682pub struct VariantLiteralParser(pub &'static str);
1688
1689impl<'doc> DocumentParser<'doc> for VariantLiteralParser {
1690 type Output = &'static str;
1691 type Error = ParseError;
1692 fn parse(&mut self, ctx: &ParseContext<'doc>) -> Result<Self::Output, Self::Error> {
1693 let value: &str = ctx.parse()?;
1694 if value == self.0 {
1695 Ok(self.0)
1696 } else {
1697 Err(ParseError {
1698 node_id: ctx.node_id(),
1699 kind: ParseErrorKind::UnknownVariant(value.to_string()),
1700 })
1701 }
1702 }
1703}
1704
1705pub struct MapParser<T, F> {
1706 parser: T,
1707 mapper: F,
1708}
1709
1710impl<'doc, T, O, F> DocumentParser<'doc> for MapParser<T, F>
1711where
1712 T: DocumentParser<'doc>,
1713 F: FnMut(T::Output) -> O,
1714{
1715 type Output = O;
1716 type Error = T::Error;
1717 fn parse(&mut self, ctx: &ParseContext<'doc>) -> Result<Self::Output, Self::Error> {
1718 self.parser.parse(ctx).map(|value| (self.mapper)(value))
1719 }
1720}
1721
1722pub struct AndThenParser<T, F> {
1723 parser: T,
1724 mapper: F,
1725}
1726
1727impl<'doc, T, O, F, E> DocumentParser<'doc> for AndThenParser<T, F>
1728where
1729 T: DocumentParser<'doc, Error = E>,
1730 F: Fn(T::Output) -> Result<O, E>,
1731{
1732 type Output = O;
1733 type Error = E;
1734 fn parse(&mut self, ctx: &ParseContext<'doc>) -> Result<Self::Output, Self::Error> {
1735 let value = self.parser.parse(ctx)?;
1736 (self.mapper)(value)
1737 }
1738}
1739
1740pub trait DocumentParserExt<'doc>: DocumentParser<'doc> + Sized {
1741 fn map<O, F>(self, mapper: F) -> MapParser<Self, F>
1742 where
1743 F: Fn(Self::Output) -> O,
1744 {
1745 MapParser {
1746 parser: self,
1747 mapper,
1748 }
1749 }
1750
1751 fn and_then<O, F>(self, mapper: F) -> AndThenParser<Self, F>
1752 where
1753 F: Fn(Self::Output) -> Result<O, Self::Error>,
1754 {
1755 AndThenParser {
1756 parser: self,
1757 mapper,
1758 }
1759 }
1760}
1761
1762impl<'doc, T> DocumentParserExt<'doc> for T where T: DocumentParser<'doc> {}
1763
1764#[cfg(test)]
1765mod tests {
1766 use super::*;
1767 use crate::document::node::NodeValue;
1768 use crate::eure;
1769 use crate::identifier::Identifier;
1770 use crate::text::Text;
1771 use crate::value::ObjectKey;
1772 use num_bigint::BigInt;
1773
1774 fn identifier(s: &str) -> Identifier {
1775 s.parse().unwrap()
1776 }
1777
1778 fn create_record_with_variant(
1780 field_name: &str,
1781 value: NodeValue,
1782 variant: &str,
1783 ) -> EureDocument {
1784 let mut doc = EureDocument::new();
1785 let root_id = doc.get_root_id();
1786
1787 let field_id = doc
1789 .add_map_child(ObjectKey::String(field_name.to_string()), root_id)
1790 .unwrap()
1791 .node_id;
1792 doc.node_mut(field_id).content = value;
1793
1794 let variant_node_id = doc
1796 .add_extension(identifier("variant"), field_id)
1797 .unwrap()
1798 .node_id;
1799 doc.node_mut(variant_node_id).content =
1800 NodeValue::Primitive(PrimitiveValue::Text(Text::plaintext(variant.to_string())));
1801
1802 doc
1803 }
1804
1805 #[test]
1806 fn test_option_some_tagged() {
1807 let doc = create_record_with_variant(
1808 "value",
1809 NodeValue::Primitive(PrimitiveValue::Integer(BigInt::from(42))),
1810 "some",
1811 );
1812 let root_id = doc.get_root_id();
1813 let rec = doc.parse_record(root_id).unwrap();
1814 let value: Option<i32> = rec.parse_field("value").unwrap();
1815 assert_eq!(value, Some(42));
1816 }
1817
1818 #[test]
1819 fn test_option_none_tagged() {
1820 let doc =
1821 create_record_with_variant("value", NodeValue::Primitive(PrimitiveValue::Null), "none");
1822 let root_id = doc.get_root_id();
1823 let rec = doc.parse_record(root_id).unwrap();
1824 let value: Option<i32> = rec.parse_field("value").unwrap();
1825 assert_eq!(value, None);
1826 }
1827
1828 #[test]
1829 fn test_option_some_untagged() {
1830 let doc = eure!({ value = 42 });
1832 let root_id = doc.get_root_id();
1833 let rec = doc.parse_record(root_id).unwrap();
1834 let value: Option<i32> = rec.parse_field("value").unwrap();
1835 assert_eq!(value, Some(42));
1836 }
1837
1838 #[test]
1839 fn test_option_none_untagged() {
1840 let doc = eure!({ value = null });
1842 let root_id = doc.get_root_id();
1843 let rec = doc.parse_record(root_id).unwrap();
1844 let value: Option<i32> = rec.parse_field("value").unwrap();
1845 assert_eq!(value, None);
1846 }
1847
1848 #[test]
1849 fn test_result_ok_tagged() {
1850 let doc = create_record_with_variant(
1851 "value",
1852 NodeValue::Primitive(PrimitiveValue::Integer(BigInt::from(42))),
1853 "ok",
1854 );
1855 let root_id = doc.get_root_id();
1856 let rec = doc.parse_record(root_id).unwrap();
1857 let value: Result<i32, String> = rec.parse_field("value").unwrap();
1858 assert_eq!(value, Ok(42));
1859 }
1860
1861 #[test]
1862 fn test_result_err_tagged() {
1863 let doc = create_record_with_variant(
1864 "value",
1865 NodeValue::Primitive(PrimitiveValue::Text(Text::plaintext(
1866 "error message".to_string(),
1867 ))),
1868 "err",
1869 );
1870 let root_id = doc.get_root_id();
1871 let rec = doc.parse_record(root_id).unwrap();
1872 let value: Result<i32, String> = rec.parse_field("value").unwrap();
1873 assert_eq!(value, Err("error message".to_string()));
1874 }
1875
1876 #[test]
1877 fn test_nested_result_option_ok_some() {
1878 let doc = create_record_with_variant(
1880 "value",
1881 NodeValue::Primitive(PrimitiveValue::Integer(BigInt::from(42))),
1882 "ok.some",
1883 );
1884 let root_id = doc.get_root_id();
1885 let rec = doc.parse_record(root_id).unwrap();
1886 let value: Result<Option<i32>, String> = rec.parse_field("value").unwrap();
1887 assert_eq!(value, Ok(Some(42)));
1888 }
1889
1890 #[test]
1891 fn test_nested_result_option_ok_none() {
1892 let doc = create_record_with_variant(
1894 "value",
1895 NodeValue::Primitive(PrimitiveValue::Null),
1896 "ok.none",
1897 );
1898 let root_id = doc.get_root_id();
1899 let rec = doc.parse_record(root_id).unwrap();
1900 let value: Result<Option<i32>, String> = rec.parse_field("value").unwrap();
1901 assert_eq!(value, Ok(None));
1902 }
1903
1904 #[test]
1905 fn test_nested_result_option_err() {
1906 let doc = create_record_with_variant(
1908 "value",
1909 NodeValue::Primitive(PrimitiveValue::Text(Text::plaintext("error".to_string()))),
1910 "err",
1911 );
1912 let root_id = doc.get_root_id();
1913 let rec = doc.parse_record(root_id).unwrap();
1914 let value: Result<Option<i32>, String> = rec.parse_field("value").unwrap();
1915 assert_eq!(value, Err("error".to_string()));
1916 }
1917
1918 #[test]
1919 fn test_deeply_nested_option_option() {
1920 let doc = create_record_with_variant(
1922 "value",
1923 NodeValue::Primitive(PrimitiveValue::Integer(BigInt::from(42))),
1924 "some.some",
1925 );
1926 let root_id = doc.get_root_id();
1927 let rec = doc.parse_record(root_id).unwrap();
1928 let value: Option<Option<i32>> = rec.parse_field("value").unwrap();
1929 assert_eq!(value, Some(Some(42)));
1930 }
1931
1932 #[test]
1933 fn test_deeply_nested_option_none() {
1934 let doc = create_record_with_variant(
1936 "value",
1937 NodeValue::Primitive(PrimitiveValue::Null),
1938 "some.none",
1939 );
1940 let root_id = doc.get_root_id();
1941 let rec = doc.parse_record(root_id).unwrap();
1942 let value: Option<Option<i32>> = rec.parse_field("value").unwrap();
1943 assert_eq!(value, Some(None));
1944 }
1945
1946 #[test]
1947 fn test_outer_none() {
1948 let doc =
1950 create_record_with_variant("value", NodeValue::Primitive(PrimitiveValue::Null), "none");
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, None);
1955 }
1956
1957 #[test]
1964 fn test_flatten_indexmap_marks_fields_as_accessed() {
1965 use indexmap::IndexMap;
1966
1967 let doc = eure!({
1968 name = "test"
1969 foo = "bar"
1970 baz = "qux"
1971 });
1972
1973 let root_id = doc.get_root_id();
1974 let rec = doc.parse_record(root_id).unwrap();
1975
1976 let _name: String = rec.parse_field("name").unwrap();
1978
1979 let extra: IndexMap<String, String> = rec.flatten().parse().unwrap();
1981
1982 assert_eq!(extra.get("foo"), Some(&"bar".to_string()));
1984 assert_eq!(extra.get("baz"), Some(&"qux".to_string()));
1985
1986 rec.deny_unknown_fields().unwrap();
1989 }
1990
1991 #[derive(Debug, PartialEq)]
1997 struct RemoteDuration {
1998 secs: u64,
1999 nanos: u32,
2000 }
2001
2002 struct RemoteDurationDef;
2004
2005 impl<'doc> FromEure<'doc, RemoteDuration> for RemoteDurationDef {
2006 type Error = ParseError;
2007
2008 fn parse(ctx: &ParseContext<'doc>) -> Result<RemoteDuration, Self::Error> {
2009 let rec = ctx.parse_record()?;
2010 let secs: u64 = rec.parse_field("secs")?;
2011 let nanos: u32 = rec.parse_field("nanos")?;
2012 rec.deny_unknown_fields()?;
2013 Ok(RemoteDuration { secs, nanos })
2014 }
2015 }
2016
2017 #[test]
2018 fn test_remote_type_basic_parsing() {
2019 let doc = eure!({ secs = 10, nanos = 500 });
2020 let root_id = doc.get_root_id();
2021
2022 let duration: RemoteDuration = doc.parse_via::<RemoteDurationDef, _>(root_id).unwrap();
2024
2025 assert_eq!(
2026 duration,
2027 RemoteDuration {
2028 secs: 10,
2029 nanos: 500
2030 }
2031 );
2032 }
2033
2034 #[test]
2035 fn test_remote_type_in_option() {
2036 let doc = eure!({ secs = 5, nanos = 0 });
2039 let root_id = doc.get_root_id();
2040
2041 let duration: Option<RemoteDuration> = doc
2043 .parse_via::<Option<RemoteDurationDef>, _>(root_id)
2044 .unwrap();
2045
2046 assert_eq!(duration, Some(RemoteDuration { secs: 5, nanos: 0 }));
2047 }
2048
2049 #[test]
2050 fn test_remote_type_in_option_none() {
2051 let doc = eure!({ = null });
2052 let root_id = doc.get_root_id();
2053
2054 let duration: Option<RemoteDuration> = doc
2055 .parse_via::<Option<RemoteDurationDef>, _>(root_id)
2056 .unwrap();
2057
2058 assert_eq!(duration, None);
2059 }
2060
2061 #[test]
2062 fn test_remote_type_in_vec() {
2063 let doc = eure!({
2064 items[] { secs = 1, nanos = 0 }
2065 items[] { secs = 2, nanos = 100 }
2066 });
2067 let root_id = doc.get_root_id();
2068 let rec = doc.parse_record(root_id).unwrap();
2069 let items_ctx = rec.field("items").unwrap();
2070
2071 let durations: Vec<RemoteDuration> =
2073 items_ctx.parse_via::<Vec<RemoteDurationDef>, _>().unwrap();
2074
2075 assert_eq!(
2076 durations,
2077 vec![
2078 RemoteDuration { secs: 1, nanos: 0 },
2079 RemoteDuration {
2080 secs: 2,
2081 nanos: 100
2082 },
2083 ]
2084 );
2085 }
2086
2087 #[test]
2088 fn test_remote_type_in_indexmap() {
2089 let doc = eure!({
2090 short { secs = 1, nanos = 0 }
2091 long { secs = 10, nanos = 0 }
2092 });
2093 let root_id = doc.get_root_id();
2094
2095 let durations: IndexMap<String, RemoteDuration> = doc
2097 .parse_via::<IndexMap<String, RemoteDurationDef>, _>(root_id)
2098 .unwrap();
2099
2100 assert_eq!(durations.len(), 2);
2101 assert_eq!(
2102 durations.get("short"),
2103 Some(&RemoteDuration { secs: 1, nanos: 0 })
2104 );
2105 assert_eq!(
2106 durations.get("long"),
2107 Some(&RemoteDuration { secs: 10, nanos: 0 })
2108 );
2109 }
2110
2111 #[test]
2112 fn test_remote_type_in_nested_containers() {
2113 let doc = eure!({
2115 items[] { secs = 1, nanos = 0 }
2116 });
2117 let root_id = doc.get_root_id();
2118 let rec = doc.parse_record(root_id).unwrap();
2119 let items_ctx = rec.field("items").unwrap();
2120
2121 let durations: Option<Vec<RemoteDuration>> = items_ctx
2123 .parse_via::<Option<Vec<RemoteDurationDef>>, _>()
2124 .unwrap();
2125
2126 assert_eq!(durations, Some(vec![RemoteDuration { secs: 1, nanos: 0 }]));
2127 }
2128
2129 #[test]
2130 fn test_parse_context_parse_via() {
2131 let doc = eure!({ secs = 42, nanos = 123 });
2132 let root_id = doc.get_root_id();
2133 let ctx = doc.parse_context(root_id);
2134
2135 let duration: RemoteDuration = ctx.parse_via::<RemoteDurationDef, _>().unwrap();
2137
2138 assert_eq!(
2139 duration,
2140 RemoteDuration {
2141 secs: 42,
2142 nanos: 123
2143 }
2144 );
2145 }
2146
2147 #[test]
2152 fn test_array_basic_parsing() {
2153 let doc = eure!({ items = [1, 2, 3] });
2154 let root_id = doc.get_root_id();
2155 let rec = doc.parse_record(root_id).unwrap();
2156 let items: [i32; 3] = rec.parse_field("items").unwrap();
2157 assert_eq!(items, [1, 2, 3]);
2158 }
2159
2160 #[test]
2161 fn test_array_empty() {
2162 let doc = eure!({ items = [] });
2163 let root_id = doc.get_root_id();
2164 let rec = doc.parse_record(root_id).unwrap();
2165 let items: [i32; 0] = rec.parse_field("items").unwrap();
2166 assert_eq!(items, []);
2167 }
2168
2169 #[test]
2170 fn test_array_length_mismatch_too_few() {
2171 let doc = eure!({ items = [1, 2] });
2172 let root_id = doc.get_root_id();
2173 let rec = doc.parse_record(root_id).unwrap();
2174 let result: Result<[i32; 3], _> = rec.parse_field("items");
2175 assert!(result.is_err());
2176 let err = result.unwrap_err();
2177 assert!(matches!(
2178 err.kind,
2179 ParseErrorKind::UnexpectedArrayLength {
2180 expected: 3,
2181 actual: 2
2182 }
2183 ));
2184 }
2185
2186 #[test]
2187 fn test_array_length_mismatch_too_many() {
2188 let doc = eure!({ items = [1, 2, 3, 4] });
2189 let root_id = doc.get_root_id();
2190 let rec = doc.parse_record(root_id).unwrap();
2191 let result: Result<[i32; 3], _> = rec.parse_field("items");
2192 assert!(result.is_err());
2193 let err = result.unwrap_err();
2194 assert!(matches!(
2195 err.kind,
2196 ParseErrorKind::UnexpectedArrayLength {
2197 expected: 3,
2198 actual: 4
2199 }
2200 ));
2201 }
2202
2203 #[test]
2204 fn test_array_nested_types() {
2205 let doc = eure!({ items = ["a", "b"] });
2206 let root_id = doc.get_root_id();
2207 let rec = doc.parse_record(root_id).unwrap();
2208 let items: [String; 2] = rec.parse_field("items").unwrap();
2209 assert_eq!(items, ["a".to_string(), "b".to_string()]);
2210 }
2211
2212 #[test]
2213 fn test_array_in_option() {
2214 let doc = eure!({ items = [1, 2, 3] });
2215 let root_id = doc.get_root_id();
2216 let rec = doc.parse_record(root_id).unwrap();
2217 let items: Option<[i32; 3]> = rec.parse_field("items").unwrap();
2218 assert_eq!(items, Some([1, 2, 3]));
2219 }
2220
2221 #[test]
2222 fn test_array_of_arrays() {
2223 let doc = eure!({ matrix = [[1, 2], [3, 4]] });
2224 let root_id = doc.get_root_id();
2225 let rec = doc.parse_record(root_id).unwrap();
2226 let matrix: [[i32; 2]; 2] = rec.parse_field("matrix").unwrap();
2227 assert_eq!(matrix, [[1, 2], [3, 4]]);
2228 }
2229
2230 #[test]
2231 fn test_array_remote_type() {
2232 let doc = eure!({
2233 items[] { secs = 1, nanos = 0 }
2234 items[] { secs = 2, nanos = 100 }
2235 });
2236 let root_id = doc.get_root_id();
2237 let rec = doc.parse_record(root_id).unwrap();
2238 let items_ctx = rec.field("items").unwrap();
2239
2240 let durations: [RemoteDuration; 2] =
2242 items_ctx.parse_via::<[RemoteDurationDef; 2], _>().unwrap();
2243
2244 assert_eq!(
2245 durations,
2246 [
2247 RemoteDuration { secs: 1, nanos: 0 },
2248 RemoteDuration {
2249 secs: 2,
2250 nanos: 100
2251 },
2252 ]
2253 );
2254 }
2255
2256 #[test]
2261 fn test_cow_static_str_from_eure() {
2262 use alloc::borrow::Cow;
2263
2264 let doc = eure!({ name = "hello" });
2265 let root_id = doc.get_root_id();
2266 let rec = doc.parse_record(root_id).unwrap();
2267 let value: Cow<'static, str> = rec.parse_field("name").unwrap();
2268 assert_eq!(value, Cow::<str>::Owned("hello".to_string()));
2269 }
2270}