Skip to main content

fhir_types/
codec.rs

1// @generated by fhir-codegen from hl7.fhir.r4.core 4.0.1, hl7.fhir.r4b.core 4.3.0, hl7.fhir.r5.core 5.0.0, hl7.fhir.r6.core 6.0.0-ballot5, hl7.fhir.r3.core 3.0.2. DO NOT EDIT.
2// Change the emitter (tools/fhir-codegen) and regenerate.
3// SPDX-FileCopyrightText: Cadasto B.V.
4// SPDX-License-Identifier: Apache-2.0
5//! The FHIR JSON representation shared by every version module.
6//!
7//! Resources carry `resourceType`; a primitive element is a JSON value plus an
8//! optional sibling named with a leading underscore that holds its `id` and
9//! `extension`; repeating primitives are two arrays aligned with `null`;
10//! integers and decimals are JSON numbers with their lexical form preserved;
11//! objects and arrays are never empty; unknown properties are refused
12//! (<https://hl7.org/fhir/R4B/json.html>).
13
14use std::collections::BTreeMap;
15use std::fmt;
16use std::str::FromStr;
17
18use serde_json::value::RawValue;
19
20/// A JSON object, its keys in sorted order.
21pub type Object = BTreeMap<String, Value>;
22
23/// A JSON number, in the lexical form the document carried.
24///
25/// FHIR forbids reading a decimal through a binary float: "Do not use an IEEE
26/// type floating point type, instead use something that works like a true
27/// decimal" (<https://hl7.org/fhir/R4B/datatypes.html#decimal>), so the number
28/// keeps its text and the codec never rounds it.
29#[derive(Debug, Clone, PartialEq, Eq)]
30pub struct Number(String);
31
32impl Number {
33    /// The number as it was written.
34    #[must_use]
35    pub fn as_str(&self) -> &str {
36        &self.0
37    }
38
39    /// The number as an `i64`, `None` when it is no whole number in range.
40    #[must_use]
41    pub fn as_i64(&self) -> Option<i64> {
42        self.as_str().parse().ok()
43    }
44
45    /// The number as a `u64`, `None` when it is no whole number in range.
46    #[must_use]
47    pub fn as_u64(&self) -> Option<u64> {
48        self.as_str().parse().ok()
49    }
50}
51
52impl fmt::Display for Number {
53    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54        f.write_str(self.as_str())
55    }
56}
57
58/// Text that is no JSON number.
59#[derive(Debug, Clone, Copy, PartialEq, Eq)]
60pub struct NotANumber;
61
62impl fmt::Display for NotANumber {
63    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64        f.write_str("not a JSON number")
65    }
66}
67
68impl std::error::Error for NotANumber {}
69
70impl FromStr for Number {
71    type Err = NotANumber;
72
73    fn from_str(text: &str) -> Result<Self, Self::Err> {
74        let numeric = matches!(text.as_bytes().first(), Some(b'-' | b'0'..=b'9'))
75            && matches!(text.as_bytes().last(), Some(b'0'..=b'9'));
76        if !numeric {
77            return Err(NotANumber);
78        }
79        serde_json::from_str::<&RawValue>(text).map_err(|_| NotANumber)?;
80        Ok(Self(String::from(text)))
81    }
82}
83
84impl From<i64> for Number {
85    fn from(value: i64) -> Self {
86        Self(value.to_string())
87    }
88}
89
90impl From<i32> for Number {
91    fn from(value: i32) -> Self {
92        Self::from(i64::from(value))
93    }
94}
95
96impl From<u32> for Number {
97    fn from(value: u32) -> Self {
98        Self::from(i64::from(value))
99    }
100}
101
102impl serde::Serialize for Number {
103    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
104        // NOTE: JSON forbids a leading plus or zero (RFC 8259 ยง6), so an `i64`
105        // that parses writes back the same text apart from `-0`; every other
106        // number goes out raw, keeping the precision FHIR gives it.
107        match self.as_i64() {
108            Some(whole) if self.as_str() != "-0" => serializer.serialize_i64(whole),
109            _ => {
110                let raw = serde_json::from_str::<&RawValue>(self.as_str())
111                    .map_err(serde::ser::Error::custom)?;
112                serde::Serialize::serialize(raw, serializer)
113            }
114        }
115    }
116}
117
118/// A JSON document, with every number kept in its lexical form.
119///
120/// Reading one goes through `serde_json`'s raw value, so a number arrives with
121/// the precision the document wrote and the crate imposes no
122/// `arbitrary_precision` feature on anything that depends on it.
123#[derive(Debug, Clone, Default, PartialEq, Eq)]
124pub enum Value {
125    /// `null`.
126    #[default]
127    Null,
128    /// `true` or `false`.
129    Bool(bool),
130    /// A number.
131    Number(Number),
132    /// A string.
133    String(String),
134    /// An array.
135    Array(Vec<Value>),
136    /// An object.
137    Object(Object),
138}
139
140impl Value {
141    /// The member named `key`, `None` unless this is an object holding it.
142    #[must_use]
143    pub fn get(&self, key: &str) -> Option<&Self> {
144        match self {
145            Self::Object(object) => object.get(key),
146            _ => None,
147        }
148    }
149
150    /// The object this holds, `None` for every other kind.
151    #[must_use]
152    pub const fn as_object(&self) -> Option<&Object> {
153        match self {
154            Self::Object(object) => Some(object),
155            _ => None,
156        }
157    }
158
159    /// The array this holds, `None` for every other kind.
160    #[must_use]
161    pub fn as_array(&self) -> Option<&[Self]> {
162        match self {
163            Self::Array(items) => Some(items),
164            _ => None,
165        }
166    }
167
168    /// The string this holds, `None` for every other kind.
169    #[must_use]
170    pub fn as_str(&self) -> Option<&str> {
171        match self {
172            Self::String(text) => Some(text),
173            _ => None,
174        }
175    }
176
177    /// Whether this is `null`.
178    #[must_use]
179    pub const fn is_null(&self) -> bool {
180        matches!(self, Self::Null)
181    }
182
183    /// This document as a `serde_json::Value`, keeping every number exact.
184    ///
185    /// A number converts only when `serde_json` writes it back in the text
186    /// this document carried, so a decimal is never altered on the way out:
187    /// FHIR regards `0.010` as different from `0.01`
188    /// (<https://hl7.org/fhir/R4/datatypes.html#decimal>). A `serde_json`
189    /// built with `arbitrary_precision` keeps every lexical form, and one
190    /// built without it keeps whole numbers and the decimals `f64` writes back
191    /// unchanged. Object keys stay in the sorted order [`Object`] holds them
192    /// in, which carries no meaning: "the order of properties of an object is
193    /// not significant in the JSON representation"
194    /// (<https://hl7.org/fhir/R4/json.html>).
195    ///
196    /// # Errors
197    ///
198    /// Returns [`ValueConversionError`] naming the element path of the first
199    /// number `serde_json` would alter or cannot hold.
200    pub fn into_serde_json(
201        self,
202        path: &mut Path,
203    ) -> Result<serde_json::Value, ValueConversionError> {
204        match self {
205            Self::Null => Ok(serde_json::Value::Null),
206            Self::Bool(flag) => Ok(serde_json::Value::Bool(flag)),
207            Self::Number(number) => convert_number(&number, path).map(serde_json::Value::Number),
208            Self::String(text) => Ok(serde_json::Value::String(text)),
209            Self::Array(items) => {
210                let mut converted = Vec::with_capacity(items.len());
211                for (index, item) in items.into_iter().enumerate() {
212                    converted.push(path.with_index("", index, |path| item.into_serde_json(path))?);
213                }
214                Ok(serde_json::Value::Array(converted))
215            }
216            Self::Object(members) => {
217                let mut converted = serde_json::Map::with_capacity(members.len());
218                for (key, member) in members {
219                    let value = convert_member(&key, member, path)?;
220                    converted.insert(key, value);
221                }
222                Ok(serde_json::Value::Object(converted))
223            }
224        }
225    }
226
227    /// A copy of this document as a `serde_json::Value`, keeping every number
228    /// exact.
229    ///
230    /// The document is cloned first, so prefer [`Value::into_serde_json`]
231    /// where the caller owns it. The number rule is the same.
232    ///
233    /// # Errors
234    ///
235    /// Returns [`ValueConversionError`] naming the element path of the first
236    /// number `serde_json` would alter or cannot hold.
237    pub fn to_serde_json(
238        &self,
239        path: &mut Path,
240    ) -> Result<serde_json::Value, ValueConversionError> {
241        self.clone().into_serde_json(path)
242    }
243
244    /// A `serde_json::Value` as this document.
245    ///
246    /// A number arrives in the text `serde_json` holds for it, which is the
247    /// form the document carried when `serde_json` was built with
248    /// `arbitrary_precision` and the `f64` rendering of it otherwise. Read a
249    /// FHIR document whose decimals must stay exact through this crate's own
250    /// [`Value`] decoder instead; this direction serves the HTTP edge and test
251    /// fixtures, where the document is already a `serde_json::Value`.
252    #[must_use]
253    pub fn from_serde_json(value: serde_json::Value) -> Self {
254        match value {
255            serde_json::Value::Null => Self::Null,
256            serde_json::Value::Bool(flag) => Self::Bool(flag),
257            serde_json::Value::Number(number) => Self::Number(Number(number.to_string())),
258            serde_json::Value::String(text) => Self::String(text),
259            serde_json::Value::Array(items) => {
260                Self::Array(items.into_iter().map(Self::from_serde_json).collect())
261            }
262            serde_json::Value::Object(members) => Self::Object(
263                members
264                    .into_iter()
265                    .map(|(key, member)| (key, Self::from_serde_json(member)))
266                    .collect(),
267            ),
268        }
269    }
270}
271
272/// Why a [`Value`] has no `serde_json::Value` form.
273#[derive(Debug, Clone, PartialEq, Eq)]
274pub enum ValueConversionError {
275    /// `serde_json` writes the number back in another form.
276    LossyNumber {
277        /// The element path, for example `Observation.valueQuantity.value`.
278        path: String,
279        /// The number as the document carried it.
280        lexical: String,
281        /// The number as `serde_json` writes it.
282        rendered: String,
283    },
284    /// `serde_json` holds no number of this magnitude.
285    UnrepresentableNumber {
286        /// The element path, for example `Observation.valueQuantity.value`.
287        path: String,
288        /// The number as the document carried it.
289        lexical: String,
290    },
291}
292
293impl fmt::Display for ValueConversionError {
294    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
295        match self {
296            Self::LossyNumber {
297                path,
298                lexical,
299                rendered,
300            } => write!(f, "{path}: serde_json writes {lexical} as {rendered}"),
301            Self::UnrepresentableNumber { path, lexical } => {
302                write!(f, "{path}: serde_json holds no number {lexical}")
303            }
304        }
305    }
306}
307
308impl std::error::Error for ValueConversionError {}
309
310fn convert_number(
311    number: &Number,
312    path: &Path,
313) -> Result<serde_json::Number, ValueConversionError> {
314    let lexical = number.as_str();
315    let converted = serde_json::Number::from_str(lexical).map_err(|_| {
316        ValueConversionError::UnrepresentableNumber {
317            path: path.location(),
318            lexical: String::from(lexical),
319        }
320    })?;
321    let rendered = converted.to_string();
322    if rendered == lexical {
323        return Ok(converted);
324    }
325    Err(ValueConversionError::LossyNumber {
326        path: path.location(),
327        lexical: String::from(lexical),
328        rendered,
329    })
330}
331
332fn convert_member(
333    key: &str,
334    member: Value,
335    path: &mut Path,
336) -> Result<serde_json::Value, ValueConversionError> {
337    match member {
338        Value::Array(items) => {
339            let mut converted = Vec::with_capacity(items.len());
340            for (index, item) in items.into_iter().enumerate() {
341                converted.push(path.with_index(key, index, |path| item.into_serde_json(path))?);
342            }
343            Ok(serde_json::Value::Array(converted))
344        }
345        other => path.with(key, |path| other.into_serde_json(path)),
346    }
347}
348
349impl From<i32> for Value {
350    fn from(value: i32) -> Self {
351        Self::Number(Number::from(value))
352    }
353}
354
355impl From<u32> for Value {
356    fn from(value: u32) -> Self {
357        Self::Number(Number::from(value))
358    }
359}
360
361impl serde::Serialize for Value {
362    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
363        match self {
364            Self::Null => serializer.serialize_unit(),
365            Self::Bool(flag) => serializer.serialize_bool(*flag),
366            Self::Number(number) => serde::Serialize::serialize(number, serializer),
367            Self::String(text) => serializer.serialize_str(text),
368            Self::Array(items) => serde::Serialize::serialize(items, serializer),
369            Self::Object(object) => serde::Serialize::serialize(object, serializer),
370        }
371    }
372}
373
374impl<'de> serde::Deserialize<'de> for Value {
375    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
376        let raw = <Box<RawValue> as serde::Deserialize>::deserialize(deserializer)?;
377        read_raw(raw.get(), 0).map_err(serde::de::Error::custom)
378    }
379}
380
381/// How deeply a document may nest, the limit `serde_json` itself enforces
382/// (<https://docs.rs/serde_json/1/serde_json/de/struct.Deserializer.html>).
383const NESTING_LIMIT: usize = 128;
384
385// NOTE: `RawValue` hands back the text of a value serde_json already validated
386// (<https://docs.rs/serde_json/1/serde_json/value/struct.RawValue.html>), so the
387// first byte names the kind and a number arrives with its precision intact.
388fn read_raw(raw: &str, depth: usize) -> Result<Value, serde_json::Error> {
389    let text = raw.trim();
390    if depth > NESTING_LIMIT {
391        return Err(serde::de::Error::custom("recursion limit exceeded"));
392    }
393    match text.as_bytes().first() {
394        Some(b'{') => {
395            let members: BTreeMap<String, Box<RawValue>> = serde_json::from_str(text)?;
396            let mut object = Object::new();
397            for (key, member) in members {
398                object.insert(key, read_raw(member.get(), depth + 1)?);
399            }
400            Ok(Value::Object(object))
401        }
402        Some(b'[') => {
403            let members: Vec<Box<RawValue>> = serde_json::from_str(text)?;
404            let mut items = Vec::with_capacity(members.len());
405            for member in members {
406                items.push(read_raw(member.get(), depth + 1)?);
407            }
408            Ok(Value::Array(items))
409        }
410        Some(b'"') => Ok(Value::String(serde_json::from_str(text)?)),
411        Some(b't' | b'f') => Ok(Value::Bool(serde_json::from_str(text)?)),
412        Some(b'n') => Ok(Value::Null),
413        _ => Ok(Value::Number(Number(String::from(text)))),
414    }
415}
416
417/// Why a JSON document was refused.
418#[derive(Debug, Clone, PartialEq, Eq)]
419pub enum DecodeErrorKind {
420    /// A property the type does not define.
421    UnknownProperty,
422    /// A required property is absent.
423    MissingProperty,
424    /// The value has the wrong JSON type.
425    WrongType {
426        /// What the type expected.
427        expected: &'static str,
428    },
429    /// A property appears with a shape its cardinality forbids (an array
430    /// for a single element or the reverse).
431    WrongCardinality,
432    /// An object or array is empty.
433    Empty,
434    /// A number is out of range or not a whole number where one is required.
435    BadNumber,
436    /// The lexical form of a primitive is invalid.
437    BadValue,
438    /// Two forms of one choice element are both present.
439    DuplicateChoice,
440    /// `resourceType` is absent, not a string, or names another type.
441    ResourceType,
442    /// An XML element the type does not define.
443    UnknownElement,
444    /// Text where XML elements belong.
445    UnexpectedText,
446    /// An XML root element that is no resource of the version.
447    WrongRoot,
448    /// XML the parser refuses.
449    MalformedXml {
450        /// The parser's reason.
451        reason: String,
452    },
453}
454
455impl fmt::Display for DecodeErrorKind {
456    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
457        match self {
458            Self::UnknownProperty => f.write_str("unknown property"),
459            Self::MissingProperty => f.write_str("required property is missing"),
460            Self::WrongType { expected } => write!(f, "expected {expected}"),
461            Self::WrongCardinality => f.write_str("cardinality mismatch"),
462            Self::Empty => f.write_str("empty object or array"),
463            Self::BadNumber => f.write_str("number out of range"),
464            Self::BadValue => f.write_str("invalid value"),
465            Self::DuplicateChoice => f.write_str("more than one form of a choice element"),
466            Self::ResourceType => f.write_str("resourceType is missing or does not match"),
467            Self::UnknownElement => f.write_str("unknown element"),
468            Self::UnexpectedText => f.write_str("text where an element belongs"),
469            Self::WrongRoot => f.write_str("the root element is no resource of this version"),
470            Self::MalformedXml { reason } => write!(f, "malformed XML: {reason}"),
471        }
472    }
473}
474
475/// A refused JSON document, located by its element path.
476#[derive(Debug, Clone, PartialEq, Eq)]
477pub struct DecodeError {
478    /// The element path, for example `ValueSet.compose.include[2].system`.
479    pub path: String,
480    /// Why it was refused.
481    pub kind: DecodeErrorKind,
482}
483
484impl fmt::Display for DecodeError {
485    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
486        write!(f, "{}: {}", self.path, self.kind)
487    }
488}
489
490impl std::error::Error for DecodeError {}
491
492/// A text outside the lexical form of a FHIR primitive, the form the
493/// package's `regex` extension on `<primitive>.value` states
494/// (<https://hl7.org/fhir/R4/datatypes.html#primitive>).
495#[derive(Debug, Clone, Copy, PartialEq, Eq)]
496pub struct LexicalError {
497    /// The primitive's type code, for example `id`.
498    pub type_code: &'static str,
499}
500
501impl fmt::Display for LexicalError {
502    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
503        write!(
504            f,
505            "the text is outside the lexical form of {}",
506            self.type_code
507        )
508    }
509}
510
511impl std::error::Error for LexicalError {}
512
513/// The element path being decoded, for error reports.
514#[derive(Debug, Default, Clone)]
515pub struct Path {
516    segments: Vec<String>,
517    lenient: bool,
518}
519
520impl Path {
521    /// A path starting at `root`.
522    #[must_use]
523    pub fn root(root: &str) -> Self {
524        Self {
525            segments: vec![root.to_owned()],
526            lenient: false,
527        }
528    }
529
530    /// A path starting at `root` that reads a required primitive stating no
531    /// value as the value-less element it would be with only an extension,
532    /// and a required repeating element with fewer items than its minimum as
533    /// the items it carries.
534    ///
535    /// Cardinality is an aspect of validating a resource, which a server
536    /// performs at its discretion, and an implementation "should be
537    /// conservative in its sending behavior, and liberal in its receiving
538    /// behavior" (<https://hl7.org/fhir/R4B/validation.html>). A reader that
539    /// is handed a resource to use, rather than to store, takes this path so
540    /// one absent element does not cost the whole request.
541    #[must_use]
542    pub fn lenient(root: &str) -> Self {
543        Self {
544            segments: vec![root.to_owned()],
545            lenient: true,
546        }
547    }
548
549    /// Whether this read tolerates a required primitive that states no value.
550    #[must_use]
551    pub const fn is_lenient(&self) -> bool {
552        self.lenient
553    }
554
555    /// The dotted path, for example `Observation.valueQuantity.value`.
556    #[must_use]
557    pub fn location(&self) -> String {
558        self.segments.join(".")
559    }
560
561    /// Runs `f` under `name`.
562    ///
563    /// # Errors
564    ///
565    /// Returns whatever `f` returns.
566    pub fn with<T, E>(
567        &mut self,
568        name: &str,
569        f: impl FnOnce(&mut Self) -> Result<T, E>,
570    ) -> Result<T, E> {
571        self.segments.push(name.to_owned());
572        let out = f(self);
573        self.segments.pop();
574        out
575    }
576
577    /// Runs `f` under `name[index]`.
578    ///
579    /// # Errors
580    ///
581    /// Returns whatever `f` returns.
582    pub fn with_index<T, E>(
583        &mut self,
584        name: &str,
585        index: usize,
586        f: impl FnOnce(&mut Self) -> Result<T, E>,
587    ) -> Result<T, E> {
588        self.segments.push(format!("{name}[{index}]"));
589        let out = f(self);
590        self.segments.pop();
591        out
592    }
593
594    /// An error at the current path.
595    #[must_use]
596    pub fn error(&self, kind: DecodeErrorKind) -> DecodeError {
597        DecodeError {
598            path: self.location(),
599            kind,
600        }
601    }
602}
603
604/// A type with a FHIR JSON representation as an object.
605pub trait Json: Sized {
606    /// The JSON object.
607    ///
608    /// # Errors
609    ///
610    /// Returns [`EncodeError`] when a held value has no JSON form.
611    fn to_json(&self) -> Result<Object, EncodeError>;
612
613    /// Decodes `object`, refusing unknown properties.
614    ///
615    /// # Errors
616    ///
617    /// Returns [`DecodeError`] for any deviation from the type's definition.
618    fn from_json(object: &Object, path: &mut Path) -> Result<Self, DecodeError>;
619}
620
621/// Decodes a resource straight into a box.
622///
623/// The resource enum matches over every resource type its features select, and
624/// a decoded resource is a large value, so building each one inside the match
625/// would size that one stack frame for the whole set. This call keeps each
626/// value in its own frame.
627///
628/// # Errors
629///
630/// Returns [`DecodeError`] for any deviation from the type's definition.
631#[inline(never)]
632pub fn boxed<T: Json>(object: &Object, path: &mut Path) -> Result<Box<T>, DecodeError> {
633    Ok(Box::new(T::from_json(object, path)?))
634}
635
636/// A FHIR primitive: a JSON value plus an optional element object.
637pub trait Primitive: Sized {
638    /// The JSON value, `None` when only `id` or `extension` are present.
639    ///
640    /// # Errors
641    ///
642    /// Returns [`EncodeError`] when the held value has no JSON form.
643    fn value_json(&self) -> Result<Option<Value>, EncodeError>;
644
645    /// The `_name` object, `None` when the primitive has no `id` or `extension`.
646    ///
647    /// # Errors
648    ///
649    /// Returns [`EncodeError`] when an extension value has no JSON form.
650    fn element_json(&self) -> Result<Option<Value>, EncodeError>;
651
652    /// Decodes the value and its `_name` sibling.
653    ///
654    /// # Errors
655    ///
656    /// Returns [`DecodeError`] when both parts are absent or either is malformed.
657    fn from_json_parts(
658        value: Option<&Value>,
659        element: Option<&Value>,
660        path: &mut Path,
661    ) -> Result<Self, DecodeError>;
662
663    /// Whether the primitive carries a value.
664    fn has_value(&self) -> bool;
665
666    /// Whether the primitive carries an `id` or an `extension`.
667    fn has_element(&self) -> bool;
668
669    /// Writes the value, `null` when the primitive carries none.
670    ///
671    /// # Errors
672    ///
673    /// Returns the serializer's error, which for a decimal includes a lexical
674    /// form that is no JSON number.
675    fn serialize_value<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>;
676
677    /// Writes the `_name` object, `null` when the primitive carries no `id`
678    /// and no `extension`.
679    ///
680    /// # Errors
681    ///
682    /// Returns the serializer's error.
683    fn serialize_element<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>;
684}
685
686/// A primitive's value, written straight to a serializer.
687///
688/// This wrapper and the three below carry a primitive into `serde`, so a
689/// generated type writes it as a map entry without building a [`Value`] first.
690#[derive(Debug)]
691pub struct PrimitiveValue<'a, P: Primitive>(pub &'a P);
692
693impl<P: Primitive> serde::Serialize for PrimitiveValue<'_, P> {
694    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
695        self.0.serialize_value(serializer)
696    }
697}
698
699/// A primitive's `_name` object, written straight to a serializer.
700#[derive(Debug)]
701pub struct PrimitiveElement<'a, P: Primitive>(pub &'a P);
702
703impl<P: Primitive> serde::Serialize for PrimitiveElement<'_, P> {
704    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
705        self.0.serialize_element(serializer)
706    }
707}
708
709/// The value array of a repeating primitive, `null` at a position that carries
710/// only an `id` or an `extension`.
711#[derive(Debug)]
712pub struct PrimitiveValues<'a, P: Primitive>(pub &'a [P]);
713
714impl<P: Primitive> serde::Serialize for PrimitiveValues<'_, P> {
715    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
716        let mut seq = serde::Serializer::serialize_seq(serializer, Some(self.0.len()))?;
717        for item in self.0 {
718            serde::ser::SerializeSeq::serialize_element(&mut seq, &PrimitiveValue(item))?;
719        }
720        serde::ser::SerializeSeq::end(seq)
721    }
722}
723
724/// The `_name` array of a repeating primitive, `null` at a position that
725/// carries no `id` and no `extension`.
726#[derive(Debug)]
727pub struct PrimitiveElements<'a, P: Primitive>(pub &'a [P]);
728
729impl<P: Primitive> serde::Serialize for PrimitiveElements<'_, P> {
730    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
731        let mut seq = serde::Serializer::serialize_seq(serializer, Some(self.0.len()))?;
732        for item in self.0 {
733            serde::ser::SerializeSeq::serialize_element(&mut seq, &PrimitiveElement(item))?;
734        }
735        serde::ser::SerializeSeq::end(seq)
736    }
737}
738
739/// Writes `key` with the primitive's value, unless it carries none.
740///
741/// # Errors
742///
743/// Returns the serializer's error.
744pub fn value_entry<M: serde::ser::SerializeMap, P: Primitive>(
745    map: &mut M,
746    key: &str,
747    primitive: &P,
748) -> Result<(), M::Error> {
749    if primitive.has_value() {
750        map.serialize_entry(key, &PrimitiveValue(primitive))?;
751    }
752    Ok(())
753}
754
755/// Writes `key` with the primitive's `_name` object, unless it carries no
756/// `id` and no `extension`.
757///
758/// # Errors
759///
760/// Returns the serializer's error.
761pub fn element_entry<M: serde::ser::SerializeMap, P: Primitive>(
762    map: &mut M,
763    key: &str,
764    primitive: &P,
765) -> Result<(), M::Error> {
766    if primitive.has_element() {
767        map.serialize_entry(key, &PrimitiveElement(primitive))?;
768    }
769    Ok(())
770}
771
772/// Writes `key` with the value array of a repeating primitive, when any
773/// position carries a value.
774///
775/// A list whose every position carries only an `id` or an `extension` is
776/// written as the `_name` array alone
777/// (<https://hl7.org/fhir/R4/json.html#primitive>).
778///
779/// # Errors
780///
781/// Returns the serializer's error.
782pub fn value_list_entry<M: serde::ser::SerializeMap, P: Primitive>(
783    map: &mut M,
784    key: &str,
785    items: &[P],
786) -> Result<(), M::Error> {
787    if items.iter().any(Primitive::has_value) {
788        map.serialize_entry(key, &PrimitiveValues(items))?;
789    }
790    Ok(())
791}
792
793/// Writes `key` with the `_name` array of a repeating primitive, when any
794/// position carries an `id` or an `extension`.
795///
796/// # Errors
797///
798/// Returns the serializer's error.
799pub fn element_list_entry<M: serde::ser::SerializeMap, P: Primitive>(
800    map: &mut M,
801    key: &str,
802    items: &[P],
803) -> Result<(), M::Error> {
804    if items.iter().any(Primitive::has_element) {
805        map.serialize_entry(key, &PrimitiveElements(items))?;
806    }
807    Ok(())
808}
809
810/// Reads a non-empty JSON object.
811///
812/// # Errors
813///
814/// Returns [`DecodeError`] when `value` is not an object or is empty.
815pub fn expect_object<'a>(value: &'a Value, path: &Path) -> Result<&'a Object, DecodeError> {
816    match value {
817        Value::Object(object) if object.is_empty() => Err(path.error(DecodeErrorKind::Empty)),
818        Value::Object(object) => Ok(object),
819        _ => Err(path.error(DecodeErrorKind::WrongType {
820            expected: "an object",
821        })),
822    }
823}
824
825/// Reads a non-empty JSON array.
826///
827/// # Errors
828///
829/// Returns [`DecodeError`] when `value` is not an array or is empty.
830pub fn expect_array<'a>(value: &'a Value, path: &Path) -> Result<&'a [Value], DecodeError> {
831    match value {
832        Value::Array(items) if items.is_empty() => Err(path.error(DecodeErrorKind::Empty)),
833        Value::Array(items) => Ok(items),
834        _ => Err(path.error(DecodeErrorKind::WrongType {
835            expected: "an array",
836        })),
837    }
838}
839
840/// Refuses an array where a single value is expected.
841///
842/// # Errors
843///
844/// Returns [`DecodeError`] when `value` is an array.
845pub fn expect_single<'a>(value: &'a Value, path: &Path) -> Result<&'a Value, DecodeError> {
846    match value {
847        Value::Array(_) => Err(path.error(DecodeErrorKind::WrongCardinality)),
848        other => Ok(other),
849    }
850}
851
852/// Reads a JSON string.
853///
854/// # Errors
855///
856/// Returns [`DecodeError`] when `value` is not a string.
857pub fn expect_string(value: &Value, path: &Path) -> Result<String, DecodeError> {
858    match value {
859        Value::String(s) => Ok(s.clone()),
860        _ => Err(path.error(DecodeErrorKind::WrongType {
861            expected: "a string",
862        })),
863    }
864}
865
866/// Reads a JSON boolean.
867///
868/// # Errors
869///
870/// Returns [`DecodeError`] when `value` is not a boolean.
871pub fn expect_bool(value: &Value, path: &Path) -> Result<bool, DecodeError> {
872    match value {
873        Value::Bool(b) => Ok(*b),
874        _ => Err(path.error(DecodeErrorKind::WrongType {
875            expected: "a boolean",
876        })),
877    }
878}
879
880/// Reads a JSON number as an `i32`.
881///
882/// # Errors
883///
884/// Returns [`DecodeError`] when `value` is not a whole number in range.
885pub fn expect_i32(value: &Value, path: &Path) -> Result<i32, DecodeError> {
886    match value {
887        Value::Number(n) => n
888            .as_i64()
889            .and_then(|i| i32::try_from(i).ok())
890            .ok_or_else(|| path.error(DecodeErrorKind::BadNumber)),
891        _ => Err(path.error(DecodeErrorKind::WrongType {
892            expected: "a number",
893        })),
894    }
895}
896
897/// Reads a JSON number as a `u32`, at least `min`.
898///
899/// # Errors
900///
901/// Returns [`DecodeError`] when `value` is not a whole number in range.
902pub fn expect_u32(value: &Value, min: u32, path: &Path) -> Result<u32, DecodeError> {
903    match value {
904        Value::Number(n) => n
905            .as_u64()
906            .and_then(|u| u32::try_from(u).ok())
907            .filter(|u| *u >= min)
908            .ok_or_else(|| path.error(DecodeErrorKind::BadNumber)),
909        _ => Err(path.error(DecodeErrorKind::WrongType {
910            expected: "a number",
911        })),
912    }
913}
914
915/// Reads a 64-bit integer carried as a JSON string (the R5 `integer64` form).
916///
917/// # Errors
918///
919/// Returns [`DecodeError`] when `value` is not a string holding an integer.
920pub fn expect_i64_string(value: &Value, path: &Path) -> Result<i64, DecodeError> {
921    match value {
922        Value::String(s) => s
923            .parse()
924            .map_err(|_| path.error(DecodeErrorKind::BadNumber)),
925        _ => Err(path.error(DecodeErrorKind::WrongType {
926            expected: "a string holding an integer",
927        })),
928    }
929}
930
931/// Reads a JSON number keeping its lexical form, for the FHIR decimal.
932///
933/// # Errors
934///
935/// Returns [`DecodeError`] when `value` is not a number.
936pub fn expect_decimal(value: &Value, path: &Path) -> Result<String, DecodeError> {
937    match value {
938        Value::Number(n) => Ok(String::from(n.as_str())),
939        _ => Err(path.error(DecodeErrorKind::WrongType {
940            expected: "a number",
941        })),
942    }
943}
944
945/// A decimal's lexical form as a JSON number.
946///
947/// # Errors
948///
949/// Returns [`DecodeError`] when `text` is not a JSON number.
950pub fn decimal_value(text: &str, path: &Path) -> Result<Value, DecodeError> {
951    text.parse::<Number>()
952        .map(Value::Number)
953        .map_err(|_| path.error(DecodeErrorKind::BadValue))
954}
955
956/// One position of a repeating primitive: the value and its `_name` object.
957pub type ValuePair<'a> = (Option<&'a Value>, Option<&'a Value>);
958
959/// Pairs a repeating primitive's value array with its `_name` array.
960///
961/// # Errors
962///
963/// Returns [`DecodeError`] when either is not an array, is empty, or the
964/// arrays differ in length.
965pub fn pair_arrays<'a>(
966    values: Option<&'a Value>,
967    elements: Option<&'a Value>,
968    path: &Path,
969) -> Result<Vec<ValuePair<'a>>, DecodeError> {
970    let values = values.map(|v| expect_array(v, path)).transpose()?;
971    let elements = elements.map(|v| expect_array(v, path)).transpose()?;
972    let len = match (values, elements) {
973        (Some(v), Some(e)) if v.len() != e.len() => {
974            return Err(path.error(DecodeErrorKind::WrongCardinality));
975        }
976        (Some(v), _) => v.len(),
977        (None, Some(e)) => e.len(),
978        (None, None) => 0,
979    };
980    Ok((0..len)
981        .map(|i| {
982            let value = values.and_then(|v| v.get(i)).filter(|v| !v.is_null());
983            let element = elements.and_then(|e| e.get(i)).filter(|e| !e.is_null());
984            (value, element)
985        })
986        .collect())
987}
988
989/// Serializes a list of primitives as the value array, when any carries a
990/// value, and the aligned `_name` array, when any carries an element object.
991///
992/// A list whose every position carries only an `id` or an `extension` has no
993/// value array (<https://hl7.org/fhir/R4/json.html#primitive>).
994///
995/// # Errors
996///
997/// Returns [`EncodeError`] when a held value has no JSON form.
998pub fn primitive_arrays<P: Primitive>(
999    items: &[P],
1000) -> Result<(Option<Value>, Option<Value>), EncodeError> {
1001    let mut values = Vec::with_capacity(items.len());
1002    let mut elements = Vec::with_capacity(items.len());
1003    for item in items {
1004        values.push(item.value_json()?.unwrap_or(Value::Null));
1005        elements.push(item.element_json()?.unwrap_or(Value::Null));
1006    }
1007    let any_value = values.iter().any(|v| !v.is_null());
1008    let any_element = elements.iter().any(|e| !e.is_null());
1009    Ok((
1010        any_value.then_some(Value::Array(values)),
1011        any_element.then_some(Value::Array(elements)),
1012    ))
1013}
1014
1015/// Why a value could not be written as JSON.
1016#[derive(Debug, Clone, PartialEq, Eq)]
1017pub enum EncodeError {
1018    /// A decimal's lexical form is not a JSON number.
1019    BadDecimal {
1020        /// The text that was held.
1021        text: String,
1022    },
1023    /// An unknown resource's body is not a JSON object.
1024    UnknownResourceBody,
1025    /// A value has no XML form, or the XML writer failed.
1026    Xml {
1027        /// What went wrong.
1028        reason: String,
1029    },
1030}
1031
1032impl fmt::Display for EncodeError {
1033    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1034        match self {
1035            Self::BadDecimal { text } => write!(f, "decimal {text:?} is not a JSON number"),
1036            Self::UnknownResourceBody => f.write_str("an unknown resource's body is not an object"),
1037            Self::Xml { reason } => write!(f, "no XML form: {reason}"),
1038        }
1039    }
1040}
1041
1042impl std::error::Error for EncodeError {}
1043
1044/// The parts of one choice element met while reading an object.
1045#[derive(Debug, Default)]
1046pub struct ChoiceSlot<'a> {
1047    /// The type suffix of the key seen, for example `String` for `valueString`.
1048    pub suffix: Option<&'static str>,
1049    /// The value part.
1050    pub value: Option<&'a Value>,
1051    /// The `_name` part.
1052    pub element: Option<&'a Value>,
1053}
1054
1055impl<'a> ChoiceSlot<'a> {
1056    fn claim(&mut self, suffix: &'static str, path: &Path) -> Result<(), DecodeError> {
1057        match self.suffix {
1058            Some(seen) if seen != suffix => Err(path.error(DecodeErrorKind::DuplicateChoice)),
1059            _ => {
1060                self.suffix = Some(suffix);
1061                Ok(())
1062            }
1063        }
1064    }
1065
1066    /// Records the value part of the form `suffix`.
1067    ///
1068    /// # Errors
1069    ///
1070    /// Returns [`DecodeError`] when another form was already seen.
1071    pub fn value(
1072        &mut self,
1073        suffix: &'static str,
1074        value: &'a Value,
1075        path: &Path,
1076    ) -> Result<(), DecodeError> {
1077        self.claim(suffix, path)?;
1078        self.value = Some(value);
1079        Ok(())
1080    }
1081
1082    /// Records the `_name` part of the form `suffix`.
1083    ///
1084    /// # Errors
1085    ///
1086    /// Returns [`DecodeError`] when another form was already seen.
1087    pub fn element(
1088        &mut self,
1089        suffix: &'static str,
1090        element: &'a Value,
1091        path: &Path,
1092    ) -> Result<(), DecodeError> {
1093        self.claim(suffix, path)?;
1094        self.element = Some(element);
1095        Ok(())
1096    }
1097}
1098
1099/// The `resourceType` of an object, for dispatch.
1100///
1101/// # Errors
1102///
1103/// Returns [`DecodeError`] when the property is absent or not a string.
1104pub fn resource_type<'a>(object: &'a Object, path: &Path) -> Result<&'a str, DecodeError> {
1105    match object.get("resourceType") {
1106        Some(Value::String(name)) => Ok(name),
1107        _ => Err(path.error(DecodeErrorKind::ResourceType)),
1108    }
1109}