Skip to main content

fhir_types/
operation.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//! Runtime descriptors of the terminology operations.
6//!
7//! The exact parameter set each FHIR version declares
8//! (<https://hl7.org/fhir/R4B/operationdefinition.html>) plus the terminology
9//! ecosystem overlay (<https://hl7.org/fhir/uv/tx-ecosystem/requirements.html>),
10//! each parameter marked with its source, so a server accepts nothing more
11//! and nothing less.
12//!
13//! NOTE: a parameter is read from the primitive its definition declares and
14//! from the primitives that share that one's scalar in either direction, so a
15//! `canonical` parameter reads a `valueUri` too. No clause requires refusing
16//! the wider spelling, and the GET form carries no type marker at all
17//! (<https://hl7.org/fhir/R4B/operations.html>); the decision is recorded on
18//! #352.
19
20/// The direction of an operation parameter.
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub enum ParameterUse {
23    /// An input parameter.
24    In,
25    /// An output parameter.
26    Out,
27}
28
29/// Where a declared parameter comes from.
30#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31pub enum ParameterSource {
32    /// The version's own `OperationDefinition`.
33    Version,
34    /// Pre-adopted from the FHIR R6 ballot for the terminology ecosystem.
35    PreAdopted,
36    /// Defined by the terminology ecosystem alone.
37    Ecosystem,
38}
39
40/// How many values a parameter takes.
41#[derive(Debug, Clone, Copy, PartialEq, Eq)]
42pub struct Cardinality {
43    /// The minimum number of values.
44    pub min: u32,
45    /// The maximum number of values; `None` is unbounded (`*`).
46    pub max: Option<u32>,
47}
48
49impl Cardinality {
50    /// Whether `count` values satisfy this cardinality.
51    #[must_use]
52    pub const fn admits(self, count: u32) -> bool {
53        count >= self.min
54            && match self.max {
55                Some(max) => count <= max,
56                None => true,
57            }
58    }
59}
60
61/// One declared parameter, with its parts.
62#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63pub struct Parameter {
64    /// The parameter name as it appears in `Parameters.parameter.name`.
65    pub name: &'static str,
66    /// The direction.
67    pub usage: ParameterUse,
68    /// The cardinality.
69    pub cardinality: Cardinality,
70    /// The FHIR type code, `None` for a multi-part parameter.
71    pub type_code: Option<&'static str>,
72    /// The invocation levels the parameter applies to; empty means every level.
73    pub scope: &'static [&'static str],
74    /// The nested parts.
75    pub parts: &'static [Parameter],
76    /// Where the parameter comes from.
77    pub source: ParameterSource,
78}
79
80impl Parameter {
81    /// The part named `name`, if any.
82    #[must_use]
83    pub fn part(&self, name: &str) -> Option<&'static Parameter> {
84        self.parts.iter().find(|part| part.name == name)
85    }
86}
87
88/// One operation as its version declares it.
89#[derive(Debug, Clone, Copy, PartialEq, Eq)]
90pub struct Operation {
91    /// The canonical URL of the `OperationDefinition`.
92    pub url: &'static str,
93    /// The resource type the operation applies to.
94    pub resource: &'static str,
95    /// The code used to invoke the operation, without the `$`.
96    pub code: &'static str,
97    /// Whether the operation is invoked at the system level.
98    pub system: bool,
99    /// Whether the operation is invoked at the resource type level.
100    pub type_level: bool,
101    /// Whether the operation is invoked on a resource instance.
102    pub instance: bool,
103    /// Every declared parameter, `in` and `out`, in declaration order.
104    pub parameters: &'static [Parameter],
105}
106
107impl Operation {
108    /// The parameter named `name` with the given direction, if declared.
109    #[must_use]
110    pub fn parameter(&self, usage: ParameterUse, name: &str) -> Option<&'static Parameter> {
111        self.parameters
112            .iter()
113            .find(|parameter| parameter.usage == usage && parameter.name == name)
114    }
115
116    /// The parameters of one direction, in declaration order.
117    pub fn parameters_of(&self, usage: ParameterUse) -> impl Iterator<Item = &'static Parameter> {
118        self.parameters
119            .iter()
120            .filter(move |parameter| parameter.usage == usage)
121    }
122}
123
124/// Why a `Parameters` resource does not fit an operation's declared
125/// parameter set. Every variant names the operation and the parameter.
126#[derive(Debug, Clone, PartialEq, Eq)]
127pub enum ParametersError {
128    /// A parameter has no name.
129    Unnamed {
130        /// The operation, as `Resource/$code`.
131        operation: &'static str,
132    },
133    /// A parameter the operation does not declare.
134    Undeclared {
135        /// The operation, as `Resource/$code`.
136        operation: &'static str,
137        /// The parameter name (dotted for a part).
138        name: std::string::String,
139    },
140    /// A parameter with a maximum of one given more than once.
141    Repeated {
142        /// The operation, as `Resource/$code`.
143        operation: &'static str,
144        /// The parameter name (dotted for a part).
145        name: &'static str,
146    },
147    /// A required parameter is absent.
148    Missing {
149        /// The operation, as `Resource/$code`.
150        operation: &'static str,
151        /// The parameter name (dotted for a part).
152        name: &'static str,
153    },
154    /// A parameter carries neither a value nor a resource.
155    MissingValue {
156        /// The operation, as `Resource/$code`.
157        operation: &'static str,
158        /// The parameter name (dotted for a part).
159        name: &'static str,
160    },
161    /// A parameter's value is not of the declared type.
162    WrongType {
163        /// The operation, as `Resource/$code`.
164        operation: &'static str,
165        /// The parameter name (dotted for a part).
166        name: &'static str,
167        /// The declared type.
168        expected: &'static str,
169    },
170}
171
172impl std::fmt::Display for ParametersError {
173    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
174        match self {
175            Self::Unnamed { operation } => {
176                write!(f, "{operation}: a parameter has no name")
177            }
178            Self::Undeclared { operation, name } => {
179                write!(f, "{operation}: parameter `{name}` is not declared")
180            }
181            Self::Repeated { operation, name } => {
182                write!(f, "{operation}: parameter `{name}` is given more than once")
183            }
184            Self::Missing { operation, name } => {
185                write!(f, "{operation}: parameter `{name}` is required")
186            }
187            Self::MissingValue { operation, name } => {
188                write!(f, "{operation}: parameter `{name}` has no value")
189            }
190            Self::WrongType {
191                operation,
192                name,
193                expected,
194            } => write!(f, "{operation}: parameter `{name}` is not a {expected}"),
195        }
196    }
197}
198
199impl std::error::Error for ParametersError {}