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 12 use crate::{ 13 convert::TryFrom, 14 error::*, 15 fmt::{Braced, Hyphenated, Simple, Urn}, 16 non_nil::NonNilUuid, 17 std::fmt, 18 Uuid, 19 }; 20 use serde::{ 21 de::{self, Error as _}, 22 Deserialize, Deserializer, Serialize, Serializer, 23 }; 24 25 impl Serialize for Uuid { serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>26 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { 27 if serializer.is_human_readable() { 28 serializer.serialize_str(self.hyphenated().encode_lower(&mut Uuid::encode_buffer())) 29 } else { 30 serializer.serialize_bytes(self.as_bytes()) 31 } 32 } 33 } 34 35 impl Serialize for NonNilUuid { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer,36 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 37 where 38 S: serde::Serializer, 39 { 40 Uuid::from(*self).serialize(serializer) 41 } 42 } 43 44 impl Serialize for Hyphenated { serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>45 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { 46 serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer())) 47 } 48 } 49 50 impl Serialize for Simple { serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>51 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { 52 serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer())) 53 } 54 } 55 56 impl Serialize for Urn { serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>57 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { 58 serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer())) 59 } 60 } 61 62 impl Serialize for Braced { serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>63 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { 64 serializer.serialize_str(self.encode_lower(&mut Uuid::encode_buffer())) 65 } 66 } 67 68 impl<'de> Deserialize<'de> for Uuid { deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error>69 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { 70 fn de_error<E: de::Error>(e: Error) -> E { 71 E::custom(format_args!("UUID parsing failed: {}", e)) 72 } 73 74 if deserializer.is_human_readable() { 75 struct UuidVisitor; 76 77 impl<'vi> de::Visitor<'vi> for UuidVisitor { 78 type Value = Uuid; 79 80 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { 81 write!(formatter, "a UUID string") 82 } 83 84 fn visit_str<E: de::Error>(self, value: &str) -> Result<Uuid, E> { 85 value.parse::<Uuid>().map_err(de_error) 86 } 87 88 fn visit_bytes<E: de::Error>(self, value: &[u8]) -> Result<Uuid, E> { 89 Uuid::from_slice(value).map_err(de_error) 90 } 91 92 fn visit_seq<A>(self, mut seq: A) -> Result<Uuid, A::Error> 93 where 94 A: de::SeqAccess<'vi>, 95 { 96 #[rustfmt::skip] 97 let bytes = [ 98 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(0, &self)) }, 99 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(1, &self)) }, 100 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(2, &self)) }, 101 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(3, &self)) }, 102 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(4, &self)) }, 103 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(5, &self)) }, 104 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(6, &self)) }, 105 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(7, &self)) }, 106 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(8, &self)) }, 107 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(9, &self)) }, 108 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(10, &self)) }, 109 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(11, &self)) }, 110 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(12, &self)) }, 111 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(13, &self)) }, 112 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(14, &self)) }, 113 match seq.next_element()? { Some(e) => e, None => return Err(A::Error::invalid_length(15, &self)) }, 114 ]; 115 116 Ok(Uuid::from_bytes(bytes)) 117 } 118 } 119 120 deserializer.deserialize_str(UuidVisitor) 121 } else { 122 struct UuidBytesVisitor; 123 124 impl<'vi> de::Visitor<'vi> for UuidBytesVisitor { 125 type Value = Uuid; 126 127 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { 128 write!(formatter, "bytes") 129 } 130 131 fn visit_bytes<E: de::Error>(self, value: &[u8]) -> Result<Uuid, E> { 132 Uuid::from_slice(value).map_err(de_error) 133 } 134 } 135 136 deserializer.deserialize_bytes(UuidBytesVisitor) 137 } 138 } 139 } 140 141 impl<'de> Deserialize<'de> for NonNilUuid { deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de>,142 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 143 where 144 D: serde::Deserializer<'de>, 145 { 146 let uuid = Uuid::deserialize(deserializer)?; 147 148 NonNilUuid::try_from(uuid).map_err(|_| de::Error::invalid_value(de::Unexpected::Other("nil UUID"), &"a non-nil UUID")) 149 } 150 } 151 152 enum ExpectedFormat { 153 Simple, 154 Braced, 155 Urn, 156 } 157 158 impl std::fmt::Display for ExpectedFormat { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result159 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 160 let s = match self { 161 ExpectedFormat::Simple => "a simple Uuid string like 67e5504410b1426f9247bb680e5fe0c8", 162 ExpectedFormat::Braced => { 163 "a braced Uuid string like {67e55044-10b1-426f-9247-bb680e5fe0c8}" 164 } 165 ExpectedFormat::Urn => { 166 "a URN Uuid string like urn:uuid:67e55044-10b1-426f-9247-bb680e5fe0c8" 167 } 168 }; 169 f.write_str(s) 170 } 171 } 172 173 impl de::Expected for ExpectedFormat { fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result174 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 175 <ExpectedFormat as std::fmt::Display>::fmt(self, formatter) 176 } 177 } 178 179 pub mod compact { 180 //! Serialize a [`Uuid`] as a `[u8; 16]`. 181 //! 182 //! [`Uuid`]: ../../struct.Uuid.html 183 184 /// Serialize from a [`Uuid`] as a `[u8; 16]` 185 /// 186 /// [`Uuid`]: ../../struct.Uuid.html serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer,187 pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error> 188 where 189 S: serde::Serializer, 190 { 191 serde::Serialize::serialize(u.as_bytes(), serializer) 192 } 193 194 /// Deserialize a `[u8; 16]` as a [`Uuid`] 195 /// 196 /// [`Uuid`]: ../../struct.Uuid.html deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error> where D: serde::Deserializer<'de>,197 pub fn deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error> 198 where 199 D: serde::Deserializer<'de>, 200 { 201 let bytes: [u8; 16] = serde::Deserialize::deserialize(deserializer)?; 202 203 Ok(crate::Uuid::from_bytes(bytes)) 204 } 205 206 #[cfg(test)] 207 mod tests { 208 use serde_derive::*; 209 use serde_test::Configure; 210 211 #[test] test_serialize_compact()212 fn test_serialize_compact() { 213 #[derive(Serialize, Debug, Deserialize, PartialEq)] 214 struct UuidContainer { 215 #[serde(with = "crate::serde::compact")] 216 u: crate::Uuid, 217 } 218 219 let uuid_bytes = b"F9168C5E-CEB2-4F"; 220 let container = UuidContainer { 221 u: crate::Uuid::from_slice(uuid_bytes).unwrap(), 222 }; 223 224 // more complex because of the struct wrapping the actual UUID 225 // serialization 226 serde_test::assert_tokens( 227 &container.compact(), 228 &[ 229 serde_test::Token::Struct { 230 name: "UuidContainer", 231 len: 1, 232 }, 233 serde_test::Token::Str("u"), 234 serde_test::Token::Tuple { len: 16 }, 235 serde_test::Token::U8(uuid_bytes[0]), 236 serde_test::Token::U8(uuid_bytes[1]), 237 serde_test::Token::U8(uuid_bytes[2]), 238 serde_test::Token::U8(uuid_bytes[3]), 239 serde_test::Token::U8(uuid_bytes[4]), 240 serde_test::Token::U8(uuid_bytes[5]), 241 serde_test::Token::U8(uuid_bytes[6]), 242 serde_test::Token::U8(uuid_bytes[7]), 243 serde_test::Token::U8(uuid_bytes[8]), 244 serde_test::Token::U8(uuid_bytes[9]), 245 serde_test::Token::U8(uuid_bytes[10]), 246 serde_test::Token::U8(uuid_bytes[11]), 247 serde_test::Token::U8(uuid_bytes[12]), 248 serde_test::Token::U8(uuid_bytes[13]), 249 serde_test::Token::U8(uuid_bytes[14]), 250 serde_test::Token::U8(uuid_bytes[15]), 251 serde_test::Token::TupleEnd, 252 serde_test::Token::StructEnd, 253 ], 254 ) 255 } 256 } 257 } 258 259 /// Serialize from a [`Uuid`] as a `uuid::fmt::Simple` 260 /// 261 /// [`Uuid`]: ../../struct.Uuid.html 262 /// 263 /// ## Example 264 /// 265 /// ```rust 266 /// #[derive(serde_derive::Serialize, serde_derive::Deserialize)] 267 /// struct StructA { 268 /// // This will change both serailization and deserialization 269 /// #[serde(with = "uuid::serde::simple")] 270 /// id: uuid::Uuid, 271 /// } 272 /// 273 /// #[derive(serde_derive::Serialize, serde_derive::Deserialize)] 274 /// struct StructB { 275 /// // This will be serialized as uuid::fmt::Simple and deserialize from all valid formats 276 /// #[serde(serialize_with = "uuid::serde::simple::serialize")] 277 /// id: uuid::Uuid, 278 /// } 279 /// ``` 280 pub mod simple { 281 use serde::{de, Deserialize}; 282 283 use crate::{parser::parse_simple, Uuid}; 284 285 use super::ExpectedFormat; 286 287 /// Serialize from a [`Uuid`] as a `uuid::fmt::Simple` 288 /// 289 /// [`Uuid`]: ../../struct.Uuid.html 290 /// 291 /// # Example 292 /// 293 /// ```rust 294 /// #[derive(serde_derive::Serialize)] 295 /// struct Struct { 296 /// // This will be serialize as uuid::fmt::Simple 297 /// #[serde(serialize_with = "uuid::serde::simple::serialize")] 298 /// id: uuid::Uuid, 299 /// } 300 /// 301 /// ``` serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer,302 pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error> 303 where 304 S: serde::Serializer, 305 { 306 serde::Serialize::serialize(u.as_simple(), serializer) 307 } 308 309 /// Deserialize a simple Uuid string as a [`Uuid`] 310 /// 311 /// [`Uuid`]: ../../struct.Uuid.html deserialize<'de, D>(deserializer: D) -> Result<Uuid, D::Error> where D: serde::Deserializer<'de>,312 pub fn deserialize<'de, D>(deserializer: D) -> Result<Uuid, D::Error> 313 where 314 D: serde::Deserializer<'de>, 315 { 316 let s = <&str as Deserialize>::deserialize(deserializer)?; 317 let bytes = parse_simple(s.as_bytes()).map_err(|_| { 318 de::Error::invalid_value(de::Unexpected::Str(s), &ExpectedFormat::Simple) 319 })?; 320 Ok(Uuid::from_bytes(bytes)) 321 } 322 323 #[cfg(test)] 324 mod tests { 325 use serde::de::{self, Error}; 326 use serde_test::{Readable, Token}; 327 328 use crate::{external::serde_support::ExpectedFormat, Uuid}; 329 330 const HYPHENATED_UUID_STR: &'static str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4"; 331 const SIMPLE_UUID_STR: &'static str = "f9168c5eceb24faab6bf329bf39fa1e4"; 332 333 #[test] test_serialize_as_simple()334 fn test_serialize_as_simple() { 335 #[derive(serde_derive::Serialize)] 336 struct Struct(#[serde(with = "super")] crate::Uuid); 337 338 let u = Struct(Uuid::parse_str(HYPHENATED_UUID_STR).unwrap()); 339 serde_test::assert_ser_tokens( 340 &u, 341 &[ 342 Token::NewtypeStruct { name: "Struct" }, 343 Token::Str(SIMPLE_UUID_STR), 344 ], 345 ); 346 } 347 348 #[test] test_de_from_simple()349 fn test_de_from_simple() { 350 #[derive(PartialEq, Debug, serde_derive::Deserialize)] 351 struct Struct(#[serde(with = "super")] crate::Uuid); 352 let s = Struct(HYPHENATED_UUID_STR.parse().unwrap()); 353 serde_test::assert_de_tokens::<Struct>( 354 &s, 355 &[ 356 Token::TupleStruct { 357 name: "Struct", 358 len: 1, 359 }, 360 Token::BorrowedStr(SIMPLE_UUID_STR), 361 Token::TupleStructEnd, 362 ], 363 ); 364 } 365 366 #[test] test_de_reject_hypenated()367 fn test_de_reject_hypenated() { 368 #[derive(PartialEq, Debug, serde_derive::Deserialize)] 369 struct Struct(#[serde(with = "super")] crate::Uuid); 370 serde_test::assert_de_tokens_error::<Readable<Struct>>( 371 &[ 372 Token::TupleStruct { 373 name: "Struct", 374 len: 1, 375 }, 376 Token::BorrowedStr(HYPHENATED_UUID_STR), 377 Token::TupleStructEnd, 378 ], 379 &format!( 380 "{}", 381 de::value::Error::invalid_value( 382 de::Unexpected::Str(HYPHENATED_UUID_STR), 383 &ExpectedFormat::Simple, 384 ) 385 ), 386 ); 387 } 388 } 389 } 390 391 /// Serialize from a [`Uuid`] as a `uuid::fmt::Braced` 392 /// 393 /// [`Uuid`]: ../../struct.Uuid.html 394 /// 395 /// ## Example 396 /// 397 /// ```rust 398 /// #[derive(serde_derive::Serialize, serde_derive::Deserialize)] 399 /// struct StructA { 400 /// // This will change both serailization and deserialization 401 /// #[serde(with = "uuid::serde::braced")] 402 /// id: uuid::Uuid, 403 /// } 404 /// 405 /// #[derive(serde_derive::Serialize, serde_derive::Deserialize)] 406 /// struct StructB { 407 /// // This will be serialized as uuid::fmt::Urn and deserialize from all valid formats 408 /// #[serde(serialize_with = "uuid::serde::braced::serialize")] 409 /// id: uuid::Uuid, 410 /// } 411 /// ``` 412 pub mod braced { 413 use serde::{de, Deserialize}; 414 415 use crate::parser::parse_braced; 416 417 use super::ExpectedFormat; 418 419 /// Serialize from a [`Uuid`] as a `uuid::fmt::Braced` 420 /// 421 /// [`Uuid`]: ../../struct.Uuid.html 422 /// 423 /// # Example 424 /// 425 /// ```rust 426 /// #[derive(serde_derive::Serialize)] 427 /// struct Struct { 428 /// // This will be serialize as uuid::fmt::Braced 429 /// #[serde(serialize_with = "uuid::serde::braced::serialize")] 430 /// id: uuid::Uuid, 431 /// } 432 /// 433 /// ``` serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer,434 pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error> 435 where 436 S: serde::Serializer, 437 { 438 serde::Serialize::serialize(u.as_braced(), serializer) 439 } 440 441 /// Deserialize a braced Uuid string as a [`Uuid`] 442 /// 443 /// [`Uuid`]: ../../struct.Uuid.html deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error> where D: serde::Deserializer<'de>,444 pub fn deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error> 445 where 446 D: serde::Deserializer<'de>, 447 { 448 let s = <&str as Deserialize>::deserialize(deserializer)?; 449 let bytes = parse_braced(s.as_bytes()).map_err(|_| { 450 de::Error::invalid_value(de::Unexpected::Str(s), &ExpectedFormat::Braced) 451 })?; 452 Ok(crate::Uuid::from_bytes(bytes)) 453 } 454 455 #[cfg(test)] 456 mod tests { 457 use serde::de::{self, Error}; 458 use serde_test::{Readable, Token}; 459 460 use crate::{external::serde_support::ExpectedFormat, Uuid}; 461 462 const HYPHENATED_UUID_STR: &'static str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4"; 463 const BRACED_UUID_STR: &'static str = "{f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4}"; 464 465 #[test] test_serialize_as_braced()466 fn test_serialize_as_braced() { 467 #[derive(serde_derive::Serialize)] 468 struct Struct(#[serde(with = "super")] crate::Uuid); 469 470 let u = Struct(Uuid::parse_str(HYPHENATED_UUID_STR).unwrap()); 471 serde_test::assert_ser_tokens( 472 &u, 473 &[ 474 Token::NewtypeStruct { name: "Struct" }, 475 Token::Str(BRACED_UUID_STR), 476 ], 477 ); 478 } 479 480 #[test] test_de_from_braced()481 fn test_de_from_braced() { 482 #[derive(PartialEq, Debug, serde_derive::Deserialize)] 483 struct Struct(#[serde(with = "super")] crate::Uuid); 484 let s = Struct(HYPHENATED_UUID_STR.parse().unwrap()); 485 serde_test::assert_de_tokens::<Struct>( 486 &s, 487 &[ 488 Token::TupleStruct { 489 name: "Struct", 490 len: 1, 491 }, 492 Token::BorrowedStr(BRACED_UUID_STR), 493 Token::TupleStructEnd, 494 ], 495 ); 496 } 497 498 #[test] test_de_reject_hypenated()499 fn test_de_reject_hypenated() { 500 #[derive(PartialEq, Debug, serde_derive::Deserialize)] 501 struct Struct(#[serde(with = "super")] crate::Uuid); 502 serde_test::assert_de_tokens_error::<Readable<Struct>>( 503 &[ 504 Token::TupleStruct { 505 name: "Struct", 506 len: 1, 507 }, 508 Token::BorrowedStr(HYPHENATED_UUID_STR), 509 Token::TupleStructEnd, 510 ], 511 &format!( 512 "{}", 513 de::value::Error::invalid_value( 514 de::Unexpected::Str(HYPHENATED_UUID_STR), 515 &ExpectedFormat::Braced, 516 ) 517 ), 518 ); 519 } 520 } 521 } 522 523 /// Serialize from a [`Uuid`] as a `uuid::fmt::Urn` 524 /// 525 /// [`Uuid`]: ../../struct.Uuid.html 526 /// 527 /// ## Example 528 /// 529 /// ```rust 530 /// #[derive(serde_derive::Serialize, serde_derive::Deserialize)] 531 /// struct StructA { 532 /// // This will change both serailization and deserialization 533 /// #[serde(with = "uuid::serde::urn")] 534 /// id: uuid::Uuid, 535 /// } 536 /// 537 /// #[derive(serde_derive::Serialize, serde_derive::Deserialize)] 538 /// struct StructB { 539 /// // This will be serialized as uuid::fmt::Urn and deserialize from all valid formats 540 /// #[serde(serialize_with = "uuid::serde::urn::serialize")] 541 /// id: uuid::Uuid, 542 /// } 543 /// ``` 544 pub mod urn { 545 use serde::{de, Deserialize}; 546 547 use crate::parser::parse_urn; 548 549 use super::ExpectedFormat; 550 551 /// Serialize from a [`Uuid`] as a `uuid::fmt::Urn` 552 /// 553 /// [`Uuid`]: ../../struct.Uuid.html 554 /// 555 /// # Example 556 /// 557 /// ```rust 558 /// #[derive(serde_derive::Serialize)] 559 /// struct Struct { 560 /// // This will be serialize as uuid::fmt::Urn 561 /// #[serde(serialize_with = "uuid::serde::urn::serialize")] 562 /// id: uuid::Uuid, 563 /// } 564 /// 565 /// ``` serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer,566 pub fn serialize<S>(u: &crate::Uuid, serializer: S) -> Result<S::Ok, S::Error> 567 where 568 S: serde::Serializer, 569 { 570 serde::Serialize::serialize(u.as_urn(), serializer) 571 } 572 573 /// Deserialize a urn Uuid string as a [`Uuid`] 574 /// 575 /// [`Uuid`]: ../../struct.Uuid.html deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error> where D: serde::Deserializer<'de>,576 pub fn deserialize<'de, D>(deserializer: D) -> Result<crate::Uuid, D::Error> 577 where 578 D: serde::Deserializer<'de>, 579 { 580 let s = <&str as Deserialize>::deserialize(deserializer)?; 581 let bytes = parse_urn(s.as_bytes()) 582 .map_err(|_| de::Error::invalid_value(de::Unexpected::Str(s), &ExpectedFormat::Urn))?; 583 Ok(crate::Uuid::from_bytes(bytes)) 584 } 585 586 #[cfg(test)] 587 mod tests { 588 use serde::de::{self, Error}; 589 use serde_test::{Readable, Token}; 590 591 use crate::{external::serde_support::ExpectedFormat, Uuid}; 592 593 const HYPHENATED_UUID_STR: &'static str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4"; 594 const URN_UUID_STR: &'static str = "urn:uuid:f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4"; 595 596 #[test] test_serialize_as_urn()597 fn test_serialize_as_urn() { 598 #[derive(serde_derive::Serialize)] 599 struct Struct(#[serde(with = "super")] crate::Uuid); 600 601 let u = Struct(Uuid::parse_str(HYPHENATED_UUID_STR).unwrap()); 602 serde_test::assert_ser_tokens( 603 &u, 604 &[ 605 Token::NewtypeStruct { name: "Struct" }, 606 Token::Str(URN_UUID_STR), 607 ], 608 ); 609 } 610 611 #[test] test_de_from_urn()612 fn test_de_from_urn() { 613 #[derive(PartialEq, Debug, serde_derive::Deserialize)] 614 struct Struct(#[serde(with = "super")] crate::Uuid); 615 let s = Struct(HYPHENATED_UUID_STR.parse().unwrap()); 616 serde_test::assert_de_tokens::<Struct>( 617 &s, 618 &[ 619 Token::TupleStruct { 620 name: "Struct", 621 len: 1, 622 }, 623 Token::BorrowedStr(URN_UUID_STR), 624 Token::TupleStructEnd, 625 ], 626 ); 627 } 628 629 #[test] test_de_reject_hypenated()630 fn test_de_reject_hypenated() { 631 #[derive(PartialEq, Debug, serde_derive::Deserialize)] 632 struct Struct(#[serde(with = "super")] crate::Uuid); 633 serde_test::assert_de_tokens_error::<Readable<Struct>>( 634 &[ 635 Token::TupleStruct { 636 name: "Struct", 637 len: 1, 638 }, 639 Token::BorrowedStr(HYPHENATED_UUID_STR), 640 Token::TupleStructEnd, 641 ], 642 &format!( 643 "{}", 644 de::value::Error::invalid_value( 645 de::Unexpected::Str(HYPHENATED_UUID_STR), 646 &ExpectedFormat::Urn, 647 ) 648 ), 649 ); 650 } 651 } 652 } 653 654 #[cfg(test)] 655 mod serde_tests { 656 use super::*; 657 658 use serde_test::{Compact, Configure, Readable, Token}; 659 660 #[test] test_serialize_readable_string()661 fn test_serialize_readable_string() { 662 let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4"; 663 let u = Uuid::parse_str(uuid_str).unwrap(); 664 serde_test::assert_tokens(&u.readable(), &[Token::Str(uuid_str)]); 665 } 666 667 #[test] test_deserialize_readable_compact()668 fn test_deserialize_readable_compact() { 669 let uuid_bytes = b"F9168C5E-CEB2-4F"; 670 let u = Uuid::from_slice(uuid_bytes).unwrap(); 671 672 serde_test::assert_de_tokens( 673 &u.readable(), 674 &[ 675 serde_test::Token::Tuple { len: 16 }, 676 serde_test::Token::U8(uuid_bytes[0]), 677 serde_test::Token::U8(uuid_bytes[1]), 678 serde_test::Token::U8(uuid_bytes[2]), 679 serde_test::Token::U8(uuid_bytes[3]), 680 serde_test::Token::U8(uuid_bytes[4]), 681 serde_test::Token::U8(uuid_bytes[5]), 682 serde_test::Token::U8(uuid_bytes[6]), 683 serde_test::Token::U8(uuid_bytes[7]), 684 serde_test::Token::U8(uuid_bytes[8]), 685 serde_test::Token::U8(uuid_bytes[9]), 686 serde_test::Token::U8(uuid_bytes[10]), 687 serde_test::Token::U8(uuid_bytes[11]), 688 serde_test::Token::U8(uuid_bytes[12]), 689 serde_test::Token::U8(uuid_bytes[13]), 690 serde_test::Token::U8(uuid_bytes[14]), 691 serde_test::Token::U8(uuid_bytes[15]), 692 serde_test::Token::TupleEnd, 693 ], 694 ); 695 } 696 697 #[test] test_deserialize_readable_bytes()698 fn test_deserialize_readable_bytes() { 699 let uuid_bytes = b"F9168C5E-CEB2-4F"; 700 let u = Uuid::from_slice(uuid_bytes).unwrap(); 701 702 serde_test::assert_de_tokens(&u.readable(), &[serde_test::Token::Bytes(uuid_bytes)]); 703 } 704 705 #[test] test_serialize_hyphenated()706 fn test_serialize_hyphenated() { 707 let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4"; 708 let u = Uuid::parse_str(uuid_str).unwrap(); 709 serde_test::assert_ser_tokens(&u.hyphenated(), &[Token::Str(uuid_str)]); 710 } 711 712 #[test] test_serialize_simple()713 fn test_serialize_simple() { 714 let uuid_str = "f9168c5eceb24faab6bf329bf39fa1e4"; 715 let u = Uuid::parse_str(uuid_str).unwrap(); 716 serde_test::assert_ser_tokens(&u.simple(), &[Token::Str(uuid_str)]); 717 } 718 719 #[test] test_serialize_urn()720 fn test_serialize_urn() { 721 let uuid_str = "urn:uuid:f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4"; 722 let u = Uuid::parse_str(uuid_str).unwrap(); 723 serde_test::assert_ser_tokens(&u.urn(), &[Token::Str(uuid_str)]); 724 } 725 726 #[test] test_serialize_braced()727 fn test_serialize_braced() { 728 let uuid_str = "{f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4}"; 729 let u = Uuid::parse_str(uuid_str).unwrap(); 730 serde_test::assert_ser_tokens(&u.braced(), &[Token::Str(uuid_str)]); 731 } 732 733 #[test] test_serialize_non_human_readable()734 fn test_serialize_non_human_readable() { 735 let uuid_bytes = b"F9168C5E-CEB2-4F"; 736 let u = Uuid::from_slice(uuid_bytes).unwrap(); 737 serde_test::assert_tokens( 738 &u.compact(), 739 &[serde_test::Token::Bytes(&[ 740 70, 57, 49, 54, 56, 67, 53, 69, 45, 67, 69, 66, 50, 45, 52, 70, 741 ])], 742 ); 743 } 744 745 #[test] test_de_failure()746 fn test_de_failure() { 747 serde_test::assert_de_tokens_error::<Readable<Uuid>>( 748 &[Token::Str("hello_world")], 749 "UUID parsing failed: invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-fA-F-], found `h` at 1", 750 ); 751 752 serde_test::assert_de_tokens_error::<Compact<Uuid>>( 753 &[Token::Bytes(b"hello_world")], 754 "UUID parsing failed: invalid length: expected 16 bytes, found 11", 755 ); 756 } 757 758 #[test] test_serde_non_nil_uuid()759 fn test_serde_non_nil_uuid() { 760 let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4"; 761 let uuid = Uuid::parse_str(uuid_str).unwrap(); 762 let non_nil_uuid = NonNilUuid::try_from(uuid).unwrap(); 763 764 serde_test::assert_ser_tokens(&non_nil_uuid.readable(), &[Token::Str(uuid_str)]); 765 serde_test::assert_de_tokens(&non_nil_uuid.readable(), &[Token::Str(uuid_str)]); 766 } 767 } 768