tetratto_core2/model/
id.rs1use std::fmt::Display;
2
3use base62::decode;
4use serde::{Deserialize, Deserializer, Serialize, de::Visitor};
5use tritools::id::Id as NewId;
6use uuid::Uuid;
7
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub enum Id {
10 Next(NewId),
11 Legacy(usize),
12 LegacyLong(usize, usize),
14}
15
16impl Id {
17 pub fn new() -> Self {
19 Self::Next(NewId::new())
20 }
21
22 pub fn as_usize(&self) -> usize {
24 match self {
25 Self::Next(x) => x.0.as_u128() as usize,
26 Self::Legacy(x) => *x,
27 Self::LegacyLong(x, _) => *x,
28 }
29 }
30
31 pub fn printable(&self) -> String {
33 match self {
34 Self::Next(x) => x.printable(),
35 Self::Legacy(x) => x.to_string(),
36 Self::LegacyLong(x, p) => ".".repeat(*p) + &x.to_string(),
37 }
38 }
39
40 pub fn serialize(&self) -> String {
42 serde_json::to_string(&self)
43 .unwrap()
44 .trim_matches('"')
45 .to_string()
46 }
47
48 pub fn deserialize(input: &str) -> Self {
50 if input.is_empty() || input.len() < 12 {
51 return Id::default();
52 }
53
54 if is_numeric(input) {
55 let pad = input.chars().filter(|x| *x == '.').count();
56
57 if pad == 0 {
58 Id::Legacy(input.replace(".", "").parse().unwrap())
59 } else {
60 Id::LegacyLong(input.replace(".", "").parse().unwrap(), pad)
61 }
62 } else {
63 let uuid = Uuid::from_u128(match decode(input) {
64 Ok(x) => x,
65 Err(_) => return Id::default(),
66 });
67
68 Id::Next(tritools::id::Id(uuid))
69 }
70 }
71
72 pub fn normalize(self) -> Self {
74 match self {
75 Self::Next(x) => Self::Next(x),
76 Self::Legacy(x) => Self::Legacy(x),
77 Self::LegacyLong(x, _) => Self::Legacy(x),
78 }
79 }
80}
81
82impl Serialize for Id {
83 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
84 where
85 S: serde::Serializer,
86 {
87 serializer.serialize_str(&self.printable())
88 }
89}
90
91struct IdVisitor;
92
93fn is_numeric(haystack: &str) -> bool {
94 for c in haystack.chars() {
95 if !c.is_numeric() && !c.is_ascii_punctuation() {
96 return false;
97 }
98 }
99
100 true
101}
102
103macro_rules! impl_number_visitor {
104 ($n:ident, $t:ty) => {
105 fn $n<E>(self, v: $t) -> Result<Self::Value, E>
106 where
107 E: serde::de::Error,
108 {
109 Ok(Id::Legacy(v as usize))
110 }
111 };
112}
113
114impl<'de> Visitor<'de> for IdVisitor {
115 type Value = Id;
116
117 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
118 formatter.write_str("a string")
119 }
120
121 fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
122 where
123 E: serde::de::Error,
124 {
125 Ok(Id::deserialize(&v))
126 }
127
128 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
129 where
130 E: serde::de::Error,
131 {
132 Ok(Id::deserialize(v))
133 }
134
135 impl_number_visitor!(visit_f32, f32);
136 impl_number_visitor!(visit_i32, i32);
137 impl_number_visitor!(visit_u32, u32);
138 impl_number_visitor!(visit_i64, i64);
139 impl_number_visitor!(visit_u64, u64);
140 impl_number_visitor!(visit_i128, i128);
141 impl_number_visitor!(visit_u128, u128);
142}
143
144impl<'de> Deserialize<'de> for Id {
145 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
146 where
147 D: Deserializer<'de>,
148 {
149 deserializer.deserialize_any(IdVisitor)
150 }
151}
152
153impl Display for Id {
154 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
155 f.write_str(&self.printable())
156 }
157}
158
159impl Default for Id {
160 fn default() -> Self {
161 Self::Legacy(0)
162 }
163}