Skip to main content

helios_serde_support/
lib.rs

1// Serde traits used in custom Deserialize implementations
2
3/// Helper that accepts either a single value or an array when deserializing.
4///
5/// FHIR allows most repeatable elements to appear either once or multiple times
6/// depending on the instance's actual cardinality. While JSON carries enough
7/// structure (`[]` vs scalar) so serde can infer that automatically, the XML
8/// stream does not embed the schema-driven cardinality constraints. During
9/// XML deserialization we therefore wrap every field with a `min > 0` upper
10/// bound in `SingleOrVec` so we can accept both the single-element case and
11/// the repeated-element case without schema knowledge at parse time.
12#[derive(Clone, Debug, PartialEq)]
13pub struct SingleOrVec<T>(Vec<T>);
14
15impl<T> AsRef<[T]> for SingleOrVec<T> {
16    #[inline]
17    fn as_ref(&self) -> &[T] {
18        &self.0
19    }
20}
21
22impl<T> From<SingleOrVec<T>> for Vec<T> {
23    #[inline]
24    fn from(wrapper: SingleOrVec<T>) -> Self {
25        wrapper.0
26    }
27}
28
29impl<T> Default for SingleOrVec<T> {
30    #[inline]
31    fn default() -> Self {
32        SingleOrVec(Vec::new())
33    }
34}
35
36// JSON-only: delegate directly to Vec<T> — no deserialize_any overhead
37#[cfg(not(feature = "xml"))]
38impl<'de, T> serde::Deserialize<'de> for SingleOrVec<T>
39where
40    T: serde::Deserialize<'de>,
41{
42    #[inline]
43    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
44    where
45        D: serde::Deserializer<'de>,
46    {
47        Vec::<T>::deserialize(deserializer).map(SingleOrVec)
48    }
49}
50
51// XML+JSON: uses deserialize_any to handle both single values and arrays
52#[cfg(feature = "xml")]
53impl<'de, T> serde::Deserialize<'de> for SingleOrVec<T>
54where
55    T: serde::Deserialize<'de>,
56{
57    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
58    where
59        D: serde::Deserializer<'de>,
60    {
61        struct SingleOrVecVisitor<T>(std::marker::PhantomData<T>);
62
63        impl<'de, T> serde::de::Visitor<'de> for SingleOrVecVisitor<T>
64        where
65            T: serde::Deserialize<'de>,
66        {
67            type Value = SingleOrVec<T>;
68
69            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
70                formatter.write_str("a single value or a sequence")
71            }
72
73            // High performance path for JSON arrays or repeated XML tags
74            #[inline]
75            fn visit_seq<A>(self, seq: A) -> Result<Self::Value, A::Error>
76            where
77                A: serde::de::SeqAccess<'de>,
78            {
79                let values = serde::Deserialize::deserialize(
80                    serde::de::value::SeqAccessDeserializer::new(seq),
81                )?;
82                Ok(SingleOrVec(values))
83            }
84
85            // Path for single XML elements (map = object with fields)
86            #[inline]
87            fn visit_map<M>(self, map: M) -> Result<Self::Value, M::Error>
88            where
89                M: serde::de::MapAccess<'de>,
90            {
91                let value =
92                    deserialize_single_value(serde::de::value::MapAccessDeserializer::new(map))?;
93                Ok(SingleOrVec(vec![value]))
94            }
95
96            // Path for JSON scalars or XML text-only elements
97            #[inline]
98            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
99            where
100                E: serde::de::Error,
101            {
102                let value = deserialize_from_str(v).map_err(serde::de::Error::custom)?;
103                Ok(SingleOrVec(vec![value]))
104            }
105
106            #[inline]
107            fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
108            where
109                E: serde::de::Error,
110            {
111                let value = deserialize_single_value(serde::de::value::BoolDeserializer::new(v))?;
112                Ok(SingleOrVec(vec![value]))
113            }
114
115            #[inline]
116            fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
117            where
118                E: serde::de::Error,
119            {
120                let value = deserialize_single_value(serde::de::value::I64Deserializer::new(v))?;
121                Ok(SingleOrVec(vec![value]))
122            }
123
124            #[inline]
125            fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
126            where
127                E: serde::de::Error,
128            {
129                let value = deserialize_single_value(serde::de::value::U64Deserializer::new(v))?;
130                Ok(SingleOrVec(vec![value]))
131            }
132
133            #[inline]
134            fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
135            where
136                E: serde::de::Error,
137            {
138                let value = deserialize_single_value(serde::de::value::F64Deserializer::new(v))?;
139                Ok(SingleOrVec(vec![value]))
140            }
141        }
142
143        deserializer.deserialize_any(SingleOrVecVisitor(std::marker::PhantomData))
144    }
145}
146
147/// Accepts either JSON primitive values or XML element structures with metadata.
148///
149/// **JSON Format**: Primitive values come through as scalars, metadata merged from `_field` by macro.
150///   - `"birthDate": "1970-03-30"` → `Primitive("1970-03-30")` (String directly)
151///   - Metadata in `_field` is handled separately by the generated macro code
152///
153/// **XML Format**: All primitives are elements with inline metadata, no `_field` exists.
154///   - `<birthDate value="1970-03-30"/>` → `Element(Element { value: Some(...), id: None, ... })`
155///   - `<birthDate id="x" value="...">` → `Element(Element { value, id, ... })`
156///   - `<birthDate id="x" value="..."><extension>...</extension></birthDate>` → `Element` with full metadata
157///
158/// The custom `Deserialize` impl mirrors the old `#[serde(untagged)]` behavior without buffering:
159/// - JSON scalars map to the `Primitive` variant (directly deserialized into the primitive type).
160/// - XML element structures (objects with `value`, `id`, `extension`, …) map to the `Element` variant.
161/// It avoids serde’s internal `Content` buffering while preserving semantics crucial for primitives
162/// with metadata.
163///
164/// # Type Parameters
165/// - `P`: Primitive type (the final deserialized type, e.g. `String`, `i32`, `bool`)
166/// - `E`: Element type (struct containing value and metadata fields)
167#[derive(Clone, Debug, PartialEq)]
168pub enum PrimitiveOrElement<P, E> {
169    // Try Element first (more specific - requires object structure)
170    Element(E),
171    // Fall back to Primitive (catch-all for JSON scalars)
172    Primitive(P),
173}
174
175// JSON-only: always produces Primitive — no deserialize_any overhead
176#[cfg(not(feature = "xml"))]
177impl<'de, P, E> serde::Deserialize<'de> for PrimitiveOrElement<P, E>
178where
179    P: serde::Deserialize<'de>,
180{
181    #[inline]
182    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
183    where
184        D: serde::Deserializer<'de>,
185    {
186        P::deserialize(deserializer).map(PrimitiveOrElement::Primitive)
187    }
188}
189
190// XML+JSON: uses deserialize_any to distinguish primitives from element objects
191#[cfg(feature = "xml")]
192impl<'de, P, E> serde::Deserialize<'de> for PrimitiveOrElement<P, E>
193where
194    P: serde::Deserialize<'de>,
195    E: serde::Deserialize<'de>,
196{
197    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
198    where
199        D: serde::Deserializer<'de>,
200    {
201        struct PrimitiveOrElementVisitor<P, E>(std::marker::PhantomData<(P, E)>);
202
203        impl<'de, P, E> serde::de::Visitor<'de> for PrimitiveOrElementVisitor<P, E>
204        where
205            P: serde::Deserialize<'de>,
206            E: serde::Deserialize<'de>,
207        {
208            type Value = PrimitiveOrElement<P, E>;
209
210            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
211                formatter.write_str("a primitive value or an element object")
212            }
213
214            #[inline]
215            fn visit_map<M>(self, map: M) -> Result<Self::Value, M::Error>
216            where
217                M: serde::de::MapAccess<'de>,
218            {
219                let element = E::deserialize(serde::de::value::MapAccessDeserializer::new(map))?;
220                Ok(PrimitiveOrElement::Element(element))
221            }
222
223            #[inline]
224            fn visit_seq<A>(self, seq: A) -> Result<Self::Value, A::Error>
225            where
226                A: serde::de::SeqAccess<'de>,
227            {
228                let primitive =
229                    deserialize_single_value(serde::de::value::SeqAccessDeserializer::new(seq))?;
230                Ok(PrimitiveOrElement::Primitive(primitive))
231            }
232
233            #[inline]
234            fn visit_str<E2>(self, v: &str) -> Result<Self::Value, E2>
235            where
236                E2: serde::de::Error,
237            {
238                let primitive = deserialize_from_str(v).map_err(serde::de::Error::custom)?;
239                Ok(PrimitiveOrElement::Primitive(primitive))
240            }
241
242            #[inline]
243            fn visit_string<E2>(self, v: String) -> Result<Self::Value, E2>
244            where
245                E2: serde::de::Error,
246            {
247                let primitive = deserialize_from_str(&v).map_err(serde::de::Error::custom)?;
248                Ok(PrimitiveOrElement::Primitive(primitive))
249            }
250
251            #[inline]
252            fn visit_bool<E2>(self, v: bool) -> Result<Self::Value, E2>
253            where
254                E2: serde::de::Error,
255            {
256                let primitive =
257                    deserialize_single_value(serde::de::value::BoolDeserializer::new(v))?;
258                Ok(PrimitiveOrElement::Primitive(primitive))
259            }
260
261            #[inline]
262            fn visit_i64<E2>(self, v: i64) -> Result<Self::Value, E2>
263            where
264                E2: serde::de::Error,
265            {
266                let primitive =
267                    deserialize_single_value(serde::de::value::I64Deserializer::new(v))?;
268                Ok(PrimitiveOrElement::Primitive(primitive))
269            }
270
271            #[inline]
272            fn visit_u64<E2>(self, v: u64) -> Result<Self::Value, E2>
273            where
274                E2: serde::de::Error,
275            {
276                let primitive =
277                    deserialize_single_value(serde::de::value::U64Deserializer::new(v))?;
278                Ok(PrimitiveOrElement::Primitive(primitive))
279            }
280
281            #[inline]
282            fn visit_f64<E2>(self, v: f64) -> Result<Self::Value, E2>
283            where
284                E2: serde::de::Error,
285            {
286                let primitive =
287                    deserialize_single_value(serde::de::value::F64Deserializer::new(v))?;
288                Ok(PrimitiveOrElement::Primitive(primitive))
289            }
290
291            #[inline]
292            fn visit_none<E2>(self) -> Result<Self::Value, E2>
293            where
294                E2: serde::de::Error,
295            {
296                let primitive = P::deserialize(serde::de::value::UnitDeserializer::new())?;
297                Ok(PrimitiveOrElement::Primitive(primitive))
298            }
299
300            #[inline]
301            fn visit_unit<E2>(self) -> Result<Self::Value, E2>
302            where
303                E2: serde::de::Error,
304            {
305                let primitive = P::deserialize(serde::de::value::UnitDeserializer::new())?;
306                Ok(PrimitiveOrElement::Primitive(primitive))
307            }
308
309            #[inline]
310            fn visit_some<D2>(self, deserializer: D2) -> Result<Self::Value, D2::Error>
311            where
312                D2: serde::Deserializer<'de>,
313            {
314                let primitive = deserialize_single_value(deserializer)?;
315                Ok(PrimitiveOrElement::Primitive(primitive))
316            }
317
318            #[inline]
319            fn visit_newtype_struct<D2>(self, deserializer: D2) -> Result<Self::Value, D2::Error>
320            where
321                D2: serde::Deserializer<'de>,
322            {
323                let primitive = deserialize_single_value(deserializer)?;
324                Ok(PrimitiveOrElement::Primitive(primitive))
325            }
326
327            #[inline]
328            fn visit_enum<D2>(self, data: D2) -> Result<Self::Value, D2::Error>
329            where
330                D2: serde::de::EnumAccess<'de>,
331            {
332                let primitive =
333                    deserialize_single_value(serde::de::value::EnumAccessDeserializer::new(data))?;
334                Ok(PrimitiveOrElement::Primitive(primitive))
335            }
336
337            #[inline]
338            fn visit_char<E2>(self, v: char) -> Result<Self::Value, E2>
339            where
340                E2: serde::de::Error,
341            {
342                let primitive =
343                    deserialize_single_value(serde::de::value::CharDeserializer::new(v))?;
344                Ok(PrimitiveOrElement::Primitive(primitive))
345            }
346        }
347
348        deserializer.deserialize_any(PrimitiveOrElementVisitor(std::marker::PhantomData))
349    }
350}
351
352#[cfg(feature = "xml")]
353#[inline]
354fn deserialize_single_value<'de, D, T>(deserializer: D) -> Result<T, D::Error>
355where
356    D: serde::Deserializer<'de>,
357    T: serde::Deserialize<'de>,
358{
359    /// Wraps a deserializer so that `Option<T>` values produced from scalars are treated as `Some(T)`.
360    struct OptionFriendlyDeserializer<D>(D);
361
362    impl<'de, D> serde::Deserializer<'de> for OptionFriendlyDeserializer<D>
363    where
364        D: serde::Deserializer<'de>,
365    {
366        type Error = D::Error;
367
368        #[inline]
369        fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
370        where
371            V: serde::de::Visitor<'de>,
372        {
373            self.0.deserialize_any(visitor)
374        }
375
376        #[inline]
377        fn deserialize_enum<V>(
378            self,
379            name: &'static str,
380            variants: &'static [&'static str],
381            visitor: V,
382        ) -> Result<V::Value, Self::Error>
383        where
384            V: serde::de::Visitor<'de>,
385        {
386            self.0.deserialize_enum(name, variants, visitor)
387        }
388
389        #[inline]
390        fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
391        where
392            V: serde::de::Visitor<'de>,
393        {
394            visitor.visit_some(self.0)
395        }
396
397        serde::forward_to_deserialize_any! {
398            bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
399            bytes byte_buf unit unit_struct newtype_struct seq tuple tuple_struct
400            map struct identifier ignored_any
401        }
402    }
403    T::deserialize(OptionFriendlyDeserializer(deserializer))
404}
405
406#[cfg(feature = "xml")]
407/// Deserializer that wraps a string value and tries to parse it as the requested type.
408///
409/// XML sends all primitive values as strings. This deserializer enables transparent
410/// conversion from strings to bool, integer, and float types during deserialization.
411/// It first tries the string directly (works for String targets), and if the target
412/// type requests a specific numeric or boolean type, it parses the string accordingly.
413struct StringParsingDeserializer<'a>(&'a str);
414
415#[cfg(feature = "xml")]
416impl<'de, 'a> serde::Deserializer<'de> for StringParsingDeserializer<'a> {
417    type Error = serde::de::value::Error;
418
419    #[inline]
420    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
421    where
422        V: serde::de::Visitor<'de>,
423    {
424        // Try string first (works for String, &str targets)
425        visitor.visit_str(self.0)
426    }
427
428    #[inline]
429    fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
430    where
431        V: serde::de::Visitor<'de>,
432    {
433        match self.0 {
434            "true" => visitor.visit_bool(true),
435            "false" => visitor.visit_bool(false),
436            _ => Err(serde::de::Error::invalid_value(
437                serde::de::Unexpected::Str(self.0),
438                &"true or false",
439            )),
440        }
441    }
442
443    #[inline]
444    fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
445    where
446        V: serde::de::Visitor<'de>,
447    {
448        match self.0.parse::<i8>() {
449            Ok(v) => visitor.visit_i8(v),
450            Err(_) => Err(serde::de::Error::invalid_value(
451                serde::de::Unexpected::Str(self.0),
452                &"an i8 integer",
453            )),
454        }
455    }
456
457    #[inline]
458    fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
459    where
460        V: serde::de::Visitor<'de>,
461    {
462        match self.0.parse::<i16>() {
463            Ok(v) => visitor.visit_i16(v),
464            Err(_) => Err(serde::de::Error::invalid_value(
465                serde::de::Unexpected::Str(self.0),
466                &"an i16 integer",
467            )),
468        }
469    }
470
471    #[inline]
472    fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
473    where
474        V: serde::de::Visitor<'de>,
475    {
476        match self.0.parse::<i32>() {
477            Ok(v) => visitor.visit_i32(v),
478            Err(_) => Err(serde::de::Error::invalid_value(
479                serde::de::Unexpected::Str(self.0),
480                &"an i32 integer",
481            )),
482        }
483    }
484
485    #[inline]
486    fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
487    where
488        V: serde::de::Visitor<'de>,
489    {
490        match self.0.parse::<i64>() {
491            Ok(v) => visitor.visit_i64(v),
492            Err(_) => Err(serde::de::Error::invalid_value(
493                serde::de::Unexpected::Str(self.0),
494                &"an i64 integer",
495            )),
496        }
497    }
498
499    #[inline]
500    fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
501    where
502        V: serde::de::Visitor<'de>,
503    {
504        match self.0.parse::<u8>() {
505            Ok(v) => visitor.visit_u8(v),
506            Err(_) => Err(serde::de::Error::invalid_value(
507                serde::de::Unexpected::Str(self.0),
508                &"a u8 integer",
509            )),
510        }
511    }
512
513    #[inline]
514    fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
515    where
516        V: serde::de::Visitor<'de>,
517    {
518        match self.0.parse::<u16>() {
519            Ok(v) => visitor.visit_u16(v),
520            Err(_) => Err(serde::de::Error::invalid_value(
521                serde::de::Unexpected::Str(self.0),
522                &"a u16 integer",
523            )),
524        }
525    }
526
527    #[inline]
528    fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
529    where
530        V: serde::de::Visitor<'de>,
531    {
532        match self.0.parse::<u32>() {
533            Ok(v) => visitor.visit_u32(v),
534            Err(_) => Err(serde::de::Error::invalid_value(
535                serde::de::Unexpected::Str(self.0),
536                &"a u32 integer",
537            )),
538        }
539    }
540
541    #[inline]
542    fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
543    where
544        V: serde::de::Visitor<'de>,
545    {
546        match self.0.parse::<u64>() {
547            Ok(v) => visitor.visit_u64(v),
548            Err(_) => Err(serde::de::Error::invalid_value(
549                serde::de::Unexpected::Str(self.0),
550                &"a u64 integer",
551            )),
552        }
553    }
554
555    #[inline]
556    fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
557    where
558        V: serde::de::Visitor<'de>,
559    {
560        match self.0.parse::<f32>() {
561            Ok(v) => visitor.visit_f32(v),
562            Err(_) => Err(serde::de::Error::invalid_value(
563                serde::de::Unexpected::Str(self.0),
564                &"an f32 float",
565            )),
566        }
567    }
568
569    #[inline]
570    fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
571    where
572        V: serde::de::Visitor<'de>,
573    {
574        match self.0.parse::<f64>() {
575            Ok(v) => visitor.visit_f64(v),
576            Err(_) => Err(serde::de::Error::invalid_value(
577                serde::de::Unexpected::Str(self.0),
578                &"an f64 float",
579            )),
580        }
581    }
582
583    #[inline]
584    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
585    where
586        V: serde::de::Visitor<'de>,
587    {
588        visitor.visit_some(self)
589    }
590
591    serde::forward_to_deserialize_any! {
592        char str string bytes byte_buf unit unit_struct newtype_struct
593        seq tuple tuple_struct map struct enum identifier ignored_any
594    }
595
596    #[inline]
597    fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
598    where
599        V: serde::de::Visitor<'de>,
600    {
601        match self.0.parse::<i128>() {
602            Ok(v) => visitor.visit_i128(v),
603            Err(_) => Err(serde::de::Error::invalid_value(
604                serde::de::Unexpected::Str(self.0),
605                &"an i128 integer",
606            )),
607        }
608    }
609
610    #[inline]
611    fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
612    where
613        V: serde::de::Visitor<'de>,
614    {
615        match self.0.parse::<u128>() {
616            Ok(v) => visitor.visit_u128(v),
617            Err(_) => Err(serde::de::Error::invalid_value(
618                serde::de::Unexpected::Str(self.0),
619                &"a u128 integer",
620            )),
621        }
622    }
623}
624
625#[cfg(feature = "xml")]
626/// Deserializes a value from a string, trying type-specific parsing.
627///
628/// Used by `PrimitiveOrElement` and `SingleOrVec` when receiving string values
629/// from the XML deserializer to convert them into concrete primitive types.
630/// Uses `StringParsingDeserializer` directly (not `deserialize_single_value`)
631/// because the `OptionFriendlyDeserializer` wrapper would forward type-specific
632/// methods like `deserialize_i32` back to `deserialize_any`, losing the parsing.
633#[inline]
634fn deserialize_from_str<'de, T>(s: &str) -> Result<T, serde::de::value::Error>
635where
636    T: serde::Deserialize<'de>,
637{
638    T::deserialize(StringParsingDeserializer(s))
639}
640
641/// Helper struct for serializing id and extension metadata for FHIR primitives.
642///
643/// In FHIR JSON, primitive values can have associated metadata stored in a parallel
644/// `_fieldName` object containing an `id` and/or `extension` array.
645///
646/// This helper is used during serialization to output only the id/extension metadata
647/// while the primitive value itself is serialized separately.
648///
649/// # Type Parameters
650/// - `'a`: Lifetime of the borrowed data
651/// - `E`: Extension type (varies by FHIR version: R4, R4B, R5, R6)
652///
653/// # Example
654/// ```json
655/// {
656///   "status": "active",
657///   "_status": {
658///     "id": "status-1",
659///     "extension": [...]
660///   }
661/// }
662/// ```
663#[derive(serde::Serialize)]
664pub struct IdAndExtensionHelper<'a, E> {
665    #[serde(skip_serializing_if = "Option::is_none")]
666    pub id: &'a Option<String>,
667    #[serde(skip_serializing_if = "Option::is_none")]
668    pub extension: &'a Option<Vec<E>>,
669}
670
671/// Helper struct for deserializing id and extension metadata for FHIR primitives.
672///
673/// This is the owned version of `IdAndExtensionHelper`, used during deserialization
674/// to capture id and extension data from the `_fieldName` JSON object.
675///
676/// # Type Parameters
677/// - `E`: Extension type (varies by FHIR version: R4, R4B, R5, R6)
678#[derive(Clone, serde::Deserialize, Default)]
679pub struct IdAndExtensionOwned<E> {
680    #[serde(skip_serializing_if = "Option::is_none")]
681    pub id: Option<String>,
682    #[serde(skip_serializing_if = "Option::is_none")]
683    pub extension: Option<Vec<E>>,
684}