1use std::fmt::{Display, LowerHex, UpperHex};
5
6#[cfg(feature = "uuid_v1")]
7use std::time::SystemTime;
8#[cfg(feature = "uuid_v1")]
9use uuid::Uuid as V1Generator;
10
11use crate::data::{DeserializeCopy, Deserializeable, Serializeable};
12
13#[allow(clippy::upper_case_acronyms)]
17#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Default)]
18pub struct UUID {
19 low: u64,
20 high: u64,
21}
22
23impl UUID {
24 pub const fn new(low: u64, high: u64) -> Self {
27 Self { low, high }
28 }
29
30 pub const fn into_fields(self) -> (u64, u64) {
33 (self.low, self.high)
34 }
35
36 pub const NIL: UUID = UUID::new(0, 0);
39
40 #[cfg(feature = "random_uuid")]
43 pub fn random() -> Self {
44 use rand::prelude::*;
45 let (mut high, mut low) = thread_rng().gen();
46 high = (high & !0xF000) | 0x4000;
47 low = low & !0x8000000000000000;
48 UUID { low, high }
49 }
50
51 #[cfg(feature = "uuid_v1")]
54 pub fn time_based() -> Self {
55 use rand::prelude::*;
56 use uuid::v1::{Context, Timestamp};
57 static SEQ: Context = Context::new(0);
58 let bytes = thread_rng().gen::<[u8; 6]>();
59 let time = SystemTime::now()
60 .duration_since(SystemTime::UNIX_EPOCH)
61 .unwrap();
62 let ts = Timestamp::from_unix(&SEQ, time.as_secs(), time.subsec_nanos());
63 let other = V1Generator::new_v1(ts, &bytes).unwrap();
64 let fields = other.as_fields();
65 let high = ((fields.0 as u64) << 32) | ((fields.1 as u64) << 16) | (fields.2 as u64);
66 let low = u64::from_be_bytes(*fields.3);
67 UUID { high, low }
68 }
69}
70
71impl From<u128> for UUID {
72 fn from(v: u128) -> Self {
73 Self::new(v as u64, (v >> 64) as u64)
74 }
75}
76
77impl From<UUID> for u128 {
78 fn from(u: UUID) -> Self {
79 ((u.high as u128) << 64) | (u.low as u128)
80 }
81}
82
83impl Display for UUID {
84 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85 let h0 = (self.high >> 32) as u32;
86 let h1 = (self.high & 0xffff0000 >> 16) as u16;
87 let h2 = (self.high & 0xffff) as u16;
88 let l0 = (self.low >> 48) as u16;
89 let l1 = self.low & 0xffffffffffff;
90 f.write_fmt(format_args!(
91 "{:08x}-{:08x}-{:08x}-{:08x}-{:08x}",
92 h0, h1, h2, l0, l1
93 ))
94 }
95}
96
97impl LowerHex for UUID {
99 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
100 let h0 = (self.high >> 32) as u32;
101 let h1 = (self.high & 0xffff0000 >> 16) as u16;
102 let h2 = (self.high & 0xffff) as u16;
103 let l0 = (self.low >> 48) as u16;
104 let l1 = self.low & 0xffffffffffff;
105 f.write_fmt(format_args!(
106 "{:08x}-{:08x}-{:08x}-{:08x}-{:08x}",
107 h0, h1, h2, l0, l1
108 ))
109 }
110}
111
112impl UpperHex for UUID {
114 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
115 let h0 = (self.high >> 32) as u32;
116 let h1 = (self.high & 0xffff0000 >> 16) as u16;
117 let h2 = (self.high & 0xffff) as u16;
118 let l0 = (self.low >> 48) as u16;
119 let l1 = self.low & 0xffffffffffff;
120 f.write_fmt(format_args!(
121 "{:08X}-{:08X}-{:08X}-{:08X}-{:08X}",
122 h0, h1, h2, l0, l1
123 ))
124 }
125}
126
127impl Serializeable for UUID {
128 fn serialize<W: crate::data::DataOutput + ?Sized>(
129 &self,
130 output: &mut W,
131 ) -> std::io::Result<()> {
132 self.high.serialize(output)?;
133 self.low.serialize(output)
134 }
135}
136
137impl Deserializeable for UUID {
138 fn deserialize<R: crate::data::DataInput + ?Sized>(
139 &mut self,
140 input: &mut R,
141 ) -> std::io::Result<()> {
142 self.high.deserialize(input)?;
143 self.low.deserialize(input)
144 }
145}
146
147impl DeserializeCopy for UUID {
148 fn deserialize_copy<R: crate::data::DataInput + ?Sized>(
149 input: &mut R,
150 ) -> std::io::Result<Self> {
151 Ok(Self {
152 high: u64::deserialize_copy(input)?,
153 low: u64::deserialize_copy(input)?,
154 })
155 }
156}