1use std::fmt::{Debug, Display, Formatter};
2use std::num::{NonZeroU64, ParseIntError, TryFromIntError};
3use std::str::FromStr;
4#[cfg(feature = "serde")]
5use serde::{Deserialize, Serialize, Deserializer, Serializer};
6
7#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
8pub struct Xuid(NonZeroU64);
9
10impl TryFrom<u64> for Xuid {
11 type Error = TryFromIntError;
12
13 #[inline]
14 fn try_from(value: u64) -> Result<Self, Self::Error> {
15 value.try_into().map(Xuid)
16 }
17}
18
19impl From<Xuid> for u64 {
20 #[inline]
21 fn from(x: Xuid) -> Self {
22 x.0.get()
23 }
24}
25
26impl From<Xuid> for String {
27 #[inline]
28 fn from(x: Xuid) -> Self {
29 x.0.to_string()
30 }
31}
32
33impl TryFrom<String> for Xuid {
34 type Error = ParseIntError;
35
36 #[inline]
37 fn try_from(value: String) -> Result<Self, Self::Error> {
38 value.parse().map(Self)
39 }
40}
41
42impl TryFrom<&str> for Xuid {
43 type Error = ParseIntError;
44
45 #[inline]
46 fn try_from(value: &str) -> Result<Self, Self::Error> {
47 value.parse().map(Self)
48 }
49}
50
51impl FromStr for Xuid {
52 type Err = ParseIntError;
53
54 fn from_str(value: &str) -> Result<Self, Self::Err> {
55 value.parse().map(Self)
56 }
57}
58
59impl Debug for Xuid {
60 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
61 write!(f, "{:X}", self.0.get())
62 }
63}
64
65impl Display for Xuid {
66 #[inline]
67 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
68 write!(f, "{}", self.0.get())
69 }
70}
71
72#[cfg(feature = "serde")]
73impl Serialize for Xuid {
74 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
75 where
76 S: Serializer,
77 {
78 self.0.to_string().serialize(serializer)
79 }
80}
81
82#[cfg(feature = "serde")]
83impl<'de> Deserialize<'de> for Xuid {
84 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
85 where
86 D: Deserializer<'de>,
87 {
88 let s: &str = Deserialize::deserialize(deserializer)?;
89 Self::try_from(s).map_err(serde::de::Error::custom)
90 }
91}
92
93#[macro_export]
94macro_rules! xuid {
95 ($xuid:literal) => {
96 xuid::Xuid::try_from($xuid)
97 };
98}