1use std::fmt::{Debug, Formatter};
2use std::collections::BTreeMap;
3use bson::DateTime;
4use serde::{Deserialize, Deserializer, Serialize};
5use serde_json::Value;
6#[cfg(feature = "openapi")]
7use utoipa::ToSchema;
8
9#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
10#[serde(rename_all = "camelCase")]
11#[cfg_attr(feature = "openapi", derive(ToSchema))]
12pub struct RecordReference {
13 #[serde(deserialize_with = "object_id_as_string", rename = "_id")]
14 pub id: String,
15 pub name: String,
16 #[serde(default)]
17 pub meta: BTreeMap<String, String>,
18}
19
20impl RecordReference {
21 pub fn new(id: String, name: String) -> Self {
23 Self {
24 id,
25 name,
26 meta: BTreeMap::new(),
27 }
28 }
29
30 pub fn with_meta(id: String, name: String, meta: BTreeMap<String, String>) -> Self {
32 Self { id, name, meta }
33 }
34
35 pub fn with_meta_from_hashmap(id: String, name: String, meta: std::collections::HashMap<String, String>) -> Self {
37 Self {
38 id,
39 name,
40 meta: meta.into_iter().collect()
41 }
42 }
43
44 pub fn id(&self) -> &str {
46 &self.id
47 }
48
49 pub fn name(&self) -> &str {
50 &self.name
51 }
52}
53
54pub fn from_str<'de, D>(deserializer: D) -> Result<u16, D::Error>
55where
56 D: Deserializer<'de>,
57{
58 let value = Value::deserialize(deserializer)?;
59 if value.is_string() {
60 Ok(value.as_str().unwrap().parse().unwrap())
61 } else if value.is_u64() {
62 Ok(value.as_u64().unwrap() as u16)
63 } else if value.is_i64() {
64 Ok(value.as_i64().unwrap() as u16)
65 } else {
66 Err(serde::de::Error::custom("Cannot map extension to u16"))
67 }
68}
69
70pub fn object_id_as_string<'de, D>(deserializer: D) -> Result<String, D::Error>
71where
72 D: Deserializer<'de>,
73{
74 let value = Value::deserialize(deserializer)?;
75 if value.is_string() {
76 Ok(value.as_str().unwrap().to_string())
77 } else {
78 match value.get("$oid") {
79 Some(v) => Ok(v.as_str().unwrap().to_string()),
80 None => Err(serde::de::Error::custom("Oid is required")),
81 }
82 }
83}
84
85pub fn build_timestamp() -> DateTime {
86 DateTime::now()
87}
88
89pub fn build_id() -> String {
90 bson::uuid::Uuid::new().to_string()
91}
92
93impl Debug for RecordReference {
94 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
95 f.debug_struct("RecordReference")
96 .field("id", &self.id)
97 .field("name", &self.name)
98 .field("meta", &self.meta)
99 .finish()
100 }
101}