objectiveai_sdk/
prefixed_uuid.rs1use schemars::JsonSchema;
8use std::str::FromStr;
9
10#[derive(
37 Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, JsonSchema,
38)]
39#[schemars(rename = "PrefixedUuid")]
40pub struct PrefixedUuid<const PFX_1: char, const PFX_2: char, const PFX_3: char>
41{
42 uuid: uuid::Uuid,
43}
44
45impl<const PFX_1: char, const PFX_2: char, const PFX_3: char> From<uuid::Uuid>
46 for PrefixedUuid<PFX_1, PFX_2, PFX_3>
47{
48 fn from(uuid: uuid::Uuid) -> Self {
49 PrefixedUuid { uuid }
50 }
51}
52
53#[derive(Debug, Clone, thiserror::Error)]
58pub enum ParseError<const PFX_1: char, const PFX_2: char, const PFX_3: char> {
59 #[error(
61 "invalid prefix: expected {}{}{} but got {}",
62 PFX_1,
63 PFX_2,
64 PFX_3,
65 _0
66 )]
67 InvalidPrefix(String),
68 #[error("invalid UUID: {0}")]
70 InvalidUuid(uuid::Error),
71}
72
73impl<const PFX_1: char, const PFX_2: char, const PFX_3: char> FromStr
74 for PrefixedUuid<PFX_1, PFX_2, PFX_3>
75{
76 type Err = ParseError<PFX_1, PFX_2, PFX_3>;
77 fn from_str(s: &str) -> Result<Self, Self::Err> {
78 if s.len() >= 3 + uuid::fmt::Simple::LENGTH && {
79 let s_bytes = s.as_bytes();
80 s_bytes[0] == (PFX_1 as u8)
81 && s_bytes[1] == (PFX_2 as u8)
82 && s_bytes[2] == (PFX_3 as u8)
83 } {
84 match uuid::Uuid::parse_str(&s[3..]) {
85 Ok(uuid) => Ok(PrefixedUuid { uuid }),
86 Err(e) => Err(ParseError::InvalidUuid(e)),
87 }
88 } else {
89 Err(ParseError::InvalidPrefix(s.to_string()))
90 }
91 }
92}
93
94impl<const PFX_1: char, const PFX_2: char, const PFX_3: char>
95 PrefixedUuid<PFX_1, PFX_2, PFX_3>
96{
97 pub fn new() -> Self {
108 PrefixedUuid {
109 uuid: uuid::Uuid::new_v4(),
110 }
111 }
112
113 pub fn uuid(&self) -> uuid::Uuid {
125 self.uuid
126 }
127}
128
129impl<const PFX_1: char, const PFX_2: char, const PFX_3: char> std::fmt::Display
130 for PrefixedUuid<PFX_1, PFX_2, PFX_3>
131{
132 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
133 write!(
134 f,
135 "{}{}{}{}",
136 PFX_1,
137 PFX_2,
138 PFX_3,
139 self.uuid
140 .simple()
141 .encode_lower(&mut [0; uuid::fmt::Simple::LENGTH])
142 )
143 }
144}
145
146impl<const PFX_1: char, const PFX_2: char, const PFX_3: char> serde::Serialize
147 for PrefixedUuid<PFX_1, PFX_2, PFX_3>
148{
149 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
150 where
151 S: serde::Serializer,
152 {
153 serializer.serialize_str(&self.to_string())
154 }
155}
156
157impl<'de, const PFX_1: char, const PFX_2: char, const PFX_3: char>
158 serde::Deserialize<'de> for PrefixedUuid<PFX_1, PFX_2, PFX_3>
159{
160 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
161 where
162 D: serde::Deserializer<'de>,
163 {
164 let s = String::deserialize(deserializer)?;
165 PrefixedUuid::from_str(&s).map_err(serde::de::Error::custom)
166 }
167}