fhir-types 0.1.92

Generated per-version FHIR types and terminology operation contracts
Documentation
// @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. DO NOT EDIT.
// Change the emitter (tools/fhir-codegen) and regenerate.
//! Runtime descriptors of the terminology operations.
//!
//! The exact parameter set each FHIR version declares
//! (<https://hl7.org/fhir/R4B/operationdefinition.html>) plus the terminology
//! ecosystem overlay (<https://hl7.org/fhir/uv/tx-ecosystem/requirements.html>),
//! each parameter marked with its source, so a server accepts nothing more
//! and nothing less.
//!
//! NOTE: a parameter is read from the primitive its definition declares and
//! from the primitives that share that one's scalar in either direction, so a
//! `canonical` parameter reads a `valueUri` too. No clause requires refusing
//! the wider spelling, and the GET form carries no type marker at all
//! (<https://hl7.org/fhir/R4B/operations.html>); the decision is recorded on
//! #352.

/// The direction of an operation parameter.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ParameterUse {
    /// An input parameter.
    In,
    /// An output parameter.
    Out,
}

/// Where a declared parameter comes from.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ParameterSource {
    /// The version's own `OperationDefinition`.
    Version,
    /// Pre-adopted from the FHIR R6 ballot for the terminology ecosystem.
    PreAdopted,
    /// Defined by the terminology ecosystem alone.
    Ecosystem,
}

/// How many values a parameter takes.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Cardinality {
    /// The minimum number of values.
    pub min: u32,
    /// The maximum number of values; `None` is unbounded (`*`).
    pub max: Option<u32>,
}

impl Cardinality {
    /// Whether `count` values satisfy this cardinality.
    #[must_use]
    pub const fn admits(self, count: u32) -> bool {
        count >= self.min
            && match self.max {
                Some(max) => count <= max,
                None => true,
            }
    }
}

/// One declared parameter, with its parts.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Parameter {
    /// The parameter name as it appears in `Parameters.parameter.name`.
    pub name: &'static str,
    /// The direction.
    pub usage: ParameterUse,
    /// The cardinality.
    pub cardinality: Cardinality,
    /// The FHIR type code, `None` for a multi-part parameter.
    pub type_code: Option<&'static str>,
    /// The invocation levels the parameter applies to; empty means every level.
    pub scope: &'static [&'static str],
    /// The nested parts.
    pub parts: &'static [Parameter],
    /// Where the parameter comes from.
    pub source: ParameterSource,
}

impl Parameter {
    /// The part named `name`, if any.
    #[must_use]
    pub fn part(&self, name: &str) -> Option<&'static Parameter> {
        self.parts.iter().find(|part| part.name == name)
    }
}

/// One operation as its version declares it.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Operation {
    /// The canonical URL of the `OperationDefinition`.
    pub url: &'static str,
    /// The resource type the operation applies to.
    pub resource: &'static str,
    /// The code used to invoke the operation, without the `$`.
    pub code: &'static str,
    /// Whether the operation is invoked at the system level.
    pub system: bool,
    /// Whether the operation is invoked at the resource type level.
    pub type_level: bool,
    /// Whether the operation is invoked on a resource instance.
    pub instance: bool,
    /// Every declared parameter, `in` and `out`, in declaration order.
    pub parameters: &'static [Parameter],
}

impl Operation {
    /// The parameter named `name` with the given direction, if declared.
    #[must_use]
    pub fn parameter(&self, usage: ParameterUse, name: &str) -> Option<&'static Parameter> {
        self.parameters
            .iter()
            .find(|parameter| parameter.usage == usage && parameter.name == name)
    }

    /// The parameters of one direction, in declaration order.
    pub fn parameters_of(&self, usage: ParameterUse) -> impl Iterator<Item = &'static Parameter> {
        self.parameters
            .iter()
            .filter(move |parameter| parameter.usage == usage)
    }
}

/// Why a `Parameters` resource does not fit an operation's declared
/// parameter set. Every variant names the operation and the parameter.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ParametersError {
    /// A parameter has no name.
    Unnamed {
        /// The operation, as `Resource/$code`.
        operation: &'static str,
    },
    /// A parameter the operation does not declare.
    Undeclared {
        /// The operation, as `Resource/$code`.
        operation: &'static str,
        /// The parameter name (dotted for a part).
        name: std::string::String,
    },
    /// A parameter with a maximum of one given more than once.
    Repeated {
        /// The operation, as `Resource/$code`.
        operation: &'static str,
        /// The parameter name (dotted for a part).
        name: &'static str,
    },
    /// A required parameter is absent.
    Missing {
        /// The operation, as `Resource/$code`.
        operation: &'static str,
        /// The parameter name (dotted for a part).
        name: &'static str,
    },
    /// A parameter carries neither a value nor a resource.
    MissingValue {
        /// The operation, as `Resource/$code`.
        operation: &'static str,
        /// The parameter name (dotted for a part).
        name: &'static str,
    },
    /// A parameter's value is not of the declared type.
    WrongType {
        /// The operation, as `Resource/$code`.
        operation: &'static str,
        /// The parameter name (dotted for a part).
        name: &'static str,
        /// The declared type.
        expected: &'static str,
    },
}

impl std::fmt::Display for ParametersError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Unnamed { operation } => {
                write!(f, "{operation}: a parameter has no name")
            }
            Self::Undeclared { operation, name } => {
                write!(f, "{operation}: parameter `{name}` is not declared")
            }
            Self::Repeated { operation, name } => {
                write!(f, "{operation}: parameter `{name}` is given more than once")
            }
            Self::Missing { operation, name } => {
                write!(f, "{operation}: parameter `{name}` is required")
            }
            Self::MissingValue { operation, name } => {
                write!(f, "{operation}: parameter `{name}` has no value")
            }
            Self::WrongType {
                operation,
                name,
                expected,
            } => write!(f, "{operation}: parameter `{name}` is not a {expected}"),
        }
    }
}

impl std::error::Error for ParametersError {}