1mod fmt;
2mod parse;
3mod serde;
4mod v4;
5mod v7;
6mod v8;
7#[derive(Clone, Copy, Debug, PartialEq, thiserror::Error)]
10pub enum Error {
11 #[error("uuid: Size is not valid")]
12 InvalidSize,
13 #[error("uuid: Invalid uuid")]
14 InvalidUuid,
15}
16
17#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
18pub struct Uuid([u8; 16]);
19
20#[derive(Clone, Copy, Debug, PartialEq)]
21#[non_exhaustive]
22#[repr(u8)]
23pub enum Version {
24 Nil = 0u8,
26 V4 = 4,
28 V7 = 7,
30 V8 = 8,
32 Max = 0xff,
34}
35
36impl Uuid {
37 pub const fn nil() -> Uuid {
60 Uuid([0; 16])
61 }
62
63 pub const fn get_version(&self) -> Option<Version> {
64 match self.0[6] >> 4 {
65 0 if self.is_nil() => Some(Version::Nil),
66 4 => Some(Version::V4),
67 7 => Some(Version::V7),
68 0xf => Some(Version::Max),
69 _ => None,
70 }
71 }
72
73 pub const fn is_nil(&self) -> bool {
74 self.as_u128() == u128::MIN
75 }
76
77 pub const fn as_u128(&self) -> u128 {
78 u128::from_be_bytes(self.0)
79 }
80
81 pub const fn from_u128(v: u128) -> Self {
82 Uuid::from_bytes([
83 (v >> 120) as u8,
84 (v >> 112) as u8,
85 (v >> 104) as u8,
86 (v >> 96) as u8,
87 (v >> 88) as u8,
88 (v >> 80) as u8,
89 (v >> 72) as u8,
90 (v >> 64) as u8,
91 (v >> 56) as u8,
92 (v >> 48) as u8,
93 (v >> 40) as u8,
94 (v >> 32) as u8,
95 (v >> 24) as u8,
96 (v >> 16) as u8,
97 (v >> 8) as u8,
98 v as u8,
99 ])
100 }
101
102 #[inline]
103 pub const fn from_bytes(bytes: [u8; 16]) -> Uuid {
104 Uuid(bytes)
105 }
106
107 pub const fn as_bytes(&self) -> &[u8; 16] {
108 &self.0
109 }
110
111 pub fn from_slice(b: &[u8]) -> Result<Uuid, Error> {
112 if b.len() != 16 {
113 return Err(Error::InvalidSize);
114 }
115
116 let mut bytes = [0; 16];
117 bytes.copy_from_slice(b);
118 return Ok(Uuid(bytes));
119 }
120
121 pub fn parse_str(input: &str) -> Result<Uuid, Error> {
122 Self::try_parse(input.as_bytes())
123 .map(|bytes| Uuid(bytes))
124 .map_err(|_| Error::InvalidUuid)
125 }
126
127 const fn try_parse(input: &[u8]) -> Result<[u8; 16], Error> {
128 match (input.len(), input) {
129 (36, s) => parse::parse_hyphenated(s),
130 _ => Err(Error::InvalidUuid),
132 }
133 }
134}
135
136impl Uuid {
139 pub fn hyphenated(&self) -> String {
140 return self.to_string();
141 }
142
143 pub fn as_hyphenated(&self) -> String {
144 return self.to_string();
145 }
146
147 pub fn simple(&self) -> Self {
148 return self.clone();
149 }
150
151 pub fn as_simple(&self) -> Self {
152 return self.clone();
153 }
154}
155
156pub type Bytes = [u8; 16];
157
158#[derive(Clone, Copy, Debug, PartialEq)]
159#[non_exhaustive]
160#[repr(u8)]
161pub enum Variant {
162 NCS = 0u8,
164 RFC4122,
167 Microsoft,
169 Future,
171}
172
173pub struct Builder(Uuid);
175
176impl Builder {
177 pub const fn from_random_bytes(random_bytes: Bytes) -> Self {
178 Builder(Uuid::from_bytes(random_bytes))
179 .with_variant(Variant::RFC4122)
180 .with_version(Version::V4)
181 }
182
183 pub const fn into_uuid(self) -> Uuid {
184 self.0
185 }
186
187 pub const fn with_variant(mut self, v: Variant) -> Self {
188 let byte = (self.0).0[8];
189
190 (self.0).0[8] = match v {
191 Variant::NCS => byte & 0x7f,
192 Variant::RFC4122 => (byte & 0x3f) | 0x80,
193 Variant::Microsoft => (byte & 0x1f) | 0xc0,
194 Variant::Future => byte | 0xe0,
195 };
196
197 self
198 }
199
200 pub const fn with_version(mut self, v: Version) -> Self {
201 (self.0).0[6] = ((self.0).0[6] & 0x0f) | ((v as u8) << 4);
202
203 self
204 }
205}