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 Id::LegacyLong(
56 input.replace(".", "").parse().unwrap(),
57 input.chars().filter(|x| *x == '.').count(),
58 )
59 } else {
60 let uuid = Uuid::from_u128(match decode(input) {
61 Ok(x) => x,
62 Err(_) => return Id::default(),
63 });
64
65 Id::Next(tritools::id::Id(uuid))
66 }
67 }
68}
69
70impl Serialize for Id {
71 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
72 where
73 S: serde::Serializer,
74 {
75 serializer.serialize_str(&self.printable())
76 }
77}
78
79struct IdVisitor;
80
81fn is_numeric(haystack: &str) -> bool {
82 for c in haystack.chars() {
83 if !c.is_numeric() && !c.is_ascii_punctuation() {
84 return false;
85 }
86 }
87
88 true
89}
90
91macro_rules! impl_number_visitor {
92 ($n:ident, $t:ty) => {
93 fn $n<E>(self, v: $t) -> Result<Self::Value, E>
94 where
95 E: serde::de::Error,
96 {
97 Ok(Id::Legacy(v as usize))
98 }
99 };
100}
101
102impl<'de> Visitor<'de> for IdVisitor {
103 type Value = Id;
104
105 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
106 formatter.write_str("a string")
107 }
108
109 fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
110 where
111 E: serde::de::Error,
112 {
113 Ok(Id::deserialize(&v))
114 }
115
116 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
117 where
118 E: serde::de::Error,
119 {
120 Ok(Id::deserialize(v))
121 }
122
123 impl_number_visitor!(visit_f32, f32);
124 impl_number_visitor!(visit_i32, i32);
125 impl_number_visitor!(visit_u32, u32);
126 impl_number_visitor!(visit_i64, i64);
127 impl_number_visitor!(visit_u64, u64);
128 impl_number_visitor!(visit_i128, i128);
129 impl_number_visitor!(visit_u128, u128);
130}
131
132impl<'de> Deserialize<'de> for Id {
133 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
134 where
135 D: Deserializer<'de>,
136 {
137 deserializer.deserialize_any(IdVisitor)
138 }
139}
140
141impl Display for Id {
142 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
143 f.write_str(&self.printable())
144 }
145}
146
147impl Default for Id {
148 fn default() -> Self {
149 Self::Legacy(0)
150 }
151}