haste_repository/
utilities.rs1use haste_fhir_model::r4::generated::{
2 resources::Resource,
3 terminology::IssueType,
4 types::{FHIRId, Meta},
5};
6use haste_fhir_operation_error::{OperationOutcomeError, derive::OperationOutcomeError};
7use haste_reflect::MetaValue;
8
9static ID_CHARACTERS: &[char] = &[
10 '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
11 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '-',
12];
13
14pub fn generate_id(len: Option<usize>) -> String {
17 let len = len.unwrap_or(26);
18 nanoid::nanoid!(len, ID_CHARACTERS).to_string()
19}
20
21pub fn validate_id(id: &str) -> Result<(), OperationOutcomeError> {
22 let characters_allowed = ID_CHARACTERS.iter().collect::<String>();
23 let re = regex::Regex::new(&format!("^[{}]*$", characters_allowed)).unwrap();
24 if !re.is_match(id) {
25 Err(OperationOutcomeError::fatal(
26 IssueType::Invalid(None),
27 format!("ID contains invalid characters: {}", id),
28 ))
29 } else {
30 Ok(())
31 }
32}
33
34#[derive(OperationOutcomeError)]
35pub enum DataTransformError {
36 #[error(code = "invalid", diagnostic = "Invalid data: '{arg0}'")]
37 InvalidData(String),
38 #[error(code = "not-found", diagnostic = "Data not found")]
39 NotFound(String),
40}
41
42pub fn set_resource_id(
43 resource: &mut Resource,
44 id_: Option<String>,
45) -> Result<(), OperationOutcomeError> {
46 let id: &mut dyn std::any::Any =
47 resource
48 .get_field_mut("id")
49 .ok_or(DataTransformError::InvalidData(
50 "Missing 'id' field".to_string(),
51 ))?;
52 let id: &mut Option<String> =
53 id.downcast_mut::<Option<String>>()
54 .ok_or(DataTransformError::InvalidData(
55 "Invalid 'id' field".to_string(),
56 ))?;
57 *id = Some(id_.unwrap_or_else(|| generate_id(None)));
58 Ok(())
59}
60
61pub fn set_version_id(resource: &mut Resource) -> Result<(), OperationOutcomeError> {
62 let meta: &mut dyn std::any::Any =
63 resource
64 .get_field_mut("meta")
65 .ok_or(DataTransformError::InvalidData(
66 "Missing 'meta' field".to_string(),
67 ))?;
68 let meta: &mut Option<Box<Meta>> =
69 meta.downcast_mut::<Option<Box<Meta>>>()
70 .ok_or(DataTransformError::InvalidData(
71 "Invalid 'meta' field".to_string(),
72 ))?;
73
74 if meta.is_none() {
75 *meta = Some(Box::new(Meta::default()))
76 }
77 meta.as_mut().map(|meta| {
78 meta.versionId = Some(Box::new(FHIRId {
79 id: None,
80 extension: None,
81 value: Some(generate_id(None)),
82 }));
83 });
84
85 Ok(())
86}