1use std::{
8 fmt,
9 io::{Read, Write},
10 str::FromStr,
11};
12
13use uuid::Uuid;
14
15use crate::encoding::*;
16
17#[derive(Eq, PartialEq, Clone)]
19pub struct Guid {
20 uuid: Uuid,
21}
22
23impl std::hash::Hash for Guid {
26 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
27 self.as_bytes().hash(state);
28 }
29}
30
31impl From<Guid> for Uuid {
32 fn from(value: Guid) -> Self {
33 value.uuid
34 }
35}
36
37impl UaNullable for Guid {
38 fn is_ua_null(&self) -> bool {
39 self.uuid.is_nil()
40 }
41}
42
43#[cfg(feature = "json")]
44mod json {
45 use std::io::{Read, Write};
46 use std::str::FromStr;
47
48 use crate::{json::*, Error};
49
50 use super::Guid;
51
52 impl JsonEncodable for Guid {
53 fn encode(
54 &self,
55 stream: &mut JsonStreamWriter<&mut dyn Write>,
56 _ctx: &crate::json::Context<'_>,
57 ) -> super::EncodingResult<()> {
58 Ok(stream.string_value(&self.uuid.to_string())?)
59 }
60 }
61
62 impl JsonDecodable for Guid {
63 fn decode(
64 stream: &mut JsonStreamReader<&mut dyn Read>,
65 _ctx: &Context<'_>,
66 ) -> super::EncodingResult<Self> {
67 let s = stream.next_str()?;
68 let guid = Guid::from_str(s).map_err(Error::decoding)?;
69 Ok(guid)
70 }
71 }
72}
73
74#[cfg(feature = "xml")]
75mod xml {
76 use crate::xml::*;
77 use std::{
78 io::{Read, Write},
79 str::FromStr,
80 };
81
82 use super::Guid;
83
84 impl XmlType for Guid {
85 const TAG: &'static str = "Guid";
86 }
87
88 impl XmlEncodable for Guid {
89 fn encode(
90 &self,
91 writer: &mut XmlStreamWriter<&mut dyn Write>,
92 ctx: &crate::xml::Context<'_>,
93 ) -> EncodingResult<()> {
94 writer.encode_child("String", &self.to_string(), ctx)
95 }
96 }
97
98 impl XmlDecodable for Guid {
99 fn decode(
100 reader: &mut XmlStreamReader<&mut dyn Read>,
101 ctx: &crate::xml::Context<'_>,
102 ) -> EncodingResult<Self> {
103 let val: Option<String> = reader.decode_single_child("String", ctx)?;
104 let Some(val) = val else {
105 return Ok(Guid::null());
106 };
107 Guid::from_str(&val).map_err(Error::decoding)
108 }
109 }
110}
111
112impl fmt::Display for Guid {
113 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
114 write!(f, "{}", self.uuid)
115 }
116}
117
118impl fmt::Debug for Guid {
119 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120 write!(f, "{}", self.uuid.hyphenated())
121 }
122}
123
124impl BinaryEncodable for Guid {
125 fn byte_len(&self, _ctx: &crate::Context<'_>) -> usize {
126 16
127 }
128
129 fn encode<S: Write + ?Sized>(
130 &self,
131 stream: &mut S,
132 _ctx: &crate::Context<'_>,
133 ) -> EncodingResult<()> {
134 process_encode_io_result(stream.write_all(self.uuid.as_bytes()))
135 }
136}
137
138impl BinaryDecodable for Guid {
139 fn decode<S: Read + ?Sized>(stream: &mut S, _ctx: &crate::Context<'_>) -> EncodingResult<Self> {
140 let mut bytes = [0u8; 16];
141 process_decode_io_result(stream.read_exact(&mut bytes))?;
142 Ok(Guid {
143 uuid: Uuid::from_bytes(bytes),
144 })
145 }
146}
147
148impl FromStr for Guid {
149 type Err = <Uuid as FromStr>::Err;
150
151 fn from_str(s: &str) -> Result<Self, Self::Err> {
152 Uuid::from_str(s).map(|uuid| Guid { uuid })
153 }
154}
155
156impl From<Uuid> for Guid {
157 fn from(uuid: Uuid) -> Self {
158 Self { uuid }
159 }
160}
161
162impl Default for Guid {
163 fn default() -> Self {
164 Guid::null()
165 }
166}
167
168impl Guid {
169 pub fn null() -> Guid {
171 Guid { uuid: Uuid::nil() }
172 }
173
174 pub fn new() -> Guid {
176 Guid {
177 uuid: Uuid::new_v4(),
178 }
179 }
180
181 pub fn as_bytes(&self) -> &[u8; 16] {
183 self.uuid.as_bytes()
184 }
185
186 pub fn from_bytes(bytes: [u8; 16]) -> Guid {
188 Guid {
189 uuid: Uuid::from_bytes(bytes),
190 }
191 }
192
193 pub fn from_slice(bytes: &[u8]) -> Result<Guid, uuid::Error> {
195 Ok(Guid {
196 uuid: Uuid::from_slice(bytes)?,
197 })
198 }
199}
200
201impl AsRef<[u8; 16]> for Guid {
202 fn as_ref(&self) -> &[u8; 16] {
203 self.as_bytes()
204 }
205}
206
207impl PartialEq<[u8; 16]> for Guid {
208 fn eq(&self, other: &[u8; 16]) -> bool {
209 self.as_ref() == other
210 }
211}
212
213pub struct GuidRef<'a>(pub &'a [u8; 16]);
217
218impl PartialEq<Guid> for GuidRef<'_> {
219 fn eq(&self, other: &Guid) -> bool {
220 self.as_ref() == other.as_bytes()
221 }
222}
223
224impl PartialEq<GuidRef<'_>> for Guid {
225 fn eq(&self, other: &GuidRef<'_>) -> bool {
226 other == self
227 }
228}
229
230impl std::hash::Hash for GuidRef<'_> {
231 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
232 self.0.hash(state);
233 }
234}
235
236impl AsRef<[u8; 16]> for GuidRef<'_> {
237 fn as_ref(&self) -> &[u8; 16] {
238 self.0
239 }
240}