1use serde::{Deserialize, Serialize};
2use std::{fmt, hash::Hash, ops::Deref, str::FromStr};
3
4#[derive(Debug, Default, Clone)]
16pub struct Lexical<T> {
17 value: T,
19
20 representation: Option<String>,
22}
23
24impl<T> Lexical<T> {
25 pub fn new(value: T) -> Self {
30 Self {
31 value,
32 representation: None,
33 }
34 }
35
36 pub fn new_with_representation(value: T, representation: String) -> Self {
44 Self {
45 value,
46 representation: Some(representation),
47 }
48 }
49
50 pub fn from_parts(value: T, representation: Option<String>) -> Self {
59 Self {
60 value,
61 representation,
62 }
63 }
64
65 pub fn as_inner(&self) -> &T {
67 &self.value
68 }
69
70 pub fn to_value(&self) -> T
72 where
73 T: Clone,
74 {
75 self.value.clone()
76 }
77
78 pub fn into_value(self) -> T {
80 self.value
81 }
82
83 pub fn into_parts(self) -> (T, Option<String>) {
85 (self.value, self.representation)
86 }
87}
88
89impl<T> Deref for Lexical<T> {
90 type Target = T;
91
92 fn deref(&self) -> &Self::Target {
93 &self.value
94 }
95}
96
97impl<T> From<T> for Lexical<T> {
98 fn from(value: T) -> Self {
99 Self::new(value)
100 }
101}
102
103impl<T: PartialEq> PartialEq for Lexical<T> {
104 fn eq(&self, other: &Self) -> bool {
105 self.value.eq(&other.value)
106 }
107}
108
109impl<T: PartialEq> PartialEq<T> for Lexical<T> {
110 fn eq(&self, other: &T) -> bool {
111 self.value.eq(other)
112 }
113}
114
115impl<T: Eq> Eq for Lexical<T> {}
116
117impl<T: PartialOrd> PartialOrd for Lexical<T> {
118 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
119 self.value.partial_cmp(&other.value)
120 }
121}
122
123impl<T: PartialOrd> PartialOrd<T> for Lexical<T> {
124 fn partial_cmp(&self, other: &T) -> Option<std::cmp::Ordering> {
125 self.value.partial_cmp(other)
126 }
127}
128
129impl<T: Ord> Ord for Lexical<T> {
130 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
131 self.value.cmp(&other.value)
132 }
133}
134
135impl<T: Hash> Hash for Lexical<T> {
136 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
137 self.value.hash(state);
138 }
139}
140
141impl<T: FromStr> FromStr for Lexical<T> {
142 type Err = T::Err;
143
144 fn from_str(s: &str) -> Result<Self, Self::Err> {
145 s.parse()
146 .map(|value| Self::new_with_representation(value, s.to_owned()))
147 }
148}
149
150impl<T: Serialize> Serialize for Lexical<T> {
151 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
152 where
153 S: serde::Serializer,
154 {
155 match &self.representation {
156 Some(r) => r.serialize(serializer),
157 None => self.value.serialize(serializer),
158 }
159 }
160}
161
162impl<'de, T> Deserialize<'de> for Lexical<T>
163where
164 T: FromStr<Err: fmt::Display>,
165{
166 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
167 where
168 D: serde::Deserializer<'de>,
169 {
170 let representation = String::deserialize(deserializer)?;
171 representation
172 .parse()
173 .map_err(serde::de::Error::custom)
174 .map(|value| Self::new_with_representation(value, representation))
175 }
176}
177
178impl<T: fmt::Display> fmt::Display for Lexical<T> {
179 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180 match &self.representation {
181 Some(r) => f.write_str(r),
182 None => self.value.fmt(f),
183 }
184 }
185}
186
187#[cfg(test)]
188mod tests {
189 use super::*;
190
191 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
192 struct I32String(i32);
193
194 impl FromStr for I32String {
195 type Err = <i32 as FromStr>::Err;
196
197 fn from_str(s: &str) -> Result<Self, Self::Err> {
198 s.parse().map(Self)
199 }
200 }
201
202 impl fmt::Display for I32String {
203 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204 self.0.fmt(f)
205 }
206 }
207
208 impl Serialize for I32String {
209 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
210 where
211 S: serde::Serializer,
212 {
213 self.to_string().serialize(serializer)
214 }
215 }
216
217 #[test]
218 fn preserve_lexical_form() {
219 let n: Lexical<I32String> = "00001".parse().unwrap();
220 assert_eq!(n.to_string(), "00001");
221 assert_eq!(n, I32String(1));
222 assert_eq!(
223 serde_json::to_value(n).unwrap(),
224 serde_json::Value::String("00001".to_owned())
225 );
226
227 let m: Lexical<I32String> = serde_json::from_str("\"00001\"").unwrap();
228 assert_eq!(m.to_string(), "00001");
229 assert_eq!(m, I32String(1));
230 }
231}