dtz_identifier/
context_id.rs1use serde::{de::Visitor, Deserialize, Deserializer, Serialize};
2use std::fmt::Display;
3
4static PREFIX: &str = "context-";
5
6#[derive(Debug, Clone, PartialEq, Eq, Hash)]
7pub struct ContextId {
8 pub id: String,
9}
10
11impl Default for ContextId {
12 fn default() -> Self {
13 Self {
14 id: crate::generate_internal_id(),
15 }
16 }
17}
18
19impl Display for ContextId {
20 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21 f.write_str(&format!("{PREFIX}{}", self.id))
22 }
23}
24
25impl TryFrom<String> for ContextId {
26 type Error = String;
27
28 fn try_from(value: String) -> Result<Self, Self::Error> {
29 if let Some(id_str) = value.strip_prefix(PREFIX) {
30 Ok(ContextId {
31 id: id_str.to_string(),
32 })
33 } else {
34 Err("invalid format".to_string())
35 }
36 }
37}
38
39impl TryFrom<&str> for ContextId {
40 type Error = String;
41
42 fn try_from(value: &str) -> Result<Self, Self::Error> {
43 if let Some(id_str) = value.strip_prefix(PREFIX) {
44 Ok(ContextId {
45 id: id_str.to_string(),
46 })
47 } else {
48 Err("invalid format".to_string())
49 }
50 }
51}
52
53impl<'de> Deserialize<'de> for ContextId {
54 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
55 where
56 D: Deserializer<'de>,
57 {
58 struct ContextIdVisitor;
59
60 impl Visitor<'_> for ContextIdVisitor {
61 type Value = ContextId;
62
63 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
64 formatter.write_str("a string starting with '")?;
65 formatter.write_str(PREFIX)?;
66 formatter.write_str("' followed by a 8-character alphanumeric string")
67 }
68
69 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
70 where
71 E: serde::de::Error,
72 {
73 if let Some(id_str) = value.strip_prefix(PREFIX) {
74 Ok(ContextId {
75 id: id_str.to_string(),
76 })
77 } else {
78 Err(E::custom("invalid format"))
79 }
80 }
81 }
82
83 deserializer.deserialize_str(ContextIdVisitor)
84 }
85}
86
87impl Serialize for ContextId {
88 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
89 where
90 S: serde::Serializer,
91 {
92 serializer.serialize_str(&self.to_string())
93 }
94}
95
96#[test]
97fn test_from() {
98 let id = crate::generate_internal_id();
99 let id_str = format!("{PREFIX}{id}");
100 let ctx = ContextId::try_from(id_str).unwrap();
101 assert_eq!(ctx.id, id);
102}
103
104#[test]
105fn key_invalid_1() {
106 let k = "abc-dsfdg";
107 let apikey: Result<ContextId, String> = ContextId::try_from(k);
108 assert!(apikey.is_err())
109}
110
111#[test]
112fn key_invalid_2() {
113 let k = "context-dsfdg";
114 let apikey: Result<ContextId, String> = ContextId::try_from(k);
115 assert!(apikey.is_ok())
116}
117
118#[test]
119fn key_valid_1() {
120 let k = "context-0190c589-eb70-7980-97cf-af67b3a84116";
121 let apikey: Result<ContextId, String> = ContextId::try_from(k);
122 assert!(apikey.is_ok())
123}
124
125#[test]
126fn key_invalid_3() {
127 let k = "abc-0190c589-eb70-7980-97cf-af67b3a84116";
128 let apikey: Result<ContextId, String> = ContextId::try_from(k);
129 assert!(apikey.is_err())
130}