uuid/serde.rs
1// Copyright 2013-2014 The Rust Project Developers.
2// Copyright 2018 The Uuid Project Developers.
3//
4// See the COPYRIGHT file at the top-level directory of this distribution.
5//
6// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
7// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
8// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
9// option. This file may not be copied, modified, or distributed
10// except according to those terms.
11
12use std::fmt;
13
14use serde::{
15 Deserialize, Deserializer, Serialize, Serializer,
16 de::{self, Error as _},
17};
18
19use crate::{Error, Uuid};
20
21impl Serialize for Uuid {
22 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
23 if serializer.is_human_readable() {
24 serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer()))
25 } else {
26 serializer.serialize_bytes(self.as_bytes())
27 }
28 }
29}
30
31impl<'de> Deserialize<'de> for Uuid {
32 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
33 fn de_error<E: de::Error>(err: Error) -> E {
34 E::custom(format_args!("UUID parsing failed: {}", err))
35 }
36
37 if deserializer.is_human_readable() {
38 struct UuidVisitor;
39
40 impl<'vi> de::Visitor<'vi> for UuidVisitor {
41 type Value = Uuid;
42
43 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
44 write!(formatter, "a UUID string")
45 }
46
47 fn visit_str<E: de::Error>(self, value: &str) -> Result<Uuid, E> {
48 value.parse::<Uuid>().map_err(de_error)
49 }
50
51 fn visit_bytes<E: de::Error>(self, value: &[u8]) -> Result<Uuid, E> {
52 Uuid::from_slice(value).map_err(de_error)
53 }
54
55 fn visit_seq<A>(self, mut seq: A) -> Result<Uuid, A::Error>
56 where
57 A: de::SeqAccess<'vi>,
58 {
59 #[rustfmt::skip]
60 let bytes = [
61 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(0, &self)) },
62 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(1, &self)) },
63 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(2, &self)) },
64 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(3, &self)) },
65 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(4, &self)) },
66 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(5, &self)) },
67 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(6, &self)) },
68 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(7, &self)) },
69 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(8, &self)) },
70 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(9, &self)) },
71 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(10, &self)) },
72 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(11, &self)) },
73 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(12, &self)) },
74 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(13, &self)) },
75 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(14, &self)) },
76 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(15, &self)) },
77 ];
78
79 Ok(Uuid::from_bytes(bytes))
80 }
81 }
82
83 deserializer.deserialize_str(UuidVisitor)
84 } else {
85 struct UuidBytesVisitor;
86
87 impl<'vi> de::Visitor<'vi> for UuidBytesVisitor {
88 type Value = Uuid;
89
90 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
91 write!(formatter, "bytes")
92 }
93
94 fn visit_bytes<E: de::Error>(self, value: &[u8]) -> Result<Uuid, E> {
95 Uuid::from_slice(value).map_err(de_error)
96 }
97 }
98
99 deserializer.deserialize_bytes(UuidBytesVisitor)
100 }
101 }
102}
103
104// #[cfg(test)]
105// mod serde_tests {
106// use super::*;
107
108// use serde::serde_test::{Compact, Configure, Readable, Token};
109
110// #[test]
111// fn test_serialize_readable_string() {
112// let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
113// let u = Uuid::parse_str(uuid_str).unwrap();
114// serde_test::assert_tokens(&u.readable(), &[Token::Str(uuid_str)]);
115// }
116// }
117
118// #[test]
119// fn test_deserialize_readable_compact() {
120// let uuid_bytes = b"F9168C5E-CEB2-4F";
121// let u = Uuid::from_slice(uuid_bytes).unwrap();
122
123// serde_test::assert_de_tokens(
124// &u.readable(),
125// &[
126// serde_test::Token::Tuple { len: 16 },
127// serde_test::Token::U8(uuid_bytes[0]),
128// serde_test::Token::U8(uuid_bytes[1]),
129// serde_test::Token::U8(uuid_bytes[2]),
130// serde_test::Token::U8(uuid_bytes[3]),
131// serde_test::Token::U8(uuid_bytes[4]),
132// serde_test::Token::U8(uuid_bytes[5]),
133// serde_test::Token::U8(uuid_bytes[6]),
134// serde_test::Token::U8(uuid_bytes[7]),
135// serde_test::Token::U8(uuid_bytes[8]),
136// serde_test::Token::U8(uuid_bytes[9]),
137// serde_test::Token::U8(uuid_bytes[10]),
138// serde_test::Token::U8(uuid_bytes[11]),
139// serde_test::Token::U8(uuid_bytes[12]),
140// serde_test::Token::U8(uuid_bytes[13]),
141// serde_test::Token::U8(uuid_bytes[14]),
142// serde_test::Token::U8(uuid_bytes[15]),
143// serde_test::Token::TupleEnd,
144// ],
145// );
146// }
147
148// #[test]
149// fn test_deserialize_readable_bytes() {
150// let uuid_bytes = b"F9168C5E-CEB2-4F";
151// let u = Uuid::from_slice(uuid_bytes).unwrap();
152
153// serde_test::assert_de_tokens(&u.readable(), &[serde_test::Token::Bytes(uuid_bytes)]);
154// }
155
156// #[test]
157// fn test_serialize_hyphenated() {
158// let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
159// let u = Uuid::parse_str(uuid_str).unwrap();
160// serde_test::assert_ser_tokens(&u.hyphenated(), &[Token::Str(uuid_str)]);
161// }
162
163// #[test]
164// fn test_serialize_simple() {
165// let uuid_str = "f9168c5eceb24faab6bf329bf39fa1e4";
166// let u = Uuid::parse_str(uuid_str).unwrap();
167// serde_test::assert_ser_tokens(&u.simple(), &[Token::Str(uuid_str)]);
168// }
169
170// #[test]
171// fn test_serialize_urn() {
172// let uuid_str = "urn:uuid:f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
173// let u = Uuid::parse_str(uuid_str).unwrap();
174// serde_test::assert_ser_tokens(&u.urn(), &[Token::Str(uuid_str)]);
175// }
176
177// #[test]
178// fn test_serialize_braced() {
179// let uuid_str = "{f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4}";
180// let u = Uuid::parse_str(uuid_str).unwrap();
181// serde_test::assert_ser_tokens(&u.braced(), &[Token::Str(uuid_str)]);
182// }
183
184// #[test]
185// fn test_serialize_non_human_readable() {
186// let uuid_bytes = b"F9168C5E-CEB2-4F";
187// let u = Uuid::from_slice(uuid_bytes).unwrap();
188// serde_test::assert_tokens(
189// &u.compact(),
190// &[serde_test::Token::Bytes(&[
191// 70, 57, 49, 54, 56, 67, 53, 69, 45, 67, 69, 66, 50, 45, 52, 70,
192// ])],
193// );
194// }
195
196// #[test]
197// fn test_de_failure() {
198// serde_test::assert_de_tokens_error::<Readable<Uuid>>(
199// &[Token::Str("hello_world")],
200// "UUID parsing failed: invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-fA-F-], found `h` at 1",
201// );
202
203// serde_test::assert_de_tokens_error::<Compact<Uuid>>(
204// &[Token::Bytes(b"hello_world")],
205// "UUID parsing failed: invalid length: expected 16 bytes, found 11",
206// );
207// }
208// }