Skip to main content

serde_eure/
de.rs

1use std::borrow::Cow;
2use std::collections::HashSet;
3use std::fmt;
4
5use eure::document::EureDocument;
6use eure::document::constructor::DocumentConstructor;
7use eure::document::identifier::Identifier;
8use eure::document::node::NodeValue;
9use eure::document::parse::VariantPath;
10use eure::document::path::{ArrayIndexKind, PathSegment};
11use eure::value::{ObjectKey, PrimitiveValue, Text, Tuple};
12use eure_schema::interop::VariantRepr;
13use eure_schema::{
14    SchemaDocument, SchemaNodeContent, SchemaNodeId, UnionSchema, UnknownFieldsPolicy,
15};
16use num_bigint::BigInt;
17use serde::Deserialize;
18use serde::de::Error as _;
19use serde::de::{self, DeserializeSeed, IntoDeserializer, MapAccess, SeqAccess, Visitor};
20
21use crate::error::DeError;
22
23#[derive(Debug, Clone)]
24enum EureContent<'de> {
25    Bool(bool),
26    I8(i8),
27    I16(i16),
28    I32(i32),
29    I64(i64),
30    I128(i128),
31    U8(u8),
32    U16(u16),
33    U32(u32),
34    U64(u64),
35    U128(u128),
36    F32(f32),
37    F64(f64),
38    Char(char),
39    String(Cow<'de, str>),
40    Bytes(Cow<'de, [u8]>),
41    Unit,
42    Seq(Vec<EureContent<'de>>),
43    Map(Vec<(EureContent<'de>, EureContent<'de>)>),
44}
45
46impl<'de> Deserialize<'de> for EureContent<'de> {
47    fn deserialize<D>(de: D) -> Result<Self, D::Error>
48    where
49        D: serde::Deserializer<'de>,
50    {
51        de.deserialize_any(EureContentVisitor)
52    }
53}
54
55impl<'de> serde::Deserializer<'de> for EureContent<'de> {
56    type Error = DeError;
57
58    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
59    where
60        V: Visitor<'de>,
61    {
62        match self {
63            Self::Bool(value) => visitor.visit_bool(value),
64            Self::I8(value) => visitor.visit_i8(value),
65            Self::I16(value) => visitor.visit_i16(value),
66            Self::I32(value) => visitor.visit_i32(value),
67            Self::I64(value) => visitor.visit_i64(value),
68            Self::I128(value) => visitor.visit_i128(value),
69            Self::U8(value) => visitor.visit_u8(value),
70            Self::U16(value) => visitor.visit_u16(value),
71            Self::U32(value) => visitor.visit_u32(value),
72            Self::U64(value) => visitor.visit_u64(value),
73            Self::U128(value) => visitor.visit_u128(value),
74            Self::F32(value) => visitor.visit_f32(value),
75            Self::F64(value) => visitor.visit_f64(value),
76            Self::Char(value) => visitor.visit_char(value),
77            Self::String(Cow::Borrowed(value)) => visitor.visit_borrowed_str(value),
78            Self::String(Cow::Owned(value)) => visitor.visit_string(value),
79            Self::Bytes(Cow::Borrowed(value)) => visitor.visit_borrowed_bytes(value),
80            Self::Bytes(Cow::Owned(value)) => visitor.visit_byte_buf(value),
81            Self::Unit => visitor.visit_unit(),
82            Self::Seq(values) => visitor.visit_seq(EureContentSeqAccess {
83                iter: values.into_iter(),
84            }),
85            Self::Map(entries) => visitor.visit_map(EureContentMapAccess {
86                iter: entries.into_iter(),
87                pending_value: None,
88            }),
89        }
90    }
91
92    fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
93    where
94        V: Visitor<'de>,
95    {
96        match self {
97            Self::Bool(value) => visitor.visit_bool(value),
98            other => Err(type_mismatch("boolean", eure_content_type(&other))),
99        }
100    }
101
102    fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
103    where
104        V: Visitor<'de>,
105    {
106        match self {
107            Self::I8(value) => visitor.visit_i8(value),
108            other => Err(type_mismatch("integer", eure_content_type(&other))),
109        }
110    }
111
112    fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
113    where
114        V: Visitor<'de>,
115    {
116        match self {
117            Self::I16(value) => visitor.visit_i16(value),
118            other => Err(type_mismatch("integer", eure_content_type(&other))),
119        }
120    }
121
122    fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
123    where
124        V: Visitor<'de>,
125    {
126        match self {
127            Self::I32(value) => visitor.visit_i32(value),
128            other => Err(type_mismatch("integer", eure_content_type(&other))),
129        }
130    }
131
132    fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
133    where
134        V: Visitor<'de>,
135    {
136        // Accept any integer variant — the visitor handles all widths.
137        match self {
138            Self::I8(v) => visitor.visit_i8(v),
139            Self::I16(v) => visitor.visit_i16(v),
140            Self::I32(v) => visitor.visit_i32(v),
141            Self::I64(v) => visitor.visit_i64(v),
142            Self::I128(v) => visitor.visit_i128(v),
143            Self::U8(v) => visitor.visit_u8(v),
144            Self::U16(v) => visitor.visit_u16(v),
145            Self::U32(v) => visitor.visit_u32(v),
146            Self::U64(v) => visitor.visit_u64(v),
147            Self::U128(v) => visitor.visit_u128(v),
148            other => Err(type_mismatch("integer", eure_content_type(&other))),
149        }
150    }
151
152    fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
153    where
154        V: Visitor<'de>,
155    {
156        match self {
157            Self::I128(value) => visitor.visit_i128(value),
158            other => Err(type_mismatch("integer", eure_content_type(&other))),
159        }
160    }
161
162    fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
163    where
164        V: Visitor<'de>,
165    {
166        match self {
167            Self::U8(value) => visitor.visit_u8(value),
168            other => Err(type_mismatch("integer", eure_content_type(&other))),
169        }
170    }
171
172    fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
173    where
174        V: Visitor<'de>,
175    {
176        match self {
177            Self::U16(value) => visitor.visit_u16(value),
178            other => Err(type_mismatch("integer", eure_content_type(&other))),
179        }
180    }
181
182    fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
183    where
184        V: Visitor<'de>,
185    {
186        match self {
187            Self::U32(value) => visitor.visit_u32(value),
188            other => Err(type_mismatch("integer", eure_content_type(&other))),
189        }
190    }
191
192    fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
193    where
194        V: Visitor<'de>,
195    {
196        match self {
197            Self::U64(value) => visitor.visit_u64(value),
198            other => Err(type_mismatch("integer", eure_content_type(&other))),
199        }
200    }
201
202    fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
203    where
204        V: Visitor<'de>,
205    {
206        match self {
207            Self::U128(value) => visitor.visit_u128(value),
208            other => Err(type_mismatch("integer", eure_content_type(&other))),
209        }
210    }
211
212    fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
213    where
214        V: Visitor<'de>,
215    {
216        match self {
217            Self::F32(value) => visitor.visit_f32(value),
218            other => Err(type_mismatch("float", eure_content_type(&other))),
219        }
220    }
221
222    fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
223    where
224        V: Visitor<'de>,
225    {
226        match self {
227            Self::F32(v) => visitor.visit_f32(v),
228            Self::F64(v) => visitor.visit_f64(v),
229            // Accept integer types via coercion (some formats send ints for float fields).
230            Self::I8(v) => visitor.visit_f64(v as f64),
231            Self::I16(v) => visitor.visit_f64(v as f64),
232            Self::I32(v) => visitor.visit_f64(v as f64),
233            Self::I64(v) => visitor.visit_f64(v as f64),
234            Self::I128(v) => visitor.visit_f64(v as f64),
235            Self::U8(v) => visitor.visit_f64(v as f64),
236            Self::U16(v) => visitor.visit_f64(v as f64),
237            Self::U32(v) => visitor.visit_f64(v as f64),
238            Self::U64(v) => visitor.visit_f64(v as f64),
239            Self::U128(v) => visitor.visit_f64(v as f64),
240            other => Err(type_mismatch("float", eure_content_type(&other))),
241        }
242    }
243
244    fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
245    where
246        V: Visitor<'de>,
247    {
248        match self {
249            Self::Char(value) => visitor.visit_char(value),
250            other => Err(type_mismatch("text", eure_content_type(&other))),
251        }
252    }
253
254    fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
255    where
256        V: Visitor<'de>,
257    {
258        match self {
259            Self::String(Cow::Borrowed(value)) => visitor.visit_borrowed_str(value),
260            Self::String(Cow::Owned(value)) => visitor.visit_string(value),
261            other => Err(type_mismatch("text", eure_content_type(&other))),
262        }
263    }
264
265    fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
266    where
267        V: Visitor<'de>,
268    {
269        self.deserialize_str(visitor)
270    }
271
272    fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error>
273    where
274        V: Visitor<'de>,
275    {
276        match self {
277            Self::Bytes(Cow::Borrowed(value)) => visitor.visit_borrowed_bytes(value),
278            Self::Bytes(Cow::Owned(value)) => visitor.visit_byte_buf(value),
279            other => Err(type_mismatch("bytes", eure_content_type(&other))),
280        }
281    }
282
283    fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error>
284    where
285        V: Visitor<'de>,
286    {
287        self.deserialize_bytes(visitor)
288    }
289
290    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
291    where
292        V: Visitor<'de>,
293    {
294        match self {
295            Self::Unit => visitor.visit_none(),
296            other => visitor.visit_some(other),
297        }
298    }
299
300    fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
301    where
302        V: Visitor<'de>,
303    {
304        match self {
305            Self::Unit => visitor.visit_unit(),
306            other => Err(type_mismatch("null", eure_content_type(&other))),
307        }
308    }
309
310    fn deserialize_unit_struct<V>(
311        self,
312        _name: &'static str,
313        visitor: V,
314    ) -> Result<V::Value, Self::Error>
315    where
316        V: Visitor<'de>,
317    {
318        self.deserialize_unit(visitor)
319    }
320
321    fn deserialize_newtype_struct<V>(
322        self,
323        _name: &'static str,
324        visitor: V,
325    ) -> Result<V::Value, Self::Error>
326    where
327        V: Visitor<'de>,
328    {
329        visitor.visit_newtype_struct(self)
330    }
331
332    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
333    where
334        V: Visitor<'de>,
335    {
336        match self {
337            Self::Seq(values) => visitor.visit_seq(EureContentSeqAccess {
338                iter: values.into_iter(),
339            }),
340            other => Err(type_mismatch("array", eure_content_type(&other))),
341        }
342    }
343
344    fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
345    where
346        V: Visitor<'de>,
347    {
348        self.deserialize_seq(visitor)
349    }
350
351    fn deserialize_tuple_struct<V>(
352        self,
353        _name: &'static str,
354        _len: usize,
355        visitor: V,
356    ) -> Result<V::Value, Self::Error>
357    where
358        V: Visitor<'de>,
359    {
360        self.deserialize_seq(visitor)
361    }
362
363    fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
364    where
365        V: Visitor<'de>,
366    {
367        match self {
368            Self::Map(entries) => visitor.visit_map(EureContentMapAccess {
369                iter: entries.into_iter(),
370                pending_value: None,
371            }),
372            other => Err(type_mismatch("map", eure_content_type(&other))),
373        }
374    }
375
376    fn deserialize_struct<V>(
377        self,
378        _name: &'static str,
379        _fields: &'static [&'static str],
380        visitor: V,
381    ) -> Result<V::Value, Self::Error>
382    where
383        V: Visitor<'de>,
384    {
385        self.deserialize_map(visitor)
386    }
387
388    fn deserialize_enum<V>(
389        self,
390        _name: &'static str,
391        _variants: &'static [&'static str],
392        _visitor: V,
393    ) -> Result<V::Value, Self::Error>
394    where
395        V: Visitor<'de>,
396    {
397        Err(DeError::Custom(
398            "enum deserialization is unsupported for EureContent".to_string(),
399        ))
400    }
401
402    fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
403    where
404        V: Visitor<'de>,
405    {
406        match self {
407            Self::String(Cow::Borrowed(value)) => visitor.visit_borrowed_str(value),
408            Self::String(Cow::Owned(value)) => visitor.visit_string(value),
409            Self::Char(value) => visitor.visit_string(value.to_string()),
410            other => Err(type_mismatch("text", eure_content_type(&other))),
411        }
412    }
413
414    fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
415    where
416        V: Visitor<'de>,
417    {
418        visitor.visit_unit()
419    }
420}
421
422impl<'de> IntoDeserializer<'de, DeError> for EureContent<'de> {
423    type Deserializer = Self;
424
425    fn into_deserializer(self) -> Self::Deserializer {
426        self
427    }
428}
429
430struct EureContentVisitor;
431
432impl<'de> Visitor<'de> for EureContentVisitor {
433    type Value = EureContent<'de>;
434
435    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
436        formatter.write_str("any serde value")
437    }
438
439    fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E> {
440        Ok(EureContent::Bool(value))
441    }
442
443    fn visit_i8<E>(self, value: i8) -> Result<Self::Value, E> {
444        Ok(EureContent::I8(value))
445    }
446
447    fn visit_i16<E>(self, value: i16) -> Result<Self::Value, E> {
448        Ok(EureContent::I16(value))
449    }
450
451    fn visit_i32<E>(self, value: i32) -> Result<Self::Value, E> {
452        Ok(EureContent::I32(value))
453    }
454
455    fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E> {
456        Ok(EureContent::I64(value))
457    }
458
459    fn visit_i128<E>(self, value: i128) -> Result<Self::Value, E> {
460        Ok(EureContent::I128(value))
461    }
462
463    fn visit_u8<E>(self, value: u8) -> Result<Self::Value, E> {
464        Ok(EureContent::U8(value))
465    }
466
467    fn visit_u16<E>(self, value: u16) -> Result<Self::Value, E> {
468        Ok(EureContent::U16(value))
469    }
470
471    fn visit_u32<E>(self, value: u32) -> Result<Self::Value, E> {
472        Ok(EureContent::U32(value))
473    }
474
475    fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E> {
476        Ok(EureContent::U64(value))
477    }
478
479    fn visit_u128<E>(self, value: u128) -> Result<Self::Value, E> {
480        Ok(EureContent::U128(value))
481    }
482
483    fn visit_f32<E>(self, value: f32) -> Result<Self::Value, E> {
484        Ok(EureContent::F32(value))
485    }
486
487    fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E> {
488        Ok(EureContent::F64(value))
489    }
490
491    fn visit_char<E>(self, value: char) -> Result<Self::Value, E> {
492        Ok(EureContent::Char(value))
493    }
494
495    fn visit_borrowed_str<E>(self, value: &'de str) -> Result<Self::Value, E> {
496        Ok(EureContent::String(Cow::Borrowed(value)))
497    }
498
499    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
500    where
501        E: de::Error,
502    {
503        Ok(EureContent::String(Cow::Owned(value.to_owned())))
504    }
505
506    fn visit_string<E>(self, value: String) -> Result<Self::Value, E> {
507        Ok(EureContent::String(Cow::Owned(value)))
508    }
509
510    fn visit_borrowed_bytes<E>(self, value: &'de [u8]) -> Result<Self::Value, E> {
511        Ok(EureContent::Bytes(Cow::Borrowed(value)))
512    }
513
514    fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
515    where
516        E: de::Error,
517    {
518        Ok(EureContent::Bytes(Cow::Owned(value.to_vec())))
519    }
520
521    fn visit_byte_buf<E>(self, value: Vec<u8>) -> Result<Self::Value, E> {
522        Ok(EureContent::Bytes(Cow::Owned(value)))
523    }
524
525    fn visit_unit<E>(self) -> Result<Self::Value, E> {
526        Ok(EureContent::Unit)
527    }
528
529    fn visit_none<E>(self) -> Result<Self::Value, E> {
530        Ok(EureContent::Unit)
531    }
532
533    fn visit_some<D>(self, de: D) -> Result<Self::Value, D::Error>
534    where
535        D: serde::Deserializer<'de>,
536    {
537        EureContent::deserialize(de)
538    }
539
540    fn visit_newtype_struct<D>(self, de: D) -> Result<Self::Value, D::Error>
541    where
542        D: serde::Deserializer<'de>,
543    {
544        EureContent::deserialize(de)
545    }
546
547    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
548    where
549        A: SeqAccess<'de>,
550    {
551        let mut values = Vec::new();
552        while let Some(value) = seq.next_element::<EureContent<'de>>()? {
553            values.push(value);
554        }
555        Ok(EureContent::Seq(values))
556    }
557
558    fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
559    where
560        A: MapAccess<'de>,
561    {
562        let mut entries = Vec::new();
563        while let Some((key, value)) = map.next_entry::<EureContent<'de>, EureContent<'de>>()? {
564            entries.push((key, value));
565        }
566        Ok(EureContent::Map(entries))
567    }
568}
569
570struct EureContentMapVisitor;
571
572impl<'de> Visitor<'de> for EureContentMapVisitor {
573    type Value = EureContent<'de>;
574
575    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
576        formatter.write_str("a map")
577    }
578
579    fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
580    where
581        A: MapAccess<'de>,
582    {
583        let mut entries = Vec::new();
584        // Use EureContent for keys to support non-string key types (integer, bool, etc.)
585        // from formats like MessagePack/YAML. Tag lookup uses content_key_matches which
586        // handles EureContent::String comparison correctly.
587        while let Some((key, value)) = map.next_entry::<EureContent<'de>, EureContent<'de>>()? {
588            entries.push((key, value));
589        }
590        Ok(EureContent::Map(entries))
591    }
592}
593
594struct EureContentSeqAccess<'de> {
595    iter: std::vec::IntoIter<EureContent<'de>>,
596}
597
598impl<'de> SeqAccess<'de> for EureContentSeqAccess<'de> {
599    type Error = DeError;
600
601    fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
602    where
603        T: DeserializeSeed<'de>,
604    {
605        match self.iter.next() {
606            Some(value) => seed.deserialize(value).map(Some),
607            None => Ok(None),
608        }
609    }
610
611    fn size_hint(&self) -> Option<usize> {
612        Some(self.iter.len())
613    }
614}
615
616struct EureContentMapAccess<'de> {
617    iter: std::vec::IntoIter<(EureContent<'de>, EureContent<'de>)>,
618    pending_value: Option<EureContent<'de>>,
619}
620
621impl<'de> MapAccess<'de> for EureContentMapAccess<'de> {
622    type Error = DeError;
623
624    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
625    where
626        K: DeserializeSeed<'de>,
627    {
628        match self.iter.next() {
629            Some((key, value)) => {
630                self.pending_value = Some(value);
631                seed.deserialize(key).map(Some)
632            }
633            None => Ok(None),
634        }
635    }
636
637    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
638    where
639        V: DeserializeSeed<'de>,
640    {
641        let value = self.pending_value.take().ok_or_else(|| {
642            DeError::Custom("map value requested before reading a key".to_string())
643        })?;
644        seed.deserialize(value)
645    }
646
647    fn size_hint(&self) -> Option<usize> {
648        Some(self.iter.len() + usize::from(self.pending_value.is_some()))
649    }
650}
651
652pub struct EureDocumentSeed<'s> {
653    pub schema: &'s SchemaDocument,
654    pub schema_node_id: SchemaNodeId,
655    pub constructor: &'s mut DocumentConstructor,
656}
657
658impl<'de, 's> DeserializeSeed<'de> for EureDocumentSeed<'s> {
659    type Value = ();
660
661    fn deserialize<D>(self, de: D) -> Result<Self::Value, D::Error>
662    where
663        D: serde::Deserializer<'de>,
664    {
665        let schema_node_id =
666            resolve_schema_node_id(self.schema, self.schema_node_id).map_err(D::Error::custom)?;
667
668        match &self.schema.node(schema_node_id).content {
669            SchemaNodeContent::Any => de.deserialize_any(AnyVisitor {
670                constructor: self.constructor,
671            }),
672            SchemaNodeContent::Text(_) => de.deserialize_str(TextVisitor {
673                constructor: self.constructor,
674            }),
675            SchemaNodeContent::Integer(_) => de.deserialize_i64(IntegerVisitor {
676                constructor: self.constructor,
677            }),
678            SchemaNodeContent::Float(_) => de.deserialize_f64(FloatVisitor {
679                constructor: self.constructor,
680            }),
681            SchemaNodeContent::Boolean => de.deserialize_bool(BoolVisitor {
682                constructor: self.constructor,
683            }),
684            SchemaNodeContent::Null => de.deserialize_unit(NullVisitor {
685                constructor: self.constructor,
686            }),
687            SchemaNodeContent::Array(s) => de.deserialize_seq(SeqVisitor {
688                schema: self.schema,
689                item_schema_id: s.item,
690                constructor: self.constructor,
691            }),
692            SchemaNodeContent::Tuple(s) => de.deserialize_seq(TupleVisitor {
693                schema: self.schema,
694                elements: &s.elements,
695                constructor: self.constructor,
696            }),
697            SchemaNodeContent::Map(s) => de.deserialize_map(MapVisitor {
698                schema: self.schema,
699                key_schema_id: s.key,
700                value_schema_id: s.value,
701                constructor: self.constructor,
702            }),
703            SchemaNodeContent::Record(s) => de.deserialize_map(RecordVisitor {
704                schema: self.schema,
705                record_schema: s,
706                constructor: self.constructor,
707            }),
708            SchemaNodeContent::Union(u) => {
709                deserialize_union(de, self.schema, u, schema_node_id, self.constructor)
710            }
711            // Literal: accept any value and write it as-is. serde-eure is a bridge,
712            // not a validator. Callers that need literal enforcement should run the
713            // schema validator on the resulting EureDocument afterward.
714            SchemaNodeContent::Literal(_) => de.deserialize_any(AnyVisitor {
715                constructor: self.constructor,
716            }),
717            SchemaNodeContent::Reference(_) => unreachable!("references are resolved above"),
718        }
719    }
720}
721
722pub fn from_deserializer<'de, D: serde::Deserializer<'de>>(
723    de: D,
724    schema: &SchemaDocument,
725) -> Result<EureDocument, DeError> {
726    let mut constructor = DocumentConstructor::new();
727    EureDocumentSeed {
728        schema,
729        schema_node_id: schema.root,
730        constructor: &mut constructor,
731    }
732    .deserialize(de)
733    .map_err(DeError::custom)?;
734    Ok(constructor.finish())
735}
736
737struct AnySeed<'s> {
738    constructor: &'s mut DocumentConstructor,
739}
740
741impl<'de> DeserializeSeed<'de> for AnySeed<'_> {
742    type Value = ();
743
744    fn deserialize<D>(self, de: D) -> Result<Self::Value, D::Error>
745    where
746        D: serde::Deserializer<'de>,
747    {
748        de.deserialize_any(AnyVisitor {
749            constructor: self.constructor,
750        })
751    }
752}
753
754struct AnyObjectKeySeed;
755
756impl<'de> DeserializeSeed<'de> for AnyObjectKeySeed {
757    type Value = ObjectKey;
758
759    fn deserialize<D>(self, de: D) -> Result<Self::Value, D::Error>
760    where
761        D: serde::Deserializer<'de>,
762    {
763        de.deserialize_any(AnyObjectKeyVisitor)
764    }
765}
766
767struct ObjectKeySeed<'s> {
768    schema: &'s SchemaDocument,
769    schema_node_id: SchemaNodeId,
770}
771
772impl<'de> DeserializeSeed<'de> for ObjectKeySeed<'_> {
773    type Value = ObjectKey;
774
775    fn deserialize<D>(self, de: D) -> Result<Self::Value, D::Error>
776    where
777        D: serde::Deserializer<'de>,
778    {
779        let schema_node_id =
780            resolve_schema_node_id(self.schema, self.schema_node_id).map_err(D::Error::custom)?;
781
782        match &self.schema.node(schema_node_id).content {
783            SchemaNodeContent::Any => de.deserialize_any(AnyObjectKeyVisitor),
784            SchemaNodeContent::Text(_) => de.deserialize_any(TextObjectKeyVisitor),
785            SchemaNodeContent::Integer(_) => de.deserialize_any(IntegerObjectKeyVisitor),
786            SchemaNodeContent::Boolean => de.deserialize_any(BoolObjectKeyVisitor),
787            SchemaNodeContent::Literal(expected) => {
788                de.deserialize_any(LiteralObjectKeyVisitor { expected })
789            }
790            SchemaNodeContent::Tuple(tuple_schema) => de.deserialize_seq(TupleObjectKeyVisitor {
791                schema: self.schema,
792                elements: &tuple_schema.elements,
793            }),
794            SchemaNodeContent::Union(union_schema) => de.deserialize_any(UnionObjectKeyVisitor {
795                schema: self.schema,
796                union_schema,
797            }),
798            SchemaNodeContent::Reference(_) => unreachable!("references are resolved above"),
799            SchemaNodeContent::Float(_)
800            | SchemaNodeContent::Null
801            | SchemaNodeContent::Array(_)
802            | SchemaNodeContent::Map(_)
803            | SchemaNodeContent::Record(_) => {
804                Err(D::Error::custom(unsupported_complex_map_keys().to_string()))
805            }
806        }
807    }
808}
809
810struct ArrayElementSeed<'s> {
811    schema: &'s SchemaDocument,
812    item_schema_id: SchemaNodeId,
813    constructor: &'s mut DocumentConstructor,
814}
815
816impl<'de> DeserializeSeed<'de> for ArrayElementSeed<'_> {
817    type Value = ();
818
819    fn deserialize<D>(self, de: D) -> Result<Self::Value, D::Error>
820    where
821        D: serde::Deserializer<'de>,
822    {
823        let scope = self.constructor.begin_scope();
824        self.constructor
825            .navigate(PathSegment::ArrayIndex(ArrayIndexKind::Push))
826            .map_err(D::Error::custom)?;
827        EureDocumentSeed {
828            schema: self.schema,
829            schema_node_id: self.item_schema_id,
830            constructor: self.constructor,
831        }
832        .deserialize(de)?;
833        self.constructor
834            .end_scope(scope)
835            .map_err(D::Error::custom)?;
836        Ok(())
837    }
838}
839
840struct AnyArrayElementSeed<'s> {
841    constructor: &'s mut DocumentConstructor,
842}
843
844impl<'de> DeserializeSeed<'de> for AnyArrayElementSeed<'_> {
845    type Value = ();
846
847    fn deserialize<D>(self, de: D) -> Result<Self::Value, D::Error>
848    where
849        D: serde::Deserializer<'de>,
850    {
851        let scope = self.constructor.begin_scope();
852        self.constructor
853            .navigate(PathSegment::ArrayIndex(ArrayIndexKind::Push))
854            .map_err(D::Error::custom)?;
855        AnySeed {
856            constructor: self.constructor,
857        }
858        .deserialize(de)?;
859        self.constructor
860            .end_scope(scope)
861            .map_err(D::Error::custom)?;
862        Ok(())
863    }
864}
865
866struct TupleElementSeed<'s> {
867    schema: &'s SchemaDocument,
868    element_schema_id: SchemaNodeId,
869    tuple_index: u8,
870    constructor: &'s mut DocumentConstructor,
871}
872
873impl<'de> DeserializeSeed<'de> for TupleElementSeed<'_> {
874    type Value = ();
875
876    fn deserialize<D>(self, de: D) -> Result<Self::Value, D::Error>
877    where
878        D: serde::Deserializer<'de>,
879    {
880        let scope = self.constructor.begin_scope();
881        self.constructor
882            .navigate(PathSegment::TupleIndex(self.tuple_index))
883            .map_err(D::Error::custom)?;
884        EureDocumentSeed {
885            schema: self.schema,
886            schema_node_id: self.element_schema_id,
887            constructor: self.constructor,
888        }
889        .deserialize(de)?;
890        self.constructor
891            .end_scope(scope)
892            .map_err(D::Error::custom)?;
893        Ok(())
894    }
895}
896
897struct AnyVisitor<'s> {
898    constructor: &'s mut DocumentConstructor,
899}
900
901impl<'de> Visitor<'de> for AnyVisitor<'_> {
902    type Value = ();
903
904    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
905        formatter.write_str("any Eure-compatible value")
906    }
907
908    fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E>
909    where
910        E: de::Error,
911    {
912        bind_bool_value(self.constructor, value).map_err(E::custom)
913    }
914
915    fn visit_i8<E>(self, value: i8) -> Result<Self::Value, E>
916    where
917        E: de::Error,
918    {
919        self.visit_i64(i64::from(value))
920    }
921
922    fn visit_i16<E>(self, value: i16) -> Result<Self::Value, E>
923    where
924        E: de::Error,
925    {
926        self.visit_i64(i64::from(value))
927    }
928
929    fn visit_i32<E>(self, value: i32) -> Result<Self::Value, E>
930    where
931        E: de::Error,
932    {
933        self.visit_i64(i64::from(value))
934    }
935
936    fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
937    where
938        E: de::Error,
939    {
940        bind_integer_value(self.constructor, BigInt::from(value)).map_err(E::custom)
941    }
942
943    fn visit_i128<E>(self, value: i128) -> Result<Self::Value, E>
944    where
945        E: de::Error,
946    {
947        bind_integer_value(self.constructor, BigInt::from(value)).map_err(E::custom)
948    }
949
950    fn visit_u8<E>(self, value: u8) -> Result<Self::Value, E>
951    where
952        E: de::Error,
953    {
954        self.visit_u64(u64::from(value))
955    }
956
957    fn visit_u16<E>(self, value: u16) -> Result<Self::Value, E>
958    where
959        E: de::Error,
960    {
961        self.visit_u64(u64::from(value))
962    }
963
964    fn visit_u32<E>(self, value: u32) -> Result<Self::Value, E>
965    where
966        E: de::Error,
967    {
968        self.visit_u64(u64::from(value))
969    }
970
971    fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
972    where
973        E: de::Error,
974    {
975        bind_integer_value(self.constructor, BigInt::from(value)).map_err(E::custom)
976    }
977
978    fn visit_u128<E>(self, value: u128) -> Result<Self::Value, E>
979    where
980        E: de::Error,
981    {
982        bind_integer_value(self.constructor, BigInt::from(value)).map_err(E::custom)
983    }
984
985    fn visit_f32<E>(self, value: f32) -> Result<Self::Value, E>
986    where
987        E: de::Error,
988    {
989        bind_f32_value(self.constructor, value).map_err(E::custom)
990    }
991
992    fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E>
993    where
994        E: de::Error,
995    {
996        bind_f64_value(self.constructor, value).map_err(E::custom)
997    }
998
999    fn visit_char<E>(self, value: char) -> Result<Self::Value, E>
1000    where
1001        E: de::Error,
1002    {
1003        bind_text_value(self.constructor, value.to_string()).map_err(E::custom)
1004    }
1005
1006    fn visit_borrowed_str<E>(self, value: &'de str) -> Result<Self::Value, E>
1007    where
1008        E: de::Error,
1009    {
1010        bind_text_value(self.constructor, value.to_owned()).map_err(E::custom)
1011    }
1012
1013    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
1014    where
1015        E: de::Error,
1016    {
1017        bind_text_value(self.constructor, value.to_owned()).map_err(E::custom)
1018    }
1019
1020    fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
1021    where
1022        E: de::Error,
1023    {
1024        bind_text_value(self.constructor, value).map_err(E::custom)
1025    }
1026
1027    fn visit_borrowed_bytes<E>(self, value: &'de [u8]) -> Result<Self::Value, E>
1028    where
1029        E: de::Error,
1030    {
1031        bind_bytes_as_array(self.constructor, value).map_err(E::custom)
1032    }
1033
1034    fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
1035    where
1036        E: de::Error,
1037    {
1038        bind_bytes_as_array(self.constructor, value).map_err(E::custom)
1039    }
1040
1041    fn visit_byte_buf<E>(self, value: Vec<u8>) -> Result<Self::Value, E>
1042    where
1043        E: de::Error,
1044    {
1045        bind_bytes_as_array(self.constructor, &value).map_err(E::custom)
1046    }
1047
1048    fn visit_unit<E>(self) -> Result<Self::Value, E>
1049    where
1050        E: de::Error,
1051    {
1052        bind_null_value(self.constructor).map_err(E::custom)
1053    }
1054
1055    fn visit_none<E>(self) -> Result<Self::Value, E>
1056    where
1057        E: de::Error,
1058    {
1059        bind_null_value(self.constructor).map_err(E::custom)
1060    }
1061
1062    fn visit_some<D>(self, de: D) -> Result<Self::Value, D::Error>
1063    where
1064        D: serde::Deserializer<'de>,
1065    {
1066        AnySeed {
1067            constructor: self.constructor,
1068        }
1069        .deserialize(de)
1070    }
1071
1072    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
1073    where
1074        A: SeqAccess<'de>,
1075    {
1076        self.constructor
1077            .bind_empty_array()
1078            .map_err(A::Error::custom)?;
1079        while seq
1080            .next_element_seed(AnyArrayElementSeed {
1081                constructor: self.constructor,
1082            })?
1083            .is_some()
1084        {}
1085        Ok(())
1086    }
1087
1088    fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
1089    where
1090        A: MapAccess<'de>,
1091    {
1092        self.constructor
1093            .bind_empty_map()
1094            .map_err(A::Error::custom)?;
1095        while let Some(key) = map.next_key_seed(AnyObjectKeySeed)? {
1096            let scope = self.constructor.begin_scope();
1097            self.constructor
1098                .navigate(PathSegment::Value(key))
1099                .map_err(A::Error::custom)?;
1100            map.next_value_seed(AnySeed {
1101                constructor: self.constructor,
1102            })?;
1103            self.constructor
1104                .end_scope(scope)
1105                .map_err(A::Error::custom)?;
1106        }
1107        Ok(())
1108    }
1109}
1110
1111struct TextVisitor<'s> {
1112    constructor: &'s mut DocumentConstructor,
1113}
1114
1115impl<'de> Visitor<'de> for TextVisitor<'_> {
1116    type Value = ();
1117
1118    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1119        formatter.write_str("text")
1120    }
1121
1122    fn visit_borrowed_str<E>(self, value: &'de str) -> Result<Self::Value, E>
1123    where
1124        E: de::Error,
1125    {
1126        bind_text_value(self.constructor, value.to_owned()).map_err(E::custom)
1127    }
1128
1129    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
1130    where
1131        E: de::Error,
1132    {
1133        bind_text_value(self.constructor, value.to_owned()).map_err(E::custom)
1134    }
1135
1136    fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
1137    where
1138        E: de::Error,
1139    {
1140        bind_text_value(self.constructor, value).map_err(E::custom)
1141    }
1142
1143    fn visit_char<E>(self, value: char) -> Result<Self::Value, E>
1144    where
1145        E: de::Error,
1146    {
1147        bind_text_value(self.constructor, value.to_string()).map_err(E::custom)
1148    }
1149
1150    fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
1151    where
1152        E: de::Error,
1153    {
1154        bind_text_value(self.constructor, value.to_string()).map_err(E::custom)
1155    }
1156
1157    fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
1158    where
1159        E: de::Error,
1160    {
1161        bind_text_value(self.constructor, value.to_string()).map_err(E::custom)
1162    }
1163
1164    fn visit_i128<E>(self, value: i128) -> Result<Self::Value, E>
1165    where
1166        E: de::Error,
1167    {
1168        bind_text_value(self.constructor, value.to_string()).map_err(E::custom)
1169    }
1170
1171    fn visit_u128<E>(self, value: u128) -> Result<Self::Value, E>
1172    where
1173        E: de::Error,
1174    {
1175        bind_text_value(self.constructor, value.to_string()).map_err(E::custom)
1176    }
1177}
1178
1179struct IntegerVisitor<'s> {
1180    constructor: &'s mut DocumentConstructor,
1181}
1182
1183impl<'de> Visitor<'de> for IntegerVisitor<'_> {
1184    type Value = ();
1185
1186    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1187        formatter.write_str("integer")
1188    }
1189
1190    fn visit_i8<E>(self, value: i8) -> Result<Self::Value, E>
1191    where
1192        E: de::Error,
1193    {
1194        self.visit_i64(i64::from(value))
1195    }
1196
1197    fn visit_i16<E>(self, value: i16) -> Result<Self::Value, E>
1198    where
1199        E: de::Error,
1200    {
1201        self.visit_i64(i64::from(value))
1202    }
1203
1204    fn visit_i32<E>(self, value: i32) -> Result<Self::Value, E>
1205    where
1206        E: de::Error,
1207    {
1208        self.visit_i64(i64::from(value))
1209    }
1210
1211    fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
1212    where
1213        E: de::Error,
1214    {
1215        bind_integer_value(self.constructor, BigInt::from(value)).map_err(E::custom)
1216    }
1217
1218    fn visit_i128<E>(self, value: i128) -> Result<Self::Value, E>
1219    where
1220        E: de::Error,
1221    {
1222        bind_integer_value(self.constructor, BigInt::from(value)).map_err(E::custom)
1223    }
1224
1225    fn visit_u8<E>(self, value: u8) -> Result<Self::Value, E>
1226    where
1227        E: de::Error,
1228    {
1229        self.visit_u64(u64::from(value))
1230    }
1231
1232    fn visit_u16<E>(self, value: u16) -> Result<Self::Value, E>
1233    where
1234        E: de::Error,
1235    {
1236        self.visit_u64(u64::from(value))
1237    }
1238
1239    fn visit_u32<E>(self, value: u32) -> Result<Self::Value, E>
1240    where
1241        E: de::Error,
1242    {
1243        self.visit_u64(u64::from(value))
1244    }
1245
1246    fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
1247    where
1248        E: de::Error,
1249    {
1250        bind_integer_value(self.constructor, BigInt::from(value)).map_err(E::custom)
1251    }
1252
1253    fn visit_u128<E>(self, value: u128) -> Result<Self::Value, E>
1254    where
1255        E: de::Error,
1256    {
1257        bind_integer_value(self.constructor, BigInt::from(value)).map_err(E::custom)
1258    }
1259
1260    fn visit_borrowed_str<E>(self, value: &'de str) -> Result<Self::Value, E>
1261    where
1262        E: de::Error,
1263    {
1264        let value = parse_bigint(value).map_err(E::custom)?;
1265        bind_integer_value(self.constructor, value).map_err(E::custom)
1266    }
1267
1268    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
1269    where
1270        E: de::Error,
1271    {
1272        let value = parse_bigint(value).map_err(E::custom)?;
1273        bind_integer_value(self.constructor, value).map_err(E::custom)
1274    }
1275
1276    fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
1277    where
1278        E: de::Error,
1279    {
1280        let value = parse_bigint(&value).map_err(E::custom)?;
1281        bind_integer_value(self.constructor, value).map_err(E::custom)
1282    }
1283}
1284
1285struct FloatVisitor<'s> {
1286    constructor: &'s mut DocumentConstructor,
1287}
1288
1289impl<'de> Visitor<'de> for FloatVisitor<'_> {
1290    type Value = ();
1291
1292    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1293        formatter.write_str("float")
1294    }
1295
1296    fn visit_f32<E>(self, value: f32) -> Result<Self::Value, E>
1297    where
1298        E: de::Error,
1299    {
1300        bind_f32_value(self.constructor, value).map_err(E::custom)
1301    }
1302
1303    fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E>
1304    where
1305        E: de::Error,
1306    {
1307        bind_f64_value(self.constructor, value).map_err(E::custom)
1308    }
1309
1310    fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
1311    where
1312        E: de::Error,
1313    {
1314        bind_f64_value(self.constructor, value as f64).map_err(E::custom)
1315    }
1316
1317    fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
1318    where
1319        E: de::Error,
1320    {
1321        bind_f64_value(self.constructor, value as f64).map_err(E::custom)
1322    }
1323
1324    fn visit_i128<E>(self, value: i128) -> Result<Self::Value, E>
1325    where
1326        E: de::Error,
1327    {
1328        bind_f64_value(self.constructor, value as f64).map_err(E::custom)
1329    }
1330
1331    fn visit_u128<E>(self, value: u128) -> Result<Self::Value, E>
1332    where
1333        E: de::Error,
1334    {
1335        bind_f64_value(self.constructor, value as f64).map_err(E::custom)
1336    }
1337}
1338
1339struct BoolVisitor<'s> {
1340    constructor: &'s mut DocumentConstructor,
1341}
1342
1343impl<'de> Visitor<'de> for BoolVisitor<'_> {
1344    type Value = ();
1345
1346    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1347        formatter.write_str("boolean")
1348    }
1349
1350    fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E>
1351    where
1352        E: de::Error,
1353    {
1354        bind_bool_value(self.constructor, value).map_err(E::custom)
1355    }
1356}
1357
1358struct NullVisitor<'s> {
1359    constructor: &'s mut DocumentConstructor,
1360}
1361
1362impl<'de> Visitor<'de> for NullVisitor<'_> {
1363    type Value = ();
1364
1365    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1366        formatter.write_str("null")
1367    }
1368
1369    fn visit_unit<E>(self) -> Result<Self::Value, E>
1370    where
1371        E: de::Error,
1372    {
1373        bind_null_value(self.constructor).map_err(E::custom)
1374    }
1375
1376    fn visit_none<E>(self) -> Result<Self::Value, E>
1377    where
1378        E: de::Error,
1379    {
1380        bind_null_value(self.constructor).map_err(E::custom)
1381    }
1382}
1383
1384struct SeqVisitor<'s> {
1385    schema: &'s SchemaDocument,
1386    item_schema_id: SchemaNodeId,
1387    constructor: &'s mut DocumentConstructor,
1388}
1389
1390impl<'de> Visitor<'de> for SeqVisitor<'_> {
1391    type Value = ();
1392
1393    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1394        formatter.write_str("array")
1395    }
1396
1397    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
1398    where
1399        A: SeqAccess<'de>,
1400    {
1401        self.constructor
1402            .bind_empty_array()
1403            .map_err(A::Error::custom)?;
1404        while seq
1405            .next_element_seed(ArrayElementSeed {
1406                schema: self.schema,
1407                item_schema_id: self.item_schema_id,
1408                constructor: self.constructor,
1409            })?
1410            .is_some()
1411        {}
1412        Ok(())
1413    }
1414}
1415
1416struct TupleVisitor<'s> {
1417    schema: &'s SchemaDocument,
1418    elements: &'s [SchemaNodeId],
1419    constructor: &'s mut DocumentConstructor,
1420}
1421
1422impl<'de> Visitor<'de> for TupleVisitor<'_> {
1423    type Value = ();
1424
1425    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1426        formatter.write_str("tuple")
1427    }
1428
1429    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
1430    where
1431        A: SeqAccess<'de>,
1432    {
1433        self.constructor
1434            .bind_empty_tuple()
1435            .map_err(A::Error::custom)?;
1436
1437        for (index, &element_schema_id) in self.elements.iter().enumerate() {
1438            let tuple_index = u8::try_from(index)
1439                .map_err(|_| A::Error::custom("tuple index out of range for Eure tuple"))?;
1440            let Some(()) = seq.next_element_seed(TupleElementSeed {
1441                schema: self.schema,
1442                element_schema_id,
1443                tuple_index,
1444                constructor: self.constructor,
1445            })?
1446            else {
1447                return Err(A::Error::custom(DeError::EndOfSequence.to_string()));
1448            };
1449        }
1450
1451        if seq.next_element::<de::IgnoredAny>()?.is_some() {
1452            return Err(A::Error::custom(format!(
1453                "tuple length mismatch: expected {}, got more elements",
1454                self.elements.len()
1455            )));
1456        }
1457
1458        Ok(())
1459    }
1460}
1461
1462struct MapVisitor<'s> {
1463    schema: &'s SchemaDocument,
1464    key_schema_id: SchemaNodeId,
1465    value_schema_id: SchemaNodeId,
1466    constructor: &'s mut DocumentConstructor,
1467}
1468
1469impl<'de> Visitor<'de> for MapVisitor<'_> {
1470    type Value = ();
1471
1472    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1473        formatter.write_str("map")
1474    }
1475
1476    fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
1477    where
1478        A: MapAccess<'de>,
1479    {
1480        self.constructor
1481            .bind_empty_map()
1482            .map_err(A::Error::custom)?;
1483
1484        while let Some(key) = map.next_key_seed(ObjectKeySeed {
1485            schema: self.schema,
1486            schema_node_id: self.key_schema_id,
1487        })? {
1488            let scope = self.constructor.begin_scope();
1489            self.constructor
1490                .navigate(PathSegment::Value(key))
1491                .map_err(A::Error::custom)?;
1492            map.next_value_seed(EureDocumentSeed {
1493                schema: self.schema,
1494                schema_node_id: self.value_schema_id,
1495                constructor: self.constructor,
1496            })?;
1497            self.constructor
1498                .end_scope(scope)
1499                .map_err(A::Error::custom)?;
1500        }
1501
1502        Ok(())
1503    }
1504}
1505
1506/// Recursively collect `(field_name → (SchemaNodeId, optional))` from a flattened schema.
1507/// Only `Record` schemas contribute fields; other node types are silently ignored.
1508fn collect_flatten_fields(
1509    schema: &SchemaDocument,
1510    node_id: SchemaNodeId,
1511    out: &mut std::collections::HashMap<String, (SchemaNodeId, bool)>,
1512) {
1513    let Ok(resolved) = resolve_schema_node_id(schema, node_id) else {
1514        return;
1515    };
1516
1517    match &schema.node(resolved).content {
1518        SchemaNodeContent::Record(rec) => {
1519            for (name, field) in &rec.properties {
1520                out.entry(name.clone())
1521                    .or_insert((field.schema, field.optional));
1522            }
1523            for &inner in &rec.flatten {
1524                collect_flatten_fields(schema, inner, out);
1525            }
1526        }
1527        SchemaNodeContent::Union(_)
1528        | SchemaNodeContent::Any
1529        | SchemaNodeContent::Text(_)
1530        | SchemaNodeContent::Integer(_)
1531        | SchemaNodeContent::Float(_)
1532        | SchemaNodeContent::Boolean
1533        | SchemaNodeContent::Null
1534        | SchemaNodeContent::Literal(_)
1535        | SchemaNodeContent::Array(_)
1536        | SchemaNodeContent::Map(_)
1537        | SchemaNodeContent::Tuple(_)
1538        | SchemaNodeContent::Reference(_) => {}
1539    }
1540}
1541
1542struct RecordVisitor<'s> {
1543    schema: &'s SchemaDocument,
1544    record_schema: &'s eure_schema::RecordSchema,
1545    constructor: &'s mut DocumentConstructor,
1546}
1547
1548impl<'de> Visitor<'de> for RecordVisitor<'_> {
1549    type Value = ();
1550
1551    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1552        formatter.write_str("record")
1553    }
1554
1555    fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
1556    where
1557        A: MapAccess<'de>,
1558    {
1559        // Build a combined lookup that includes fields from flattened schemas.
1560        let mut flatten_fields: std::collections::HashMap<String, (SchemaNodeId, bool)> =
1561            std::collections::HashMap::new();
1562        for &fid in &self.record_schema.flatten {
1563            collect_flatten_fields(self.schema, fid, &mut flatten_fields);
1564        }
1565
1566        self.constructor
1567            .bind_empty_map()
1568            .map_err(A::Error::custom)?;
1569        let mut seen = HashSet::new();
1570
1571        while let Some(key) = map.next_key::<String>()? {
1572            // Check direct properties first, then flattened schemas.
1573            let schema_node_id = if let Some(field_schema) = self.record_schema.properties.get(&key)
1574            {
1575                Some(field_schema.schema)
1576            } else {
1577                flatten_fields.get(&key).map(|&(id, _opt)| id)
1578            };
1579
1580            if let Some(schema_node_id) = schema_node_id {
1581                let scope = self.constructor.begin_scope();
1582                self.constructor
1583                    .navigate(PathSegment::Value(ObjectKey::String(key.clone())))
1584                    .map_err(A::Error::custom)?;
1585                map.next_value_seed(EureDocumentSeed {
1586                    schema: self.schema,
1587                    schema_node_id,
1588                    constructor: self.constructor,
1589                })?;
1590                self.constructor
1591                    .end_scope(scope)
1592                    .map_err(A::Error::custom)?;
1593                seen.insert(key);
1594                continue;
1595            }
1596
1597            match &self.record_schema.unknown_fields {
1598                UnknownFieldsPolicy::Deny => {
1599                    return Err(A::Error::custom(format!("unknown field: {key}")));
1600                }
1601                UnknownFieldsPolicy::Allow => {
1602                    let scope = self.constructor.begin_scope();
1603                    self.constructor
1604                        .navigate(PathSegment::Value(ObjectKey::String(key.clone())))
1605                        .map_err(A::Error::custom)?;
1606                    map.next_value_seed(AnySeed {
1607                        constructor: self.constructor,
1608                    })?;
1609                    self.constructor
1610                        .end_scope(scope)
1611                        .map_err(A::Error::custom)?;
1612                }
1613                UnknownFieldsPolicy::Schema(schema_id) => {
1614                    let scope = self.constructor.begin_scope();
1615                    self.constructor
1616                        .navigate(PathSegment::Value(ObjectKey::String(key.clone())))
1617                        .map_err(A::Error::custom)?;
1618                    map.next_value_seed(EureDocumentSeed {
1619                        schema: self.schema,
1620                        schema_node_id: *schema_id,
1621                        constructor: self.constructor,
1622                    })?;
1623                    self.constructor
1624                        .end_scope(scope)
1625                        .map_err(A::Error::custom)?;
1626                }
1627            }
1628        }
1629
1630        for (name, field) in &self.record_schema.properties {
1631            if !field.optional && !seen.contains(name) {
1632                return Err(A::Error::custom(
1633                    DeError::MissingField(name.clone()).to_string(),
1634                ));
1635            }
1636        }
1637        for (name, &(_id, optional)) in &flatten_fields {
1638            if !optional && !seen.contains(name) {
1639                return Err(A::Error::custom(
1640                    DeError::MissingField(name.clone()).to_string(),
1641                ));
1642            }
1643        }
1644
1645        Ok(())
1646    }
1647}
1648
1649struct ExternalVariantVisitor<'s> {
1650    schema: &'s SchemaDocument,
1651    union_schema: &'s UnionSchema,
1652    constructor: &'s mut DocumentConstructor,
1653}
1654
1655impl<'de> Visitor<'de> for ExternalVariantVisitor<'_> {
1656    type Value = ();
1657
1658    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1659        formatter.write_str("an externally tagged union")
1660    }
1661
1662    fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
1663    where
1664        A: MapAccess<'de>,
1665    {
1666        let variant_name: String = map
1667            .next_key()?
1668            .ok_or_else(|| A::Error::custom("expected variant map with one key"))?;
1669
1670        let Some(&variant_schema_id) = self.union_schema.variants.get(&variant_name) else {
1671            return Err(A::Error::custom(format!("unknown variant: {variant_name}")));
1672        };
1673
1674        self.constructor
1675            .set_variant(&variant_name)
1676            .map_err(A::Error::custom)?;
1677        map.next_value_seed(EureDocumentSeed {
1678            schema: self.schema,
1679            schema_node_id: variant_schema_id,
1680            constructor: self.constructor,
1681        })?;
1682
1683        if map.next_key::<de::IgnoredAny>()?.is_some() {
1684            return Err(A::Error::custom(
1685                "expected externally tagged union map with exactly one key",
1686            ));
1687        }
1688
1689        Ok(())
1690    }
1691
1692    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
1693    where
1694        E: de::Error,
1695    {
1696        if self.union_schema.variants.contains_key(value) {
1697            self.constructor.set_variant(value).map_err(E::custom)?;
1698            self.constructor
1699                .bind_primitive(PrimitiveValue::Null)
1700                .map_err(E::custom)?;
1701            Ok(())
1702        } else {
1703            Err(E::custom(format!("unknown variant: {value}")))
1704        }
1705    }
1706
1707    fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
1708    where
1709        E: de::Error,
1710    {
1711        self.visit_str(&value)
1712    }
1713}
1714
1715struct AnyObjectKeyVisitor;
1716
1717impl<'de> Visitor<'de> for AnyObjectKeyVisitor {
1718    type Value = ObjectKey;
1719
1720    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1721        formatter.write_str("a Eure-compatible map key")
1722    }
1723
1724    fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E>
1725    where
1726        E: de::Error,
1727    {
1728        Ok(ObjectKey::from(value))
1729    }
1730
1731    fn visit_i8<E>(self, value: i8) -> Result<Self::Value, E>
1732    where
1733        E: de::Error,
1734    {
1735        self.visit_i64(i64::from(value))
1736    }
1737
1738    fn visit_i16<E>(self, value: i16) -> Result<Self::Value, E>
1739    where
1740        E: de::Error,
1741    {
1742        self.visit_i64(i64::from(value))
1743    }
1744
1745    fn visit_i32<E>(self, value: i32) -> Result<Self::Value, E>
1746    where
1747        E: de::Error,
1748    {
1749        self.visit_i64(i64::from(value))
1750    }
1751
1752    fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
1753    where
1754        E: de::Error,
1755    {
1756        Ok(ObjectKey::Number(BigInt::from(value)))
1757    }
1758
1759    fn visit_i128<E>(self, value: i128) -> Result<Self::Value, E>
1760    where
1761        E: de::Error,
1762    {
1763        Ok(ObjectKey::Number(BigInt::from(value)))
1764    }
1765
1766    fn visit_u8<E>(self, value: u8) -> Result<Self::Value, E>
1767    where
1768        E: de::Error,
1769    {
1770        self.visit_u64(u64::from(value))
1771    }
1772
1773    fn visit_u16<E>(self, value: u16) -> Result<Self::Value, E>
1774    where
1775        E: de::Error,
1776    {
1777        self.visit_u64(u64::from(value))
1778    }
1779
1780    fn visit_u32<E>(self, value: u32) -> Result<Self::Value, E>
1781    where
1782        E: de::Error,
1783    {
1784        self.visit_u64(u64::from(value))
1785    }
1786
1787    fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
1788    where
1789        E: de::Error,
1790    {
1791        Ok(ObjectKey::Number(BigInt::from(value)))
1792    }
1793
1794    fn visit_u128<E>(self, value: u128) -> Result<Self::Value, E>
1795    where
1796        E: de::Error,
1797    {
1798        Ok(ObjectKey::Number(BigInt::from(value)))
1799    }
1800
1801    fn visit_char<E>(self, value: char) -> Result<Self::Value, E>
1802    where
1803        E: de::Error,
1804    {
1805        Ok(ObjectKey::String(value.to_string()))
1806    }
1807
1808    fn visit_borrowed_str<E>(self, value: &'de str) -> Result<Self::Value, E>
1809    where
1810        E: de::Error,
1811    {
1812        Ok(ObjectKey::String(value.to_owned()))
1813    }
1814
1815    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
1816    where
1817        E: de::Error,
1818    {
1819        Ok(ObjectKey::String(value.to_owned()))
1820    }
1821
1822    fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
1823    where
1824        E: de::Error,
1825    {
1826        Ok(ObjectKey::String(value))
1827    }
1828
1829    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
1830    where
1831        A: SeqAccess<'de>,
1832    {
1833        let mut elements = Vec::new();
1834        while let Some(value) = seq.next_element_seed(AnyObjectKeySeed)? {
1835            elements.push(value);
1836        }
1837        Ok(ObjectKey::Tuple(Tuple(elements)))
1838    }
1839}
1840
1841struct TextObjectKeyVisitor;
1842
1843impl<'de> Visitor<'de> for TextObjectKeyVisitor {
1844    type Value = ObjectKey;
1845
1846    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1847        formatter.write_str("a text map key")
1848    }
1849
1850    fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E>
1851    where
1852        E: de::Error,
1853    {
1854        Ok(ObjectKey::String(if value {
1855            "true".to_string()
1856        } else {
1857            "false".to_string()
1858        }))
1859    }
1860
1861    fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
1862    where
1863        E: de::Error,
1864    {
1865        Ok(ObjectKey::String(value.to_string()))
1866    }
1867
1868    fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
1869    where
1870        E: de::Error,
1871    {
1872        Ok(ObjectKey::String(value.to_string()))
1873    }
1874
1875    fn visit_i128<E>(self, value: i128) -> Result<Self::Value, E>
1876    where
1877        E: de::Error,
1878    {
1879        Ok(ObjectKey::String(value.to_string()))
1880    }
1881
1882    fn visit_u128<E>(self, value: u128) -> Result<Self::Value, E>
1883    where
1884        E: de::Error,
1885    {
1886        Ok(ObjectKey::String(value.to_string()))
1887    }
1888
1889    fn visit_char<E>(self, value: char) -> Result<Self::Value, E>
1890    where
1891        E: de::Error,
1892    {
1893        Ok(ObjectKey::String(value.to_string()))
1894    }
1895
1896    fn visit_borrowed_str<E>(self, value: &'de str) -> Result<Self::Value, E>
1897    where
1898        E: de::Error,
1899    {
1900        Ok(ObjectKey::String(value.to_owned()))
1901    }
1902
1903    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
1904    where
1905        E: de::Error,
1906    {
1907        Ok(ObjectKey::String(value.to_owned()))
1908    }
1909
1910    fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
1911    where
1912        E: de::Error,
1913    {
1914        Ok(ObjectKey::String(value))
1915    }
1916}
1917
1918struct IntegerObjectKeyVisitor;
1919
1920impl<'de> Visitor<'de> for IntegerObjectKeyVisitor {
1921    type Value = ObjectKey;
1922
1923    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1924        formatter.write_str("an integer map key")
1925    }
1926
1927    fn visit_i8<E>(self, value: i8) -> Result<Self::Value, E>
1928    where
1929        E: de::Error,
1930    {
1931        self.visit_i64(i64::from(value))
1932    }
1933
1934    fn visit_i16<E>(self, value: i16) -> Result<Self::Value, E>
1935    where
1936        E: de::Error,
1937    {
1938        self.visit_i64(i64::from(value))
1939    }
1940
1941    fn visit_i32<E>(self, value: i32) -> Result<Self::Value, E>
1942    where
1943        E: de::Error,
1944    {
1945        self.visit_i64(i64::from(value))
1946    }
1947
1948    fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
1949    where
1950        E: de::Error,
1951    {
1952        Ok(ObjectKey::Number(BigInt::from(value)))
1953    }
1954
1955    fn visit_i128<E>(self, value: i128) -> Result<Self::Value, E>
1956    where
1957        E: de::Error,
1958    {
1959        Ok(ObjectKey::Number(BigInt::from(value)))
1960    }
1961
1962    fn visit_u8<E>(self, value: u8) -> Result<Self::Value, E>
1963    where
1964        E: de::Error,
1965    {
1966        self.visit_u64(u64::from(value))
1967    }
1968
1969    fn visit_u16<E>(self, value: u16) -> Result<Self::Value, E>
1970    where
1971        E: de::Error,
1972    {
1973        self.visit_u64(u64::from(value))
1974    }
1975
1976    fn visit_u32<E>(self, value: u32) -> Result<Self::Value, E>
1977    where
1978        E: de::Error,
1979    {
1980        self.visit_u64(u64::from(value))
1981    }
1982
1983    fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
1984    where
1985        E: de::Error,
1986    {
1987        Ok(ObjectKey::Number(BigInt::from(value)))
1988    }
1989
1990    fn visit_u128<E>(self, value: u128) -> Result<Self::Value, E>
1991    where
1992        E: de::Error,
1993    {
1994        Ok(ObjectKey::Number(BigInt::from(value)))
1995    }
1996
1997    fn visit_borrowed_str<E>(self, value: &'de str) -> Result<Self::Value, E>
1998    where
1999        E: de::Error,
2000    {
2001        Ok(ObjectKey::Number(parse_bigint(value).map_err(E::custom)?))
2002    }
2003
2004    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
2005    where
2006        E: de::Error,
2007    {
2008        Ok(ObjectKey::Number(parse_bigint(value).map_err(E::custom)?))
2009    }
2010
2011    fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
2012    where
2013        E: de::Error,
2014    {
2015        Ok(ObjectKey::Number(parse_bigint(&value).map_err(E::custom)?))
2016    }
2017}
2018
2019struct BoolObjectKeyVisitor;
2020
2021impl<'de> Visitor<'de> for BoolObjectKeyVisitor {
2022    type Value = ObjectKey;
2023
2024    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
2025        formatter.write_str("a boolean map key")
2026    }
2027
2028    fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E>
2029    where
2030        E: de::Error,
2031    {
2032        Ok(ObjectKey::from(value))
2033    }
2034
2035    fn visit_borrowed_str<E>(self, value: &'de str) -> Result<Self::Value, E>
2036    where
2037        E: de::Error,
2038    {
2039        match value {
2040            "true" => Ok(ObjectKey::String(value.to_owned())),
2041            "false" => Ok(ObjectKey::String(value.to_owned())),
2042            _ => Err(E::custom(type_mismatch("boolean", "text").to_string())),
2043        }
2044    }
2045
2046    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
2047    where
2048        E: de::Error,
2049    {
2050        self.visit_borrowed_str(value)
2051    }
2052
2053    fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
2054    where
2055        E: de::Error,
2056    {
2057        self.visit_str(&value)
2058    }
2059}
2060
2061struct LiteralObjectKeyVisitor<'a> {
2062    expected: &'a EureDocument,
2063}
2064
2065impl<'de> Visitor<'de> for LiteralObjectKeyVisitor<'_> {
2066    type Value = ObjectKey;
2067
2068    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
2069        formatter.write_str("a literal map key")
2070    }
2071
2072    fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E>
2073    where
2074        E: de::Error,
2075    {
2076        match expected_primitive(self.expected).map_err(E::custom)? {
2077            PrimitiveValue::Bool(expected) if *expected == value => Ok(ObjectKey::from(value)),
2078            PrimitiveValue::Bool(_) => Err(E::custom("literal mismatch")),
2079            primitive => Err(E::custom(type_mismatch(
2080                "boolean",
2081                primitive_type_name(primitive),
2082            ))),
2083        }
2084    }
2085
2086    fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
2087    where
2088        E: de::Error,
2089    {
2090        literal_integer_key(self.expected, BigInt::from(value)).map_err(E::custom)
2091    }
2092
2093    fn visit_i128<E>(self, value: i128) -> Result<Self::Value, E>
2094    where
2095        E: de::Error,
2096    {
2097        literal_integer_key(self.expected, BigInt::from(value)).map_err(E::custom)
2098    }
2099
2100    fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
2101    where
2102        E: de::Error,
2103    {
2104        literal_integer_key(self.expected, BigInt::from(value)).map_err(E::custom)
2105    }
2106
2107    fn visit_u128<E>(self, value: u128) -> Result<Self::Value, E>
2108    where
2109        E: de::Error,
2110    {
2111        literal_integer_key(self.expected, BigInt::from(value)).map_err(E::custom)
2112    }
2113
2114    fn visit_char<E>(self, value: char) -> Result<Self::Value, E>
2115    where
2116        E: de::Error,
2117    {
2118        self.visit_string(value.to_string())
2119    }
2120
2121    fn visit_borrowed_str<E>(self, value: &'de str) -> Result<Self::Value, E>
2122    where
2123        E: de::Error,
2124    {
2125        literal_string_key(self.expected, value).map_err(E::custom)
2126    }
2127
2128    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
2129    where
2130        E: de::Error,
2131    {
2132        literal_string_key(self.expected, value).map_err(E::custom)
2133    }
2134
2135    fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
2136    where
2137        E: de::Error,
2138    {
2139        literal_string_key(self.expected, &value).map_err(E::custom)
2140    }
2141}
2142
2143struct TupleObjectKeyVisitor<'s> {
2144    schema: &'s SchemaDocument,
2145    elements: &'s [SchemaNodeId],
2146}
2147
2148impl<'de> Visitor<'de> for TupleObjectKeyVisitor<'_> {
2149    type Value = ObjectKey;
2150
2151    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
2152        formatter.write_str("a tuple map key")
2153    }
2154
2155    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
2156    where
2157        A: SeqAccess<'de>,
2158    {
2159        let mut keys = Vec::with_capacity(self.elements.len());
2160
2161        for &element_schema_id in self.elements {
2162            let Some(key) = seq.next_element_seed(ObjectKeySeed {
2163                schema: self.schema,
2164                schema_node_id: element_schema_id,
2165            })?
2166            else {
2167                return Err(A::Error::custom(DeError::EndOfSequence.to_string()));
2168            };
2169            keys.push(key);
2170        }
2171
2172        if seq.next_element::<de::IgnoredAny>()?.is_some() {
2173            return Err(A::Error::custom(format!(
2174                "tuple length mismatch: expected {}, got more elements",
2175                self.elements.len()
2176            )));
2177        }
2178
2179        Ok(ObjectKey::Tuple(Tuple(keys)))
2180    }
2181}
2182
2183struct UnionObjectKeyVisitor<'s> {
2184    schema: &'s SchemaDocument,
2185    union_schema: &'s UnionSchema,
2186}
2187
2188impl<'de> Visitor<'de> for UnionObjectKeyVisitor<'_> {
2189    type Value = ObjectKey;
2190
2191    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
2192        formatter.write_str("a union-compatible map key")
2193    }
2194
2195    fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E>
2196    where
2197        E: de::Error,
2198    {
2199        union_key_from_bool(self.schema, self.union_schema, value).map_err(E::custom)
2200    }
2201
2202    fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
2203    where
2204        E: de::Error,
2205    {
2206        union_key_from_integer(self.schema, self.union_schema, BigInt::from(value))
2207            .map_err(E::custom)
2208    }
2209
2210    fn visit_i128<E>(self, value: i128) -> Result<Self::Value, E>
2211    where
2212        E: de::Error,
2213    {
2214        union_key_from_integer(self.schema, self.union_schema, BigInt::from(value))
2215            .map_err(E::custom)
2216    }
2217
2218    fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
2219    where
2220        E: de::Error,
2221    {
2222        union_key_from_integer(self.schema, self.union_schema, BigInt::from(value))
2223            .map_err(E::custom)
2224    }
2225
2226    fn visit_u128<E>(self, value: u128) -> Result<Self::Value, E>
2227    where
2228        E: de::Error,
2229    {
2230        union_key_from_integer(self.schema, self.union_schema, BigInt::from(value))
2231            .map_err(E::custom)
2232    }
2233
2234    fn visit_char<E>(self, value: char) -> Result<Self::Value, E>
2235    where
2236        E: de::Error,
2237    {
2238        self.visit_string(value.to_string())
2239    }
2240
2241    fn visit_borrowed_str<E>(self, value: &'de str) -> Result<Self::Value, E>
2242    where
2243        E: de::Error,
2244    {
2245        union_key_from_string(self.schema, self.union_schema, value).map_err(E::custom)
2246    }
2247
2248    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
2249    where
2250        E: de::Error,
2251    {
2252        union_key_from_string(self.schema, self.union_schema, value).map_err(E::custom)
2253    }
2254
2255    fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
2256    where
2257        E: de::Error,
2258    {
2259        union_key_from_string(self.schema, self.union_schema, &value).map_err(E::custom)
2260    }
2261}
2262
2263fn deserialize_union<'de, D: serde::Deserializer<'de>>(
2264    de: D,
2265    schema: &SchemaDocument,
2266    union_schema: &UnionSchema,
2267    _schema_node_id: SchemaNodeId,
2268    constructor: &mut DocumentConstructor,
2269) -> Result<(), D::Error> {
2270    let repr = union_schema
2271        .interop
2272        .variant_repr
2273        .as_ref()
2274        .unwrap_or(&VariantRepr::External);
2275
2276    match repr {
2277        VariantRepr::External => de.deserialize_map(ExternalVariantVisitor {
2278            schema,
2279            union_schema,
2280            constructor,
2281        }),
2282        VariantRepr::Internal { tag } => {
2283            let content = de
2284                .deserialize_map(EureContentMapVisitor)
2285                .map_err(D::Error::custom)?;
2286            deserialize_internal_tagged(content, schema, union_schema, tag, constructor)
2287                .map_err(D::Error::custom)
2288        }
2289        VariantRepr::Adjacent {
2290            tag,
2291            content: content_key,
2292        } => {
2293            let content = de
2294                .deserialize_map(EureContentMapVisitor)
2295                .map_err(D::Error::custom)?;
2296            deserialize_adjacent_tagged(
2297                content,
2298                schema,
2299                union_schema,
2300                tag,
2301                content_key,
2302                constructor,
2303            )
2304            .map_err(D::Error::custom)
2305        }
2306        VariantRepr::Untagged => {
2307            // Untagged unions require a self-describing input so we can trial-match variants.
2308            let content = EureContent::deserialize(de).map_err(D::Error::custom)?;
2309            deserialize_untagged(content, schema, union_schema, constructor)
2310                .map_err(D::Error::custom)
2311        }
2312    }
2313}
2314
2315fn deserialize_internal_tagged<'de>(
2316    content: EureContent<'de>,
2317    schema: &SchemaDocument,
2318    union_schema: &UnionSchema,
2319    tag: &str,
2320    constructor: &mut DocumentConstructor,
2321) -> Result<(), DeError> {
2322    let entries = match content {
2323        EureContent::Map(entries) => entries,
2324        other => return Err(type_mismatch("map", eure_content_type(&other))),
2325    };
2326
2327    let mut variant_name = None;
2328    let mut remaining = Vec::new();
2329
2330    for (key, value) in entries {
2331        if content_key_matches(&key, tag) {
2332            if variant_name.is_some() {
2333                return Err(DeError::Custom(format!("duplicate field: {tag}")));
2334            }
2335            variant_name = Some(content_as_variant_name(value)?);
2336        } else {
2337            remaining.push((key, value));
2338        }
2339    }
2340
2341    let variant_name = variant_name.ok_or_else(|| DeError::MissingField(tag.to_string()))?;
2342    let variant_schema_id = *union_schema
2343        .variants
2344        .get(&variant_name)
2345        .ok_or_else(|| DeError::InvalidVariantName(variant_name.clone()))?;
2346
2347    constructor.set_variant(&variant_name)?;
2348
2349    let resolved_variant_id = resolve_schema_node_id(schema, variant_schema_id)?;
2350    let variant_content = if remaining.is_empty()
2351        && matches!(
2352            schema.node(resolved_variant_id).content,
2353            SchemaNodeContent::Null
2354        ) {
2355        EureContent::Unit
2356    } else {
2357        EureContent::Map(remaining)
2358    };
2359
2360    EureDocumentSeed {
2361        schema,
2362        schema_node_id: variant_schema_id,
2363        constructor,
2364    }
2365    .deserialize(variant_content)
2366}
2367
2368fn deserialize_adjacent_tagged<'de>(
2369    content: EureContent<'de>,
2370    schema: &SchemaDocument,
2371    union_schema: &UnionSchema,
2372    tag: &str,
2373    content_key: &str,
2374    constructor: &mut DocumentConstructor,
2375) -> Result<(), DeError> {
2376    let entries = match content {
2377        EureContent::Map(entries) => entries,
2378        other => return Err(type_mismatch("map", eure_content_type(&other))),
2379    };
2380
2381    let mut variant_name = None;
2382    let mut variant_content = None;
2383    let mut remaining = Vec::new();
2384
2385    for (key, value) in entries {
2386        if content_key_matches(&key, tag) {
2387            if variant_name.is_some() {
2388                return Err(DeError::Custom(format!("duplicate field: {tag}")));
2389            }
2390            variant_name = Some(content_as_variant_name(value)?);
2391        } else if content_key_matches(&key, content_key) {
2392            if variant_content.is_some() {
2393                return Err(DeError::Custom(format!("duplicate field: {content_key}")));
2394            }
2395            variant_content = Some(value);
2396        } else {
2397            remaining.push((key, value));
2398        }
2399    }
2400
2401    let variant_name = variant_name.ok_or_else(|| DeError::MissingField(tag.to_string()))?;
2402    let variant_schema_id = *union_schema
2403        .variants
2404        .get(&variant_name)
2405        .ok_or_else(|| DeError::InvalidVariantName(variant_name.clone()))?;
2406    let resolved_variant_id = resolve_schema_node_id(schema, variant_schema_id)?;
2407    // Unit variants (Null schema) have no content field — treat missing content as Unit.
2408    let is_null_variant = matches!(
2409        schema.node(resolved_variant_id).content,
2410        SchemaNodeContent::Null
2411    );
2412    let variant_content = if is_null_variant {
2413        variant_content.unwrap_or(EureContent::Unit)
2414    } else {
2415        variant_content.ok_or_else(|| DeError::MissingField(content_key.to_string()))?
2416    };
2417    let variant_content = merge_adjacent_variant_content(
2418        variant_content,
2419        remaining,
2420        &schema.node(resolved_variant_id).content,
2421    )?;
2422
2423    constructor.set_variant(&variant_name)?;
2424    EureDocumentSeed {
2425        schema,
2426        schema_node_id: variant_schema_id,
2427        constructor,
2428    }
2429    .deserialize(variant_content)
2430}
2431
2432// Limitation: variant selection is based on structural deserialization success, not value-level
2433// constraints (ranges, patterns, literal equality). Untagged unions whose variants are only
2434// distinguishable by value (e.g., `int<=10 | int>=11`, `literal("ok") | text`) may match
2435// the wrong branch. Use explicit tagging or `unambiguous` semantics with structurally-distinct
2436// variants to avoid this. Running the schema validator afterward can detect but not repair
2437// a wrong variant assignment.
2438fn try_untagged_variant<'de>(
2439    content: EureContent<'de>,
2440    schema: &SchemaDocument,
2441    variant_schema_id: SchemaNodeId,
2442) -> Option<(EureDocument, Option<VariantPath>)> {
2443    let mut temp_constructor = DocumentConstructor::new();
2444    let attempt = EureDocumentSeed {
2445        schema,
2446        schema_node_id: variant_schema_id,
2447        constructor: &mut temp_constructor,
2448    }
2449    .deserialize(content.into_deserializer());
2450
2451    if attempt.is_ok() {
2452        let mut temp_doc = temp_constructor.finish();
2453        let root_id = temp_doc.get_root_id();
2454        let inner_variant_path = extract_variant_path(&temp_doc, root_id).ok()?;
2455        temp_doc
2456            .node_mut(root_id)
2457            .extensions
2458            .remove_ordered(&Identifier::VARIANT);
2459        Some((temp_doc, inner_variant_path))
2460    } else {
2461        None
2462    }
2463}
2464
2465fn deserialize_untagged<'de>(
2466    content: EureContent<'de>,
2467    schema: &SchemaDocument,
2468    union_schema: &UnionSchema,
2469    constructor: &mut DocumentConstructor,
2470) -> Result<(), DeError> {
2471    // First pass: priority (non-`unambiguous`) variants use first-match semantics —
2472    // matches the core parser's `variant()` registration with `is_priority=true`.
2473    for (variant_name, &variant_schema_id) in &union_schema.variants {
2474        if union_schema.deny_untagged.contains(variant_name)
2475            || union_schema.unambiguous.contains(variant_name)
2476        {
2477            continue;
2478        }
2479
2480        if let Some((temp_doc, inner_variant_path)) =
2481            try_untagged_variant(content.clone(), schema, variant_schema_id)
2482        {
2483            let root_id = temp_doc.get_root_id();
2484            constructor.set_variant(variant_name)?;
2485            if let Some(inner_variant_path) = inner_variant_path
2486                && !inner_variant_path.is_empty()
2487            {
2488                constructor.set_variant(&inner_variant_path.to_string())?;
2489            }
2490            constructor.write_subtree(&temp_doc, root_id)?;
2491            return Ok(());
2492        }
2493    }
2494
2495    // Second pass: `unambiguous` variants — try all, error on conflicts.
2496    // Matches the core parser's `variant_unambiguous()` with `is_priority=false`.
2497    let mut unambiguous_match: Option<(&str, EureDocument, Option<VariantPath>)> = None;
2498    for (variant_name, &variant_schema_id) in &union_schema.variants {
2499        if union_schema.deny_untagged.contains(variant_name)
2500            || !union_schema.unambiguous.contains(variant_name)
2501        {
2502            continue;
2503        }
2504        if let Some((doc, inner_path)) =
2505            try_untagged_variant(content.clone(), schema, variant_schema_id)
2506        {
2507            if unambiguous_match.is_some() {
2508                return Err(DeError::Custom(
2509                    "ambiguous untagged union: multiple variants match".to_string(),
2510                ));
2511            }
2512            unambiguous_match = Some((variant_name, doc, inner_path));
2513        }
2514    }
2515    if let Some((variant_name, temp_doc, inner_variant_path)) = unambiguous_match {
2516        let root_id = temp_doc.get_root_id();
2517        constructor.set_variant(variant_name)?;
2518        if let Some(inner_variant_path) = inner_variant_path
2519            && !inner_variant_path.is_empty()
2520        {
2521            constructor.set_variant(&inner_variant_path.to_string())?;
2522        }
2523        constructor.write_subtree(&temp_doc, root_id)?;
2524        return Ok(());
2525    }
2526
2527    Err(DeError::NoVariantMatched)
2528}
2529
2530fn merge_adjacent_variant_content<'de>(
2531    content: EureContent<'de>,
2532    mut sibling_entries: Vec<(EureContent<'de>, EureContent<'de>)>,
2533    schema_content: &SchemaNodeContent,
2534) -> Result<EureContent<'de>, DeError> {
2535    if sibling_entries.is_empty() {
2536        return Ok(content);
2537    }
2538
2539    match schema_content {
2540        SchemaNodeContent::Record(_) | SchemaNodeContent::Map(_) | SchemaNodeContent::Union(_) => {
2541            match content {
2542                EureContent::Map(mut entries) => {
2543                    entries.append(&mut sibling_entries);
2544                    Ok(EureContent::Map(entries))
2545                }
2546                other => Err(DeError::TypeMismatch {
2547                    expected: "map",
2548                    actual: eure_content_type(&other).to_string(),
2549                }),
2550            }
2551        }
2552        _ => Err(DeError::Custom(
2553            "adjacent-tagged extra sibling fields require map-like variant content".to_string(),
2554        )),
2555    }
2556}
2557
2558fn bind_text_value(constructor: &mut DocumentConstructor, value: String) -> Result<(), DeError> {
2559    constructor
2560        .bind_primitive(PrimitiveValue::Text(Text::plaintext(value)))
2561        .map_err(Into::into)
2562}
2563
2564fn bind_integer_value(constructor: &mut DocumentConstructor, value: BigInt) -> Result<(), DeError> {
2565    constructor
2566        .bind_primitive(PrimitiveValue::Integer(value))
2567        .map_err(Into::into)
2568}
2569
2570fn bind_f32_value(constructor: &mut DocumentConstructor, value: f32) -> Result<(), DeError> {
2571    constructor
2572        .bind_primitive(PrimitiveValue::F32(value))
2573        .map_err(Into::into)
2574}
2575
2576fn bind_f64_value(constructor: &mut DocumentConstructor, value: f64) -> Result<(), DeError> {
2577    constructor
2578        .bind_primitive(PrimitiveValue::F64(value))
2579        .map_err(Into::into)
2580}
2581
2582fn bind_bool_value(constructor: &mut DocumentConstructor, value: bool) -> Result<(), DeError> {
2583    constructor
2584        .bind_primitive(PrimitiveValue::Bool(value))
2585        .map_err(Into::into)
2586}
2587
2588fn bind_null_value(constructor: &mut DocumentConstructor) -> Result<(), DeError> {
2589    constructor
2590        .bind_primitive(PrimitiveValue::Null)
2591        .map_err(Into::into)
2592}
2593
2594fn bind_bytes_as_array(constructor: &mut DocumentConstructor, bytes: &[u8]) -> Result<(), DeError> {
2595    constructor.bind_empty_array()?;
2596    for &byte in bytes {
2597        let scope = constructor.begin_scope();
2598        constructor.navigate(PathSegment::ArrayIndex(ArrayIndexKind::Push))?;
2599        constructor.bind_primitive(PrimitiveValue::Integer(BigInt::from(byte)))?;
2600        constructor.end_scope(scope)?;
2601    }
2602    Ok(())
2603}
2604
2605fn parse_bigint(value: &str) -> Result<BigInt, DeError> {
2606    BigInt::parse_bytes(value.as_bytes(), 10).ok_or_else(|| type_mismatch("integer", "text"))
2607}
2608
2609fn resolve_schema_node_id(
2610    schema: &SchemaDocument,
2611    mut schema_node_id: SchemaNodeId,
2612) -> Result<SchemaNodeId, DeError> {
2613    for _ in 0..schema.nodes.len() {
2614        match &schema.node(schema_node_id).content {
2615            SchemaNodeContent::Reference(type_ref) => {
2616                if let Some(namespace) = &type_ref.namespace {
2617                    return Err(DeError::Custom(format!(
2618                        "cross-schema references are unsupported: {namespace}.{}",
2619                        type_ref.name
2620                    )));
2621                }
2622                schema_node_id = schema.types.get(&type_ref.name).copied().ok_or_else(|| {
2623                    DeError::Custom(format!("undefined type reference: {}", type_ref.name))
2624                })?;
2625            }
2626            _ => return Ok(schema_node_id),
2627        }
2628    }
2629
2630    Err(DeError::Custom(
2631        "schema reference cycle detected".to_string(),
2632    ))
2633}
2634
2635fn extract_variant_path(
2636    doc: &EureDocument,
2637    node_id: eure::document::NodeId,
2638) -> Result<Option<VariantPath>, DeError> {
2639    let Some(variant_id) = doc
2640        .node(node_id)
2641        .extensions
2642        .get(&Identifier::VARIANT)
2643        .copied()
2644    else {
2645        return Ok(None);
2646    };
2647    let value = match &doc.node(variant_id).content {
2648        NodeValue::Primitive(PrimitiveValue::Text(text)) => text.as_str(),
2649        other => {
2650            return Err(DeError::TypeMismatch {
2651                expected: "text",
2652                actual: primitive_or_node_type_name(other).to_string(),
2653            });
2654        }
2655    };
2656
2657    VariantPath::parse(value)
2658        .map(Some)
2659        .map_err(|_| DeError::InvalidVariantName(value.to_string()))
2660}
2661
2662fn primitive_or_node_type_name(value: &NodeValue) -> &'static str {
2663    match value {
2664        NodeValue::Hole(_) => "hole",
2665        NodeValue::Primitive(PrimitiveValue::Null) => "null",
2666        NodeValue::Primitive(PrimitiveValue::Bool(_)) => "boolean",
2667        NodeValue::Primitive(PrimitiveValue::Integer(_)) => "integer",
2668        NodeValue::Primitive(PrimitiveValue::F32(_))
2669        | NodeValue::Primitive(PrimitiveValue::F64(_)) => "float",
2670        NodeValue::Primitive(PrimitiveValue::Text(_)) => "text",
2671        NodeValue::Array(_) => "array",
2672        NodeValue::Map(_) => "map",
2673        NodeValue::Tuple(_) => "tuple",
2674        NodeValue::PartialMap(_) => "partial-map",
2675    }
2676}
2677
2678fn content_key_matches(content: &EureContent<'_>, expected: &str) -> bool {
2679    match content {
2680        EureContent::String(value) => value.as_ref() == expected,
2681        EureContent::Char(value) => {
2682            let mut chars = expected.chars();
2683            chars.next() == Some(*value) && chars.next().is_none()
2684        }
2685        _ => false,
2686    }
2687}
2688
2689fn content_as_variant_name(content: EureContent<'_>) -> Result<String, DeError> {
2690    match content {
2691        EureContent::String(value) => Ok(value.into_owned()),
2692        EureContent::Char(value) => Ok(value.to_string()),
2693        other => Err(type_mismatch("text", eure_content_type(&other))),
2694    }
2695}
2696
2697fn type_mismatch(expected: &'static str, actual: impl Into<String>) -> DeError {
2698    DeError::TypeMismatch {
2699        expected,
2700        actual: actual.into(),
2701    }
2702}
2703
2704fn primitive_type_name(primitive: &PrimitiveValue) -> &'static str {
2705    match primitive {
2706        PrimitiveValue::Null => "null",
2707        PrimitiveValue::Bool(_) => "boolean",
2708        PrimitiveValue::Integer(_) => "integer",
2709        PrimitiveValue::F32(_) | PrimitiveValue::F64(_) => "float",
2710        PrimitiveValue::Text(_) => "text",
2711    }
2712}
2713
2714fn eure_content_type(content: &EureContent<'_>) -> String {
2715    match content {
2716        EureContent::Bool(_) => "boolean".to_string(),
2717        EureContent::I8(_)
2718        | EureContent::I16(_)
2719        | EureContent::I32(_)
2720        | EureContent::I64(_)
2721        | EureContent::I128(_)
2722        | EureContent::U8(_)
2723        | EureContent::U16(_)
2724        | EureContent::U32(_)
2725        | EureContent::U64(_)
2726        | EureContent::U128(_) => "integer".to_string(),
2727        EureContent::F32(_) | EureContent::F64(_) => "float".to_string(),
2728        EureContent::Char(_) | EureContent::String(_) => "text".to_string(),
2729        EureContent::Bytes(_) => "bytes".to_string(),
2730        EureContent::Unit => "null".to_string(),
2731        EureContent::Seq(_) => "array".to_string(),
2732        EureContent::Map(_) => "map".to_string(),
2733    }
2734}
2735
2736fn expected_primitive(expected: &EureDocument) -> Result<&PrimitiveValue, DeError> {
2737    expected
2738        .root()
2739        .as_primitive()
2740        .ok_or_else(unsupported_complex_literal_key)
2741}
2742
2743fn unsupported_complex_map_keys() -> DeError {
2744    DeError::Custom("complex map keys are unsupported in serde-eure v1".to_string())
2745}
2746
2747fn unsupported_complex_literal_key() -> DeError {
2748    DeError::Custom("complex literal map keys are unsupported in serde-eure v1".to_string())
2749}
2750
2751fn literal_integer_key(expected: &EureDocument, actual: BigInt) -> Result<ObjectKey, DeError> {
2752    match expected_primitive(expected)? {
2753        PrimitiveValue::Integer(expected_value) if expected_value == &actual => {
2754            Ok(ObjectKey::Number(actual))
2755        }
2756        PrimitiveValue::Integer(_) => Err(DeError::Custom("literal mismatch".to_string())),
2757        primitive => Err(type_mismatch("integer", primitive_type_name(primitive))),
2758    }
2759}
2760
2761fn literal_string_key(expected: &EureDocument, actual: &str) -> Result<ObjectKey, DeError> {
2762    match expected_primitive(expected)? {
2763        PrimitiveValue::Text(expected_value) if expected_value.as_str() == actual => {
2764            Ok(ObjectKey::String(actual.to_owned()))
2765        }
2766        PrimitiveValue::Text(_) => Err(DeError::Custom("literal mismatch".to_string())),
2767        PrimitiveValue::Integer(expected_value) => {
2768            let parsed = parse_bigint(actual)?;
2769            if expected_value == &parsed {
2770                Ok(ObjectKey::Number(parsed))
2771            } else {
2772                Err(DeError::Custom("literal mismatch".to_string()))
2773            }
2774        }
2775        PrimitiveValue::Bool(expected_value) => {
2776            let expected_text = if *expected_value { "true" } else { "false" };
2777            if actual == expected_text {
2778                Ok(ObjectKey::String(actual.to_owned()))
2779            } else {
2780                Err(DeError::Custom("literal mismatch".to_string()))
2781            }
2782        }
2783        PrimitiveValue::Null | PrimitiveValue::F32(_) | PrimitiveValue::F64(_) => {
2784            Err(unsupported_complex_literal_key())
2785        }
2786    }
2787}
2788
2789fn object_key_from_string_for_schema(
2790    schema: &SchemaDocument,
2791    schema_node_id: SchemaNodeId,
2792    value: &str,
2793) -> Result<ObjectKey, DeError> {
2794    let schema_node_id = resolve_schema_node_id(schema, schema_node_id)?;
2795
2796    match &schema.node(schema_node_id).content {
2797        SchemaNodeContent::Any | SchemaNodeContent::Text(_) => {
2798            Ok(ObjectKey::String(value.to_owned()))
2799        }
2800        SchemaNodeContent::Integer(_) => Ok(ObjectKey::Number(parse_bigint(value)?)),
2801        SchemaNodeContent::Boolean => match value {
2802            "true" | "false" => Ok(ObjectKey::String(value.to_owned())),
2803            _ => Err(type_mismatch("boolean", "text")),
2804        },
2805        SchemaNodeContent::Literal(expected) => literal_string_key(expected, value),
2806        SchemaNodeContent::Tuple(_)
2807        | SchemaNodeContent::Float(_)
2808        | SchemaNodeContent::Null
2809        | SchemaNodeContent::Array(_)
2810        | SchemaNodeContent::Map(_)
2811        | SchemaNodeContent::Record(_) => Err(unsupported_complex_map_keys()),
2812        SchemaNodeContent::Union(union_schema) => {
2813            union_key_from_string(schema, union_schema, value)
2814        }
2815        SchemaNodeContent::Reference(_) => unreachable!("references are resolved above"),
2816    }
2817}
2818
2819fn object_key_from_integer_for_schema(
2820    schema: &SchemaDocument,
2821    schema_node_id: SchemaNodeId,
2822    value: &BigInt,
2823) -> Result<ObjectKey, DeError> {
2824    let schema_node_id = resolve_schema_node_id(schema, schema_node_id)?;
2825
2826    match &schema.node(schema_node_id).content {
2827        SchemaNodeContent::Any | SchemaNodeContent::Integer(_) => {
2828            Ok(ObjectKey::Number(value.clone()))
2829        }
2830        SchemaNodeContent::Text(_) => Ok(ObjectKey::String(value.to_string())),
2831        SchemaNodeContent::Literal(expected) => literal_integer_key(expected, value.clone()),
2832        SchemaNodeContent::Union(union_schema) => {
2833            union_key_from_integer(schema, union_schema, value.clone())
2834        }
2835        SchemaNodeContent::Boolean
2836        | SchemaNodeContent::Tuple(_)
2837        | SchemaNodeContent::Float(_)
2838        | SchemaNodeContent::Null
2839        | SchemaNodeContent::Array(_)
2840        | SchemaNodeContent::Map(_)
2841        | SchemaNodeContent::Record(_) => Err(unsupported_complex_map_keys()),
2842        SchemaNodeContent::Reference(_) => unreachable!("references are resolved above"),
2843    }
2844}
2845
2846fn object_key_from_bool_for_schema(
2847    schema: &SchemaDocument,
2848    schema_node_id: SchemaNodeId,
2849    value: bool,
2850) -> Result<ObjectKey, DeError> {
2851    let schema_node_id = resolve_schema_node_id(schema, schema_node_id)?;
2852
2853    match &schema.node(schema_node_id).content {
2854        SchemaNodeContent::Any | SchemaNodeContent::Text(_) | SchemaNodeContent::Boolean => {
2855            Ok(ObjectKey::from(value))
2856        }
2857        SchemaNodeContent::Literal(expected) => match expected_primitive(expected)? {
2858            PrimitiveValue::Bool(expected_value) if *expected_value == value => {
2859                Ok(ObjectKey::from(value))
2860            }
2861            PrimitiveValue::Bool(_) => Err(DeError::Custom("literal mismatch".to_string())),
2862            primitive => Err(type_mismatch("boolean", primitive_type_name(primitive))),
2863        },
2864        SchemaNodeContent::Union(union_schema) => union_key_from_bool(schema, union_schema, value),
2865        SchemaNodeContent::Integer(_)
2866        | SchemaNodeContent::Tuple(_)
2867        | SchemaNodeContent::Float(_)
2868        | SchemaNodeContent::Null
2869        | SchemaNodeContent::Array(_)
2870        | SchemaNodeContent::Map(_)
2871        | SchemaNodeContent::Record(_) => Err(unsupported_complex_map_keys()),
2872        SchemaNodeContent::Reference(_) => unreachable!("references are resolved above"),
2873    }
2874}
2875
2876fn union_key_from_string(
2877    schema: &SchemaDocument,
2878    union_schema: &UnionSchema,
2879    value: &str,
2880) -> Result<ObjectKey, DeError> {
2881    if union_schema.variants.contains_key(value) {
2882        return Ok(ObjectKey::String(value.to_owned()));
2883    }
2884
2885    for &variant_schema_id in union_schema.variants.values() {
2886        if let Ok(key) = object_key_from_string_for_schema(schema, variant_schema_id, value) {
2887            return Ok(key);
2888        }
2889    }
2890
2891    Err(type_mismatch("map-key", "text"))
2892}
2893
2894fn union_key_from_integer(
2895    schema: &SchemaDocument,
2896    union_schema: &UnionSchema,
2897    value: BigInt,
2898) -> Result<ObjectKey, DeError> {
2899    for &variant_schema_id in union_schema.variants.values() {
2900        if let Ok(key) = object_key_from_integer_for_schema(schema, variant_schema_id, &value) {
2901            return Ok(key);
2902        }
2903    }
2904
2905    Err(type_mismatch("map-key", "integer"))
2906}
2907
2908fn union_key_from_bool(
2909    schema: &SchemaDocument,
2910    union_schema: &UnionSchema,
2911    value: bool,
2912) -> Result<ObjectKey, DeError> {
2913    for &variant_schema_id in union_schema.variants.values() {
2914        if let Ok(key) = object_key_from_bool_for_schema(schema, variant_schema_id, value) {
2915            return Ok(key);
2916        }
2917    }
2918
2919    Err(type_mismatch("map-key", "boolean"))
2920}
2921
2922#[cfg(test)]
2923mod tests {
2924    use eure::eure;
2925    use eure_schema::TextSchema;
2926    use eure_schema::interop::{UnionInterop, VariantRepr};
2927    use eure_schema::{
2928        IntegerSchema, RecordFieldSchema, RecordSchema, SchemaDocument, SchemaNodeContent,
2929        UnionSchema, UnknownFieldsPolicy,
2930    };
2931    use serde_json::Deserializer;
2932
2933    use super::from_deserializer;
2934
2935    fn make_record_schema() -> SchemaDocument {
2936        let mut schema = SchemaDocument::new();
2937        let text_id = schema.create_node(SchemaNodeContent::Text(TextSchema::default()));
2938        let int_id = schema.create_node(SchemaNodeContent::Integer(IntegerSchema::default()));
2939        let record_id = schema.create_node(SchemaNodeContent::Record(RecordSchema {
2940            properties: [
2941                (
2942                    "name".to_string(),
2943                    RecordFieldSchema {
2944                        schema: text_id,
2945                        optional: false,
2946                        binding_style: None,
2947                        field_codegen: Default::default(),
2948                    },
2949                ),
2950                (
2951                    "age".to_string(),
2952                    RecordFieldSchema {
2953                        schema: int_id,
2954                        optional: false,
2955                        binding_style: None,
2956                        field_codegen: Default::default(),
2957                    },
2958                ),
2959            ]
2960            .into_iter()
2961            .collect(),
2962            flatten: Vec::new(),
2963            unknown_fields: UnknownFieldsPolicy::Deny,
2964        }));
2965        schema.root = record_id;
2966        schema
2967    }
2968
2969    fn make_union_schema(variant_repr: VariantRepr) -> SchemaDocument {
2970        let mut schema = SchemaDocument::new();
2971        let text_id = schema.create_node(SchemaNodeContent::Text(TextSchema::default()));
2972        let success_record_id = schema.create_node(SchemaNodeContent::Record(RecordSchema {
2973            properties: [(
2974                "message".to_string(),
2975                RecordFieldSchema {
2976                    schema: text_id,
2977                    optional: false,
2978                    binding_style: None,
2979                    field_codegen: Default::default(),
2980                },
2981            )]
2982            .into_iter()
2983            .collect(),
2984            flatten: Vec::new(),
2985            unknown_fields: UnknownFieldsPolicy::Deny,
2986        }));
2987        let union_id = schema.create_node(SchemaNodeContent::Union(UnionSchema {
2988            variants: [("success".to_string(), success_record_id)]
2989                .into_iter()
2990                .collect(),
2991            unambiguous: Default::default(),
2992            interop: UnionInterop {
2993                variant_repr: Some(variant_repr),
2994            },
2995            deny_untagged: Default::default(),
2996        }));
2997        schema.root = union_id;
2998        schema
2999    }
3000
3001    #[test]
3002    fn deserializes_json_object_into_record_document() {
3003        let schema = make_record_schema();
3004        let mut de = Deserializer::from_str(r#"{ "name": "Alice", "age": 30 }"#);
3005
3006        let actual = from_deserializer(&mut de, &schema).unwrap();
3007        let expected = eure!({
3008            name = "Alice",
3009            age = 30,
3010        });
3011
3012        assert_eq!(actual, expected);
3013    }
3014
3015    #[test]
3016    fn deserializes_external_variant_into_document() {
3017        let schema = make_union_schema(VariantRepr::External);
3018        let mut de = Deserializer::from_str(r#"{ "success": { "message": "ok" } }"#);
3019
3020        let actual = from_deserializer(&mut de, &schema).unwrap();
3021        let expected = eure!({
3022            message = "ok",
3023            %variant = "success",
3024        });
3025
3026        assert_eq!(actual, expected);
3027    }
3028
3029    #[test]
3030    fn deserializes_internal_variant_into_document() {
3031        let schema = make_union_schema(VariantRepr::Internal {
3032            tag: "type".to_string(),
3033        });
3034        let mut de = Deserializer::from_str(r#"{ "type": "success", "message": "ok" }"#);
3035
3036        let actual = from_deserializer(&mut de, &schema).unwrap();
3037        let expected = eure!({
3038            message = "ok",
3039            %variant = "success",
3040        });
3041
3042        assert_eq!(actual, expected);
3043    }
3044}