1use std::fmt::{self, Display, Formatter};
7use std::ops::Add;
8use std::str::FromStr;
9use std::time::SystemTime;
10
11use base64::Engine;
12use base64::engine::general_purpose::STANDARD as B64;
13use serde::{Deserialize, Deserializer, Serialize, Serializer};
14use serde_with::{DisplayFromStr, serde_as};
15
16#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, Hash)]
22pub struct Version<const N: u8>;
23
24impl<const N: u8> Version<N> {
25 pub const VALUE: u8 = N;
27}
28
29impl<const N: u8> PartialEq<u8> for Version<N> {
30 fn eq(&self, other: &u8) -> bool {
31 *other == N
32 }
33}
34
35impl<const N: u8> From<Version<N>> for u8 {
36 fn from(_: Version<N>) -> Self {
37 N
38 }
39}
40
41impl<const N: u8> Display for Version<N> {
42 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
43 write!(f, "{N}")
44 }
45}
46
47impl<const N: u8> Serialize for Version<N> {
48 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
49 serializer.serialize_u8(N)
50 }
51}
52
53impl<'de, const N: u8> Deserialize<'de> for Version<N> {
54 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
55 let v = u8::deserialize(deserializer)?;
56 if v == N {
57 Ok(Self)
58 } else {
59 Err(serde::de::Error::custom(format!(
60 "expected protocol version {N}, got {v}"
61 )))
62 }
63 }
64}
65
66pub type Version2 = Version<2>;
68
69pub const V2: Version2 = Version;
71
72#[derive(Debug, Clone, PartialEq, Eq)]
89pub struct Base64Bytes(pub Vec<u8>);
90
91impl Base64Bytes {
92 pub fn decode(&self) -> Result<Vec<u8>, base64::DecodeError> {
99 B64.decode(&self.0)
100 }
101
102 #[must_use]
104 pub fn encode<T: AsRef<[u8]>>(input: T) -> Self {
105 Self(B64.encode(input.as_ref()).into_bytes())
106 }
107}
108
109impl AsRef<[u8]> for Base64Bytes {
110 fn as_ref(&self) -> &[u8] {
111 &self.0
112 }
113}
114
115impl From<&[u8]> for Base64Bytes {
116 fn from(slice: &[u8]) -> Self {
117 Self(slice.to_vec())
118 }
119}
120
121impl Display for Base64Bytes {
122 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
123 f.write_str(&String::from_utf8_lossy(&self.0))
124 }
125}
126
127#[serde_as]
145#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
146#[repr(transparent)]
147pub struct U64String(#[serde_as(as = "DisplayFromStr")] u64);
148
149impl U64String {
150 #[must_use]
152 pub const fn inner(self) -> u64 {
153 self.0
154 }
155}
156
157impl Display for U64String {
158 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
159 Display::fmt(&self.0, f)
160 }
161}
162
163impl FromStr for U64String {
164 type Err = <u64 as FromStr>::Err;
165 fn from_str(s: &str) -> Result<Self, Self::Err> {
166 s.parse::<u64>().map(Self)
167 }
168}
169
170impl From<u64> for U64String {
171 fn from(value: u64) -> Self {
172 Self(value)
173 }
174}
175
176impl From<U64String> for u64 {
177 fn from(value: U64String) -> Self {
178 value.0
179 }
180}
181
182#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Ord, Eq, Hash)]
200pub struct UnixTimestamp(u64);
201
202impl UnixTimestamp {
203 #[must_use]
205 pub const fn from_secs(secs: u64) -> Self {
206 Self(secs)
207 }
208
209 #[must_use]
213 pub fn now() -> Self {
214 let secs = SystemTime::now()
215 .duration_since(SystemTime::UNIX_EPOCH)
216 .map(|d| d.as_secs())
217 .unwrap_or_default();
218 Self(secs)
219 }
220
221 #[must_use]
223 pub const fn as_secs(self) -> u64 {
224 self.0
225 }
226}
227
228impl Display for UnixTimestamp {
229 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
230 Display::fmt(&self.0, f)
231 }
232}
233
234impl Add<u64> for UnixTimestamp {
235 type Output = Self;
236 fn add(self, rhs: u64) -> Self::Output {
237 Self(self.0.saturating_add(rhs))
238 }
239}
240
241impl Serialize for UnixTimestamp {
242 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
243 serializer.collect_str(&self.0)
244 }
245}
246
247impl<'de> Deserialize<'de> for UnixTimestamp {
248 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
249 struct Visitor;
250
251 impl serde::de::Visitor<'_> for Visitor {
252 type Value = UnixTimestamp;
253
254 fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result {
255 f.write_str("a non-negative integer or its string representation")
256 }
257
258 fn visit_u64<E: serde::de::Error>(self, v: u64) -> Result<Self::Value, E> {
259 Ok(UnixTimestamp(v))
260 }
261
262 fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
263 v.parse::<u64>()
264 .map(UnixTimestamp)
265 .map_err(|_| E::custom("expected non-negative integer"))
266 }
267 }
268
269 deserializer.deserialize_any(Visitor)
270 }
271}