submilli_engine/runtime/
durable.rs1#[derive(
5 Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize,
6)]
7#[serde(transparent)]
8pub struct RunId(pub String);
9
10impl From<String> for RunId {
11 fn from(value: String) -> Self {
12 Self(value)
13 }
14}
15impl From<&str> for RunId {
16 fn from(value: &str) -> Self {
17 Self(value.to_owned())
18 }
19}
20impl std::ops::Deref for RunId {
21 type Target = str;
22 fn deref(&self) -> &str {
23 self.as_str()
24 }
25}
26impl std::fmt::Display for RunId {
27 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28 formatter.write_str(self.as_str())
29 }
30}
31impl RunId {
32 pub fn generate() -> std::io::Result<Self> {
34 let mut bytes = [0; 16];
35 getrandom::getrandom(&mut bytes)
36 .map_err(|error| std::io::Error::other(format!("run ID entropy: {error}")))?;
37 Ok(Self(
38 uuid::Builder::from_random_bytes(bytes)
39 .into_uuid()
40 .to_string(),
41 ))
42 }
43
44 pub fn as_str(&self) -> &str {
45 &self.0
46 }
47}
48
49impl std::borrow::Borrow<str> for RunId {
50 fn borrow(&self) -> &str {
51 self.as_str()
52 }
53}
54
55#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize)]
57#[serde(transparent)]
58pub struct EffectId(pub String);
59impl From<String> for EffectId {
60 fn from(value: String) -> Self {
61 Self(value)
62 }
63}
64impl From<&str> for EffectId {
65 fn from(value: &str) -> Self {
66 Self(value.to_owned())
67 }
68}
69impl std::ops::Deref for EffectId {
70 type Target = str;
71 fn deref(&self) -> &str {
72 &self.0
73 }
74}
75impl std::fmt::Display for EffectId {
76 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77 formatter.write_str(self.as_str())
78 }
79}
80
81impl EffectId {
82 pub fn as_str(&self) -> &str {
83 &self.0
84 }
85
86 pub fn stub() -> std::io::Result<Self> {
89 let mut bytes = [0; 16];
90 getrandom::getrandom(&mut bytes)
91 .map_err(|error| std::io::Error::other(format!("effect ID entropy: {error}")))?;
92 Ok(uuid::Builder::from_random_bytes(bytes)
93 .into_uuid()
94 .to_string()
95 .into())
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102
103 #[test]
104 fn generated_runs_have_distinct_uuid_identities() {
105 let first = RunId::generate().unwrap();
106 let second = RunId::generate().unwrap();
107 assert_ne!(first, second);
108 assert_eq!(
109 uuid::Uuid::parse_str(first.as_str())
110 .unwrap()
111 .get_version_num(),
112 4
113 );
114 }
115
116 #[test]
117 fn stored_identities_remain_plain_strings() {
118 for value in ["legacy-reservation", "00000000-0000-4000-8000-000000000001"] {
119 let id = RunId::from(value);
120 let encoded = serde_json::to_value(&id).unwrap();
121 assert_eq!(encoded, value);
122 assert_eq!(serde_json::from_value::<RunId>(encoded).unwrap(), id);
123 }
124 }
125}