Skip to main content

ferrobridge_fhirpath/value/
mod.rs

1// SPDX-FileCopyrightText: Cadasto B.V.
2// SPDX-License-Identifier: BUSL-1.1
3
4//! The items a collection holds: the FHIRPath system values (N1 §4.1), the
5//! FHIR elements of the document under evaluation, and the type descriptions
6//! `type()` returns (N1 §10.2).
7
8pub mod node;
9
10use std::fmt;
11
12use rust_decimal::Decimal;
13
14use crate::quantity::Quantity;
15use crate::temporal::{Date, DateTime, Time};
16use node::Node;
17
18/// An ordered collection, the result of every expression (N1 §3.1).
19pub type Collection<'a> = Vec<Item<'a>>;
20
21/// One item of a collection.
22#[derive(Debug, Clone, PartialEq)]
23pub enum Item<'a> {
24    /// `System.Boolean`.
25    Boolean(bool),
26    /// `System.String`.
27    String(String),
28    /// `System.Integer`, held in the 32-bit range of N1 §4.1.3.
29    Integer(i64),
30    /// `System.Decimal`.
31    Decimal(Decimal),
32    /// `System.Date`.
33    Date(Date),
34    /// `System.DateTime`.
35    DateTime(DateTime),
36    /// `System.Time`.
37    Time(Time),
38    /// `System.Quantity`.
39    Quantity(Quantity),
40    /// An element or resource of the document.
41    Node(Node<'a>),
42    /// A type description from `type()` (N1 §10.2).
43    Type(TypeInfo),
44}
45
46/// A type description (N1 §10.2): `SimpleTypeInfo` or `ClassInfo` with a
47/// name, `TupleTypeInfo` for a backbone element, which has none.
48#[derive(Debug, Clone, PartialEq, Eq)]
49pub struct TypeInfo {
50    /// `System` or `FHIR`.
51    pub namespace: &'static str,
52    /// The type name; `None` for an anonymous type.
53    pub name: Option<String>,
54}
55
56/// The system types of N1 §4.1, the `System` namespace.
57pub const SYSTEM_TYPES: [&str; 9] = [
58    "Any", "Boolean", "String", "Integer", "Decimal", "Date", "DateTime", "Time", "Quantity",
59];
60
61impl Item<'_> {
62    /// The name of the system type a system value has, `None` for a node or a
63    /// type description.
64    #[must_use]
65    pub const fn system_type(&self) -> Option<&'static str> {
66        match self {
67            Self::Boolean(_) => Some("Boolean"),
68            Self::String(_) => Some("String"),
69            Self::Integer(_) => Some("Integer"),
70            Self::Decimal(_) => Some("Decimal"),
71            Self::Date(_) => Some("Date"),
72            Self::DateTime(_) => Some("DateTime"),
73            Self::Time(_) => Some("Time"),
74            Self::Quantity(_) => Some("Quantity"),
75            Self::Node(_) | Self::Type(_) => None,
76        }
77    }
78
79    /// The node this item is, when it is one.
80    #[must_use]
81    pub const fn as_node(&self) -> Option<&Node<'_>> {
82        match self {
83            Self::Node(node) => Some(node),
84            _ => None,
85        }
86    }
87}
88
89impl fmt::Display for Item<'_> {
90    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91        match self {
92            Self::Boolean(value) => write!(f, "{value}"),
93            Self::String(value) => f.write_str(value),
94            Self::Integer(value) => write!(f, "{value}"),
95            Self::Decimal(value) => write!(f, "{value}"),
96            Self::Date(value) => write!(f, "{value}"),
97            Self::DateTime(value) => write!(f, "{value}"),
98            Self::Time(value) => write!(f, "{value}"),
99            Self::Quantity(value) => write!(f, "{value}"),
100            Self::Node(node) => write!(f, "{node}"),
101            Self::Type(info) => match &info.name {
102                Some(name) => write!(f, "{}.{name}", info.namespace),
103                None => write!(f, "{}.(anonymous)", info.namespace),
104            },
105        }
106    }
107}