1extern crate alloc;
4
5pub mod object_key;
6pub mod record;
7pub mod union;
8
9pub use object_key::ParseObjectKey;
10pub use record::{ExtParser, RecordParser};
11pub use union::UnionParser;
12
13use alloc::format;
14use num_bigint::BigInt;
15
16use crate::{
17 document::node::NodeArray, identifier::IdentifierError, prelude_internal::*, value::ValueKind,
18};
19
20pub trait ParseDocument<'doc>: Sized {
40 fn parse(doc: &'doc EureDocument, node_id: NodeId) -> Result<Self, ParseError>;
42}
43
44fn handle_unexpected_node_value(node_value: &NodeValue) -> ParseErrorKind {
45 match node_value {
46 NodeValue::Hole => ParseErrorKind::UnexpectedUninitialized,
47 value => value
48 .value_kind()
49 .map(|actual| ParseErrorKind::TypeMismatch {
50 expected: ValueKind::Text,
51 actual,
52 })
53 .unwrap_or_else(|| ParseErrorKind::UnexpectedUninitialized),
54 }
55}
56
57#[derive(Debug, thiserror::Error, Clone, PartialEq)]
58#[error("parse error: {kind}")]
59pub struct ParseError {
60 pub node_id: NodeId,
61 pub kind: ParseErrorKind,
62}
63
64#[derive(Debug, thiserror::Error, Clone, PartialEq)]
66pub enum ParseErrorKind {
67 #[error("unexpected uninitialized value")]
69 UnexpectedUninitialized,
70
71 #[error("type mismatch: expected {expected}, got {actual}")]
73 TypeMismatch {
74 expected: ValueKind,
75 actual: ValueKind,
76 },
77
78 #[error("missing field: {0}")]
80 MissingField(String),
81
82 #[error("missing extension: ${0}")]
84 MissingExtension(String),
85
86 #[error("unknown variant: {0}")]
88 UnknownVariant(String),
89
90 #[error("value out of range: {0}")]
92 OutOfRange(String),
93
94 #[error("invalid pattern: expected {pattern}, got {value}")]
96 InvalidPattern { pattern: String, value: String },
97
98 #[error("at {path}: {source}")]
100 Nested {
101 path: String,
102 #[source]
103 source: Box<ParseErrorKind>,
104 },
105
106 #[error("invalid identifier: {0}")]
108 InvalidIdentifier(#[from] IdentifierError),
109
110 #[error("unexpected tuple length: expected {expected}, got {actual}")]
112 UnexpectedTupleLength { expected: usize, actual: usize },
113
114 #[error("unknown field: {0}")]
116 UnknownField(String),
117
118 #[error("invalid key type in record: expected string key, got {0:?}")]
120 InvalidKeyType(crate::value::ObjectKey),
121
122 #[error("no matching variant")]
124 NoMatchingVariant,
125
126 #[error("ambiguous union: {0:?}")]
128 AmbiguousUnion(Vec<String>),
129
130 #[error("literal value mismatch: expected {expected:?}, got {actual:?}]")]
132 LiteralMismatch {
133 expected: Box<Value>,
134 actual: Box<Value>,
135 },
136}
137
138impl ParseErrorKind {
139 pub fn at(self, path: impl Into<String>) -> Self {
141 ParseErrorKind::Nested {
142 path: path.into(),
143 source: Box::new(self),
144 }
145 }
146}
147
148impl<'doc> EureDocument {
149 pub fn parse<T: ParseDocument<'doc>>(&'doc self, node_id: NodeId) -> Result<T, ParseError> {
150 T::parse(self, node_id)
151 }
152}
153
154impl<'doc> ParseDocument<'doc> for &'doc str {
155 fn parse(doc: &'doc EureDocument, node_id: NodeId) -> Result<Self, ParseError> {
156 match &doc.node(node_id).content {
157 NodeValue::Primitive(PrimitiveValue::Text(text)) => Ok(text.as_str()),
158 value => Err(ParseError {
159 node_id,
160 kind: handle_unexpected_node_value(value),
161 }),
162 }
163 }
164}
165
166impl ParseDocument<'_> for String {
167 fn parse(doc: &EureDocument, node_id: NodeId) -> Result<Self, ParseError> {
168 doc.parse::<&str>(node_id).map(String::from)
169 }
170}
171
172impl ParseDocument<'_> for bool {
173 fn parse(doc: &EureDocument, node_id: NodeId) -> Result<Self, ParseError> {
174 match &doc.node(node_id).content {
175 NodeValue::Primitive(PrimitiveValue::Bool(b)) => Ok(*b),
176 value => Err(ParseError {
177 node_id,
178 kind: handle_unexpected_node_value(value),
179 }),
180 }
181 }
182}
183
184impl ParseDocument<'_> for BigInt {
185 fn parse(doc: &EureDocument, node_id: NodeId) -> Result<Self, ParseError> {
186 match &doc.node(node_id).content {
187 NodeValue::Primitive(PrimitiveValue::Integer(i)) => Ok(i.clone()),
188 value => Err(ParseError {
189 node_id,
190 kind: handle_unexpected_node_value(value),
191 }),
192 }
193 }
194}
195
196impl ParseDocument<'_> for f32 {
197 fn parse(doc: &EureDocument, node_id: NodeId) -> Result<Self, ParseError> {
198 match &doc.node(node_id).content {
199 NodeValue::Primitive(PrimitiveValue::F32(f)) => Ok(*f),
200 value => Err(ParseError {
201 node_id,
202 kind: handle_unexpected_node_value(value),
203 }),
204 }
205 }
206}
207
208impl ParseDocument<'_> for f64 {
209 fn parse(doc: &EureDocument, node_id: NodeId) -> Result<Self, ParseError> {
210 match &doc.node(node_id).content {
211 NodeValue::Primitive(PrimitiveValue::F32(f)) => Ok(*f as f64),
213 value => Err(ParseError {
214 node_id,
215 kind: handle_unexpected_node_value(value),
216 }),
217 }
218 }
219}
220
221impl ParseDocument<'_> for u32 {
222 fn parse(doc: &EureDocument, node_id: NodeId) -> Result<Self, ParseError> {
223 let value: BigInt = doc.parse(node_id)?;
224 u32::try_from(&value).map_err(|_| ParseError {
225 node_id,
226 kind: ParseErrorKind::OutOfRange(format!("value {} out of u32 range", value)),
227 })
228 }
229}
230
231impl ParseDocument<'_> for i32 {
232 fn parse(doc: &EureDocument, node_id: NodeId) -> Result<Self, ParseError> {
233 let value: BigInt = doc.parse(node_id)?;
234 i32::try_from(&value).map_err(|_| ParseError {
235 node_id,
236 kind: ParseErrorKind::OutOfRange(format!("value {} out of i32 range", value)),
237 })
238 }
239}
240
241impl ParseDocument<'_> for i64 {
242 fn parse(doc: &EureDocument, node_id: NodeId) -> Result<Self, ParseError> {
243 let value: BigInt = doc.parse(node_id)?;
244 i64::try_from(&value).map_err(|_| ParseError {
245 node_id,
246 kind: ParseErrorKind::OutOfRange(format!("value {} out of i64 range", value)),
247 })
248 }
249}
250
251impl ParseDocument<'_> for u64 {
252 fn parse(doc: &EureDocument, node_id: NodeId) -> Result<Self, ParseError> {
253 let value: BigInt = doc.parse(node_id)?;
254 u64::try_from(&value).map_err(|_| ParseError {
255 node_id,
256 kind: ParseErrorKind::OutOfRange(format!("value {} out of u64 range", value)),
257 })
258 }
259}
260
261impl ParseDocument<'_> for usize {
262 fn parse(doc: &EureDocument, node_id: NodeId) -> Result<Self, ParseError> {
263 let value: BigInt = doc.parse(node_id)?;
264 usize::try_from(&value).map_err(|_| ParseError {
265 node_id,
266 kind: ParseErrorKind::OutOfRange(format!("value {} out of usize range", value)),
267 })
268 }
269}
270
271impl<'doc> ParseDocument<'doc> for &'doc PrimitiveValue {
272 fn parse(doc: &'doc EureDocument, node_id: NodeId) -> Result<Self, ParseError> {
273 match &doc.node(node_id).content {
274 NodeValue::Primitive(primitive) => Ok(primitive),
275 value => Err(ParseError {
276 node_id,
277 kind: handle_unexpected_node_value(value),
278 }),
279 }
280 }
281}
282
283impl ParseDocument<'_> for PrimitiveValue {
284 fn parse(doc: &EureDocument, node_id: NodeId) -> Result<Self, ParseError> {
285 doc.parse::<&PrimitiveValue>(node_id).cloned()
286 }
287}
288
289impl ParseDocument<'_> for Identifier {
290 fn parse(doc: &EureDocument, node_id: NodeId) -> Result<Self, ParseError> {
291 match &doc.node(node_id).content {
292 NodeValue::Primitive(PrimitiveValue::Text(text)) => Ok(text
293 .content
294 .parse()
295 .map_err(ParseErrorKind::InvalidIdentifier)
296 .map_err(|kind| ParseError { node_id, kind })?),
297 value => Err(ParseError {
298 node_id,
299 kind: handle_unexpected_node_value(value),
300 }),
301 }
302 }
303}
304
305impl<'doc> ParseDocument<'doc> for &'doc NodeArray {
306 fn parse(doc: &'doc EureDocument, node_id: NodeId) -> Result<Self, ParseError> {
307 match &doc.node(node_id).content {
308 NodeValue::Array(array) => Ok(array),
309 value => Err(handle_unexpected_node_value(value)),
310 }
311 .map_err(|kind| ParseError { node_id, kind })
312 }
313}
314
315impl<'doc, T> ParseDocument<'doc> for Vec<T>
316where
317 T: ParseDocument<'doc>,
318{
319 fn parse(doc: &'doc EureDocument, node_id: NodeId) -> Result<Self, ParseError> {
320 match &doc.node(node_id).content {
321 NodeValue::Array(array) => array
322 .iter()
323 .map(|item| T::parse(doc, *item))
324 .collect::<Result<Vec<_>, _>>(),
325 value => Err(ParseError {
326 node_id,
327 kind: handle_unexpected_node_value(value),
328 }),
329 }
330 }
331}
332
333macro_rules! parse_tuple {
334 ($n:expr, $($var:ident),*) => {
335 impl<'doc, $($var: ParseDocument<'doc>),*> ParseDocument<'doc> for ($($var),*,) {
336 fn parse(doc: &'doc EureDocument, node_id: NodeId) -> Result<Self, ParseError> {
337 let tuple = match &doc.node(node_id).content {
338 NodeValue::Tuple(tuple) => tuple,
339 value => return Err(ParseError { node_id, kind: handle_unexpected_node_value(value) }),
340 };
341 if tuple.len() != $n {
342 return Err(ParseError { node_id, kind: ParseErrorKind::UnexpectedTupleLength { expected: $n, actual: tuple.len() } });
343 }
344 let mut iter = tuple.iter();
345 Ok(($($var::parse(doc, *iter.next().unwrap())?),*,))
346 }
347 }
348 }
349}
350
351parse_tuple!(1, A);
352parse_tuple!(2, A, B);
353parse_tuple!(3, A, B, C);
354parse_tuple!(4, A, B, C, D);
355parse_tuple!(5, A, B, C, D, E);
356parse_tuple!(6, A, B, C, D, E, F);
357parse_tuple!(7, A, B, C, D, E, F, G);
358parse_tuple!(8, A, B, C, D, E, F, G, H);
359parse_tuple!(9, A, B, C, D, E, F, G, H, I);
360parse_tuple!(10, A, B, C, D, E, F, G, H, I, J);
361parse_tuple!(11, A, B, C, D, E, F, G, H, I, J, K);
362parse_tuple!(12, A, B, C, D, E, F, G, H, I, J, K, L);
363parse_tuple!(13, A, B, C, D, E, F, G, H, I, J, K, L, M);
364parse_tuple!(14, A, B, C, D, E, F, G, H, I, J, K, L, M, N);
365parse_tuple!(15, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
366parse_tuple!(16, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
367
368impl<'doc, K, T> ParseDocument<'doc> for Map<K, T>
369where
370 K: ParseObjectKey<'doc>,
371 T: ParseDocument<'doc>,
372{
373 fn parse(doc: &'doc EureDocument, node_id: NodeId) -> Result<Self, ParseError> {
374 let map = match &doc.node(node_id).content {
375 NodeValue::Map(map) => map,
376 value => {
377 return Err(ParseError {
378 node_id,
379 kind: handle_unexpected_node_value(value),
380 });
381 }
382 };
383 map.iter()
384 .map(|(key, value)| {
385 Ok((
386 K::from_object_key(key).map_err(|kind| ParseError { node_id, kind })?,
387 T::parse(doc, *value)?,
388 ))
389 })
390 .collect::<Result<Map<_, _>, _>>()
391 }
392}
393
394impl ParseDocument<'_> for crate::data_model::VariantRepr {
395 fn parse(doc: &EureDocument, node_id: NodeId) -> Result<Self, ParseError> {
396 use crate::data_model::VariantRepr;
397
398 if let Ok(value) = doc.parse::<&str>(node_id) {
400 return match value {
401 "external" => Ok(VariantRepr::External),
402 "untagged" => Ok(VariantRepr::Untagged),
403 _ => Err(ParseError {
404 node_id,
405 kind: ParseErrorKind::UnknownVariant(value.to_string()),
406 }),
407 };
408 }
409
410 let mut rec = doc.parse_record(node_id)?;
412
413 let tag = rec.field_optional::<String>("tag")?;
414 let content = rec.field_optional::<String>("content")?;
415
416 rec.allow_unknown_fields()?;
417
418 match (tag, content) {
419 (Some(tag), Some(content)) => Ok(VariantRepr::Adjacent { tag, content }),
420 (Some(tag), None) => Ok(VariantRepr::Internal { tag }),
421 (None, None) => Ok(VariantRepr::External),
422 (None, Some(_)) => Err(ParseError {
423 node_id,
424 kind: ParseErrorKind::MissingField(
425 "tag (required when content is present)".to_string(),
426 ),
427 }),
428 }
429 }
430}
431
432pub trait DocumentParser<'doc> {
433 type Output: 'doc;
434 fn parse(self, doc: &'doc EureDocument, node_id: NodeId) -> Result<Self::Output, ParseError>;
435}
436
437impl<'doc, T: 'doc, F> DocumentParser<'doc> for F
438where
439 F: FnOnce(&'doc EureDocument, NodeId) -> Result<T, ParseError>,
440{
441 type Output = T;
442 fn parse(self, doc: &'doc EureDocument, node_id: NodeId) -> Result<Self::Output, ParseError> {
443 self(doc, node_id)
444 }
445}
446
447pub struct LiteralParser<T>(T);
448
449impl<'doc, T> DocumentParser<'doc> for LiteralParser<T>
450where
451 T: 'doc + ParseDocument<'doc> + PartialEq + Into<Value>,
452{
453 type Output = T;
454 fn parse(self, doc: &'doc EureDocument, node_id: NodeId) -> Result<Self::Output, ParseError> {
455 let value: T = doc.parse(node_id)?;
456 if value == self.0 {
457 Ok(value)
458 } else {
459 Err(ParseError {
460 node_id,
461 kind: ParseErrorKind::LiteralMismatch {
462 expected: Box::new(self.0.into()),
463 actual: Box::new(value.into()),
464 },
465 })
466 }
467 }
468}
469
470pub struct MappedParser<T, F> {
471 parser: T,
472 mapper: F,
473}
474
475impl<'doc, T, O, F> DocumentParser<'doc> for MappedParser<T, F>
476where
477 T: DocumentParser<'doc>,
478 F: Fn(T::Output) -> Result<O, ParseError>,
479 O: 'doc,
480{
481 type Output = O;
482 fn parse(self, doc: &'doc EureDocument, node_id: NodeId) -> Result<Self::Output, ParseError> {
483 let value = self.parser.parse(doc, node_id)?;
484 (self.mapper)(value)
485 }
486}
487
488pub trait DocumentParserExt<'doc>: DocumentParser<'doc> + Sized {
489 fn map<O, F>(self, mapper: F) -> MappedParser<Self, F>
490 where
491 F: Fn(Self::Output) -> Result<O, ParseError>,
492 O: 'doc,
493 {
494 MappedParser {
495 parser: self,
496 mapper,
497 }
498 }
499}