1use derivative::Derivative;
2use haste_fhir_model::r4::generated::terminology::{BoundCode, UserRole as FHIRUserRole};
3use serde::{Deserialize, Serialize};
4use std::fmt::Display;
5
6#[cfg(feature = "reflect")]
7pub mod reflect;
8
9#[cfg(feature = "sqlx")]
10pub mod sqlx;
11
12pub mod claims;
13pub mod scopes;
14
15#[cfg(test)]
16mod proptests;
17
18static SYSTEM: &str = "system";
20
21#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Deserialize, Serialize)]
26#[cfg_attr(feature = "sqlx", derive(::sqlx::Type))]
27#[cfg_attr(
28 feature = "sqlx",
29 sqlx(type_name = "fhir_version", rename_all = "lowercase")
30)]
31#[serde(rename_all = "lowercase")]
32pub enum SupportedFHIRVersions {
33 #[default]
34 R4,
35}
36
37impl SupportedFHIRVersions {
38 pub const ALL: &[SupportedFHIRVersions] = &[SupportedFHIRVersions::R4];
41
42 #[must_use]
44 pub fn as_str(&self) -> &'static str {
45 match self {
46 SupportedFHIRVersions::R4 => "r4",
47 }
48 }
49
50 #[must_use]
53 pub fn from_url_segment(segment: &str) -> Option<SupportedFHIRVersions> {
54 SupportedFHIRVersions::ALL
55 .iter()
56 .find(|version| version.as_str() == segment)
57 .cloned()
58 }
59}
60
61impl Display for SupportedFHIRVersions {
62 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63 write!(f, "{}", self.as_str())
64 }
65}
66
67#[derive(Clone, Debug, PartialEq, PartialOrd, Deserialize, Serialize)]
68#[serde(rename_all = "lowercase")]
69pub enum UserRole {
70 Owner,
71 Admin,
72 Member,
73}
74
75impl From<BoundCode<FHIRUserRole>> for UserRole {
76 fn from(role: BoundCode<FHIRUserRole>) -> Self {
77 if role == FHIRUserRole::owner() {
78 UserRole::Owner
79 } else if role == FHIRUserRole::admin() {
80 UserRole::Admin
81 } else {
82 UserRole::Member
83 }
84 }
85}
86
87#[derive(Derivative, Clone)]
88#[derivative(Debug = "transparent")]
89pub enum AuthorId {
90 System,
92 User(ResourceId),
93}
94
95impl AuthorId {
96 #[must_use]
97 pub fn new(id: String) -> Self {
98 if id == SYSTEM {
100 AuthorId::System
101 } else {
102 AuthorId::User(ResourceId::new(id))
103 }
104 }
105}
106
107impl AsRef<str> for AuthorId {
108 fn as_ref(&self) -> &str {
109 match self {
110 AuthorId::System => SYSTEM,
111 AuthorId::User(id) => id.as_ref(),
112 }
113 }
114}
115
116impl<'de> Deserialize<'de> for AuthorId {
117 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
118 where
119 D: serde::Deserializer<'de>,
120 {
121 Ok(AuthorId::new(String::deserialize(deserializer)?))
122 }
123}
124
125impl Serialize for AuthorId {
126 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
127 where
128 S: serde::Serializer,
129 {
130 serializer.serialize_str(self.as_ref())
131 }
132}
133
134impl Display for AuthorId {
135 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
136 match self {
137 AuthorId::System => write!(f, "{SYSTEM}"),
138 AuthorId::User(id) => write!(f, "{}", id.as_ref()),
139 }
140 }
141}
142
143#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
144pub enum AuthorKind {
145 System,
146 Membership,
147 ClientApplication,
148 OperationDefinition,
149}
150
151impl AsRef<str> for AuthorKind {
152 fn as_ref(&self) -> &str {
153 match self {
154 AuthorKind::System => "System",
155 AuthorKind::Membership => "Membership",
156 AuthorKind::ClientApplication => "ClientApplication",
157 AuthorKind::OperationDefinition => "OperationDefinition",
158 }
159 }
160}
161
162impl Display for AuthorKind {
163 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
164 write!(f, "{}", self.as_ref())
165 }
166}
167
168#[derive(Derivative, Clone, PartialEq, Eq, Hash)]
169#[derivative(Debug = "transparent")]
170pub enum TenantId {
171 System,
172 #[derivative(Debug = "transparent")]
173 Custom(String),
174}
175
176impl TenantId {
177 #[must_use]
178 pub fn new(id: String) -> Self {
179 if id == SYSTEM {
181 TenantId::System
182 } else {
183 TenantId::Custom(id)
184 }
185 }
186}
187
188impl From<String> for TenantId {
189 fn from(id: String) -> Self {
190 TenantId::new(id)
191 }
192}
193
194impl AsRef<str> for TenantId {
195 fn as_ref(&self) -> &str {
196 match self {
197 TenantId::System => SYSTEM,
198 TenantId::Custom(id) => id,
199 }
200 }
201}
202
203impl<'de> Deserialize<'de> for TenantId {
204 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
205 where
206 D: serde::Deserializer<'de>,
207 {
208 Ok(TenantId::new(String::deserialize(deserializer)?))
209 }
210}
211
212impl Serialize for TenantId {
213 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
214 where
215 S: serde::Serializer,
216 {
217 serializer.serialize_str(self.as_ref())
218 }
219}
220
221impl Display for TenantId {
222 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
223 match self {
224 TenantId::System => write!(f, "{SYSTEM}"),
225 TenantId::Custom(id) => write!(f, "{id}"),
226 }
227 }
228}
229
230#[derive(Derivative, Clone, PartialEq, Eq, Hash)]
231#[derivative(Debug = "transparent")]
232pub enum ProjectId {
233 System,
234 #[derivative(Debug = "transparent")]
235 Custom(String),
236}
237impl ProjectId {
238 #[must_use]
239 pub fn new(id: String) -> Self {
240 if id == SYSTEM {
242 ProjectId::System
243 } else {
244 ProjectId::Custom(id)
245 }
246 }
247}
248
249impl AsRef<str> for ProjectId {
250 fn as_ref(&self) -> &str {
251 match self {
252 ProjectId::System => SYSTEM,
253 ProjectId::Custom(id) => id,
254 }
255 }
256}
257
258impl<'de> Deserialize<'de> for ProjectId {
259 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
260 where
261 D: serde::Deserializer<'de>,
262 {
263 Ok(ProjectId::new(String::deserialize(deserializer)?))
264 }
265}
266
267impl Serialize for ProjectId {
268 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
269 where
270 S: serde::Serializer,
271 {
272 serializer.serialize_str(self.as_ref())
273 }
274}
275
276impl Display for ProjectId {
277 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
278 match self {
279 ProjectId::System => write!(f, "{SYSTEM}"),
280 ProjectId::Custom(id) => write!(f, "{id}"),
281 }
282 }
283}
284
285pub struct VersionIdRef<'a>(&'a str);
286impl<'a> VersionIdRef<'a> {
287 #[must_use]
288 pub fn new(id: &'a str) -> Self {
289 VersionIdRef(id)
290 }
291}
292impl<'a> AsRef<str> for VersionIdRef<'a> {
293 fn as_ref(&self) -> &'a str {
294 self.0
295 }
296}
297impl<'a> From<&'a VersionId> for VersionIdRef<'a> {
298 fn from(version_id: &'a VersionId) -> Self {
299 VersionIdRef::new(&version_id.0)
300 }
301}
302
303#[derive(Derivative, Deserialize, Serialize, Clone, PartialEq, Eq, Hash)]
304#[derivative(Debug = "transparent")]
305pub struct VersionId(String);
306impl VersionId {
307 #[must_use]
308 pub fn new(id: String) -> Self {
309 VersionId(id)
310 }
311}
312impl From<String> for VersionId {
313 fn from(id: String) -> Self {
314 VersionId(id)
315 }
316}
317impl AsRef<str> for VersionId {
318 fn as_ref(&self) -> &str {
319 &self.0
320 }
321}
322
323#[derive(Derivative, Clone, Deserialize, Serialize)]
324#[derivative(Debug = "transparent")]
325pub struct ResourceId(String);
326impl ResourceId {
327 #[must_use]
328 pub fn new(id: String) -> Self {
329 ResourceId(id)
330 }
331}
332impl AsRef<str> for ResourceId {
333 fn as_ref(&self) -> &str {
334 &self.0
335 }
336}