| 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 | //! [`Uuid`] parsing constructs and utilities. |
| 13 | //! |
| 14 | //! [`Uuid`]: ../struct.Uuid.html |
| 15 | |
| 16 | use crate::{ |
| 17 | error::*, |
| 18 | std::{convert::TryFrom, str}, |
| 19 | Uuid, |
| 20 | }; |
| 21 | |
| 22 | impl str::FromStr for Uuid { |
| 23 | type Err = Error; |
| 24 | |
| 25 | fn from_str(uuid_str: &str) -> Result<Self, Self::Err> { |
| 26 | Uuid::parse_str(input:uuid_str) |
| 27 | } |
| 28 | } |
| 29 | |
| 30 | impl TryFrom<&'_ str> for Uuid { |
| 31 | type Error = Error; |
| 32 | |
| 33 | fn try_from(uuid_str: &'_ str) -> Result<Self, Self::Error> { |
| 34 | Uuid::parse_str(input:uuid_str) |
| 35 | } |
| 36 | } |
| 37 | |
| 38 | impl Uuid { |
| 39 | /// Parses a `Uuid` from a string of hexadecimal digits with optional |
| 40 | /// hyphens. |
| 41 | /// |
| 42 | /// Any of the formats generated by this module (simple, hyphenated, urn, |
| 43 | /// Microsoft GUID) are supported by this parsing function. |
| 44 | /// |
| 45 | /// Prefer [`try_parse`] unless you need detailed user-facing diagnostics. |
| 46 | /// This method will be eventually deprecated in favor of `try_parse`. |
| 47 | /// |
| 48 | /// # Examples |
| 49 | /// |
| 50 | /// Parse a hyphenated UUID: |
| 51 | /// |
| 52 | /// ``` |
| 53 | /// # use uuid::{Uuid, Version, Variant}; |
| 54 | /// # fn main() -> Result<(), uuid::Error> { |
| 55 | /// let uuid = Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000" )?; |
| 56 | /// |
| 57 | /// assert_eq!(Some(Version::Random), uuid.get_version()); |
| 58 | /// assert_eq!(Variant::RFC4122, uuid.get_variant()); |
| 59 | /// # Ok(()) |
| 60 | /// # } |
| 61 | /// ``` |
| 62 | /// |
| 63 | /// [`try_parse`]: #method.try_parse |
| 64 | pub fn parse_str(input: &str) -> Result<Uuid, Error> { |
| 65 | try_parse(input.as_bytes()) |
| 66 | .map(Uuid::from_bytes) |
| 67 | .map_err(InvalidUuid::into_err) |
| 68 | } |
| 69 | |
| 70 | /// Parses a `Uuid` from a string of hexadecimal digits with optional |
| 71 | /// hyphens. |
| 72 | /// |
| 73 | /// This function is similar to [`parse_str`], in fact `parse_str` shares |
| 74 | /// the same underlying parser. The difference is that if `try_parse` |
| 75 | /// fails, it won't generate very useful error messages. The `parse_str` |
| 76 | /// function will eventually be deprecated in favor of `try_parse`. |
| 77 | /// |
| 78 | /// To parse a UUID from a byte stream instead of a UTF8 string, see |
| 79 | /// [`try_parse_ascii`]. |
| 80 | /// |
| 81 | /// # Examples |
| 82 | /// |
| 83 | /// Parse a hyphenated UUID: |
| 84 | /// |
| 85 | /// ``` |
| 86 | /// # use uuid::{Uuid, Version, Variant}; |
| 87 | /// # fn main() -> Result<(), uuid::Error> { |
| 88 | /// let uuid = Uuid::try_parse("550e8400-e29b-41d4-a716-446655440000" )?; |
| 89 | /// |
| 90 | /// assert_eq!(Some(Version::Random), uuid.get_version()); |
| 91 | /// assert_eq!(Variant::RFC4122, uuid.get_variant()); |
| 92 | /// # Ok(()) |
| 93 | /// # } |
| 94 | /// ``` |
| 95 | /// |
| 96 | /// [`parse_str`]: #method.parse_str |
| 97 | /// [`try_parse_ascii`]: #method.try_parse_ascii |
| 98 | pub const fn try_parse(input: &str) -> Result<Uuid, Error> { |
| 99 | Self::try_parse_ascii(input.as_bytes()) |
| 100 | } |
| 101 | |
| 102 | /// Parses a `Uuid` from a string of hexadecimal digits with optional |
| 103 | /// hyphens. |
| 104 | /// |
| 105 | /// The input is expected to be a string of ASCII characters. This method |
| 106 | /// can be more convenient than [`try_parse`] if the UUID is being |
| 107 | /// parsed from a byte stream instead of from a UTF8 string. |
| 108 | /// |
| 109 | /// # Examples |
| 110 | /// |
| 111 | /// Parse a hyphenated UUID: |
| 112 | /// |
| 113 | /// ``` |
| 114 | /// # use uuid::{Uuid, Version, Variant}; |
| 115 | /// # fn main() -> Result<(), uuid::Error> { |
| 116 | /// let uuid = Uuid::try_parse_ascii(b"550e8400-e29b-41d4-a716-446655440000" )?; |
| 117 | /// |
| 118 | /// assert_eq!(Some(Version::Random), uuid.get_version()); |
| 119 | /// assert_eq!(Variant::RFC4122, uuid.get_variant()); |
| 120 | /// # Ok(()) |
| 121 | /// # } |
| 122 | /// ``` |
| 123 | /// |
| 124 | /// [`try_parse`]: #method.try_parse |
| 125 | pub const fn try_parse_ascii(input: &[u8]) -> Result<Uuid, Error> { |
| 126 | match try_parse(input) { |
| 127 | Ok(bytes) => Ok(Uuid::from_bytes(bytes)), |
| 128 | // If parsing fails then we don't know exactly what went wrong |
| 129 | // In this case, we just return a generic error |
| 130 | Err(_) => Err(Error(ErrorKind::Other)), |
| 131 | } |
| 132 | } |
| 133 | } |
| 134 | |
| 135 | const fn try_parse(input: &[u8]) -> Result<[u8; 16], InvalidUuid> { |
| 136 | match (input.len(), input) { |
| 137 | // Inputs of 32 bytes must be a non-hyphenated UUID |
| 138 | (32, s: &[u8]) => parse_simple(s), |
| 139 | // Hyphenated UUIDs may be wrapped in various ways: |
| 140 | // - `{UUID}` for braced UUIDs |
| 141 | // - `urn:uuid:UUID` for URNs |
| 142 | // - `UUID` for a regular hyphenated UUID |
| 143 | (36, s: &[u8]) |
| 144 | | (38, [b'{' , s: &[u8] @ .., b'}' ]) |
| 145 | | (45, [b'u' , b'r' , b'n' , b':' , b'u' , b'u' , b'i' , b'd' , b':' , s: &[u8] @ ..]) => { |
| 146 | parse_hyphenated(s) |
| 147 | } |
| 148 | // Any other shaped input is immediately invalid |
| 149 | _ => Err(InvalidUuid(input)), |
| 150 | } |
| 151 | } |
| 152 | |
| 153 | #[inline ] |
| 154 | #[allow (dead_code)] |
| 155 | pub(crate) const fn parse_braced(input: &[u8]) -> Result<[u8; 16], InvalidUuid> { |
| 156 | if let (38, [b'{' , s: &[u8] @ .., b'}' ]) = (input.len(), input) { |
| 157 | parse_hyphenated(s) |
| 158 | } else { |
| 159 | Err(InvalidUuid(input)) |
| 160 | } |
| 161 | } |
| 162 | |
| 163 | #[inline ] |
| 164 | #[allow (dead_code)] |
| 165 | pub(crate) const fn parse_urn(input: &[u8]) -> Result<[u8; 16], InvalidUuid> { |
| 166 | if let (45, [b'u' , b'r' , b'n' , b':' , b'u' , b'u' , b'i' , b'd' , b':' , s: &[u8] @ ..]) = |
| 167 | (input.len(), input) |
| 168 | { |
| 169 | parse_hyphenated(s) |
| 170 | } else { |
| 171 | Err(InvalidUuid(input)) |
| 172 | } |
| 173 | } |
| 174 | |
| 175 | #[inline ] |
| 176 | pub(crate) const fn parse_simple(s: &[u8]) -> Result<[u8; 16], InvalidUuid> { |
| 177 | // This length check here removes all other bounds |
| 178 | // checks in this function |
| 179 | if s.len() != 32 { |
| 180 | return Err(InvalidUuid(s)); |
| 181 | } |
| 182 | |
| 183 | let mut buf: [u8; 16] = [0; 16]; |
| 184 | let mut i = 0; |
| 185 | |
| 186 | while i < 16 { |
| 187 | // Convert a two-char hex value (like `A8`) |
| 188 | // into a byte (like `10101000`) |
| 189 | let h1 = HEX_TABLE[s[i * 2] as usize]; |
| 190 | let h2 = HEX_TABLE[s[i * 2 + 1] as usize]; |
| 191 | |
| 192 | // We use `0xff` as a sentinel value to indicate |
| 193 | // an invalid hex character sequence (like the letter `G`) |
| 194 | if h1 | h2 == 0xff { |
| 195 | return Err(InvalidUuid(s)); |
| 196 | } |
| 197 | |
| 198 | // The upper nibble needs to be shifted into position |
| 199 | // to produce the final byte value |
| 200 | buf[i] = SHL4_TABLE[h1 as usize] | h2; |
| 201 | i += 1; |
| 202 | } |
| 203 | |
| 204 | Ok(buf) |
| 205 | } |
| 206 | |
| 207 | #[inline ] |
| 208 | const fn parse_hyphenated(s: &[u8]) -> Result<[u8; 16], InvalidUuid> { |
| 209 | // This length check here removes all other bounds |
| 210 | // checks in this function |
| 211 | if s.len() != 36 { |
| 212 | return Err(InvalidUuid(s)); |
| 213 | } |
| 214 | |
| 215 | // We look at two hex-encoded values (4 chars) at a time because |
| 216 | // that's the size of the smallest group in a hyphenated UUID. |
| 217 | // The indexes we're interested in are: |
| 218 | // |
| 219 | // uuid : 936da01f-9abd-4d9d-80c7-02af85c822a8 |
| 220 | // | | || || || || | | |
| 221 | // hyphens : | | 8| 13| 18| 23| | | |
| 222 | // positions: 0 4 9 14 19 24 28 32 |
| 223 | |
| 224 | // First, ensure the hyphens appear in the right places |
| 225 | match [s[8], s[13], s[18], s[23]] { |
| 226 | [b'-' , b'-' , b'-' , b'-' ] => {} |
| 227 | _ => return Err(InvalidUuid(s)), |
| 228 | } |
| 229 | |
| 230 | let positions: [u8; 8] = [0, 4, 9, 14, 19, 24, 28, 32]; |
| 231 | let mut buf: [u8; 16] = [0; 16]; |
| 232 | let mut j = 0; |
| 233 | |
| 234 | while j < 8 { |
| 235 | let i = positions[j]; |
| 236 | |
| 237 | // The decoding here is the same as the simple case |
| 238 | // We're just dealing with two values instead of one |
| 239 | let h1 = HEX_TABLE[s[i as usize] as usize]; |
| 240 | let h2 = HEX_TABLE[s[(i + 1) as usize] as usize]; |
| 241 | let h3 = HEX_TABLE[s[(i + 2) as usize] as usize]; |
| 242 | let h4 = HEX_TABLE[s[(i + 3) as usize] as usize]; |
| 243 | |
| 244 | if h1 | h2 | h3 | h4 == 0xff { |
| 245 | return Err(InvalidUuid(s)); |
| 246 | } |
| 247 | |
| 248 | buf[j * 2] = SHL4_TABLE[h1 as usize] | h2; |
| 249 | buf[j * 2 + 1] = SHL4_TABLE[h3 as usize] | h4; |
| 250 | j += 1; |
| 251 | } |
| 252 | |
| 253 | Ok(buf) |
| 254 | } |
| 255 | |
| 256 | const HEX_TABLE: &[u8; 256] = &{ |
| 257 | let mut buf: [u8; 256] = [0; 256]; |
| 258 | let mut i: u8 = 0; |
| 259 | |
| 260 | loop { |
| 261 | buf[i as usize] = match i { |
| 262 | b'0' ..=b'9' => i - b'0' , |
| 263 | b'a' ..=b'f' => i - b'a' + 10, |
| 264 | b'A' ..=b'F' => i - b'A' + 10, |
| 265 | _ => 0xff, |
| 266 | }; |
| 267 | |
| 268 | if i == 255 { |
| 269 | break buf; |
| 270 | } |
| 271 | |
| 272 | i += 1 |
| 273 | } |
| 274 | }; |
| 275 | |
| 276 | const SHL4_TABLE: &[u8; 256] = &{ |
| 277 | let mut buf: [u8; 256] = [0; 256]; |
| 278 | let mut i: u8 = 0; |
| 279 | |
| 280 | loop { |
| 281 | buf[i as usize] = i.wrapping_shl(4); |
| 282 | |
| 283 | if i == 255 { |
| 284 | break buf; |
| 285 | } |
| 286 | |
| 287 | i += 1; |
| 288 | } |
| 289 | }; |
| 290 | |
| 291 | #[cfg (test)] |
| 292 | mod tests { |
| 293 | use super::*; |
| 294 | use crate::{std::string::ToString, tests::new}; |
| 295 | |
| 296 | #[test ] |
| 297 | fn test_parse_uuid_v4_valid() { |
| 298 | let from_hyphenated = Uuid::parse_str("67e55044-10b1-426f-9247-bb680e5fe0c8" ).unwrap(); |
| 299 | let from_simple = Uuid::parse_str("67e5504410b1426f9247bb680e5fe0c8" ).unwrap(); |
| 300 | let from_urn = Uuid::parse_str("urn:uuid:67e55044-10b1-426f-9247-bb680e5fe0c8" ).unwrap(); |
| 301 | let from_guid = Uuid::parse_str("{67e55044-10b1-426f-9247-bb680e5fe0c8}" ).unwrap(); |
| 302 | |
| 303 | assert_eq!(from_hyphenated, from_simple); |
| 304 | assert_eq!(from_hyphenated, from_urn); |
| 305 | assert_eq!(from_hyphenated, from_guid); |
| 306 | |
| 307 | assert!(Uuid::parse_str("00000000000000000000000000000000" ).is_ok()); |
| 308 | assert!(Uuid::parse_str("67e55044-10b1-426f-9247-bb680e5fe0c8" ).is_ok()); |
| 309 | assert!(Uuid::parse_str("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4" ).is_ok()); |
| 310 | assert!(Uuid::parse_str("67e5504410b1426f9247bb680e5fe0c8" ).is_ok()); |
| 311 | assert!(Uuid::parse_str("01020304-1112-2122-3132-414243444546" ).is_ok()); |
| 312 | assert!(Uuid::parse_str("urn:uuid:67e55044-10b1-426f-9247-bb680e5fe0c8" ).is_ok()); |
| 313 | assert!(Uuid::parse_str("{6d93bade-bd9f-4e13-8914-9474e1e3567b}" ).is_ok()); |
| 314 | |
| 315 | // Nil |
| 316 | let nil = Uuid::nil(); |
| 317 | assert_eq!( |
| 318 | Uuid::parse_str("00000000000000000000000000000000" ).unwrap(), |
| 319 | nil |
| 320 | ); |
| 321 | assert_eq!( |
| 322 | Uuid::parse_str("00000000-0000-0000-0000-000000000000" ).unwrap(), |
| 323 | nil |
| 324 | ); |
| 325 | } |
| 326 | |
| 327 | #[test ] |
| 328 | fn test_parse_uuid_v4_invalid() { |
| 329 | // Invalid |
| 330 | assert_eq!( |
| 331 | Uuid::parse_str("" ), |
| 332 | Err(Error(ErrorKind::SimpleLength { len: 0 })) |
| 333 | ); |
| 334 | |
| 335 | assert_eq!( |
| 336 | Uuid::parse_str("!" ), |
| 337 | Err(Error(ErrorKind::Char { |
| 338 | character: '!' , |
| 339 | index: 1, |
| 340 | })) |
| 341 | ); |
| 342 | |
| 343 | assert_eq!( |
| 344 | Uuid::parse_str("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E45" ), |
| 345 | Err(Error(ErrorKind::GroupLength { |
| 346 | group: 4, |
| 347 | len: 13, |
| 348 | index: 25, |
| 349 | })) |
| 350 | ); |
| 351 | |
| 352 | assert_eq!( |
| 353 | Uuid::parse_str("F9168C5E-CEB2-4faa-BBF-329BF39FA1E4" ), |
| 354 | Err(Error(ErrorKind::GroupLength { |
| 355 | group: 3, |
| 356 | len: 3, |
| 357 | index: 20, |
| 358 | })) |
| 359 | ); |
| 360 | |
| 361 | assert_eq!( |
| 362 | Uuid::parse_str("F9168C5E-CEB2-4faa-BGBF-329BF39FA1E4" ), |
| 363 | Err(Error(ErrorKind::Char { |
| 364 | character: 'G' , |
| 365 | index: 21, |
| 366 | })) |
| 367 | ); |
| 368 | |
| 369 | assert_eq!( |
| 370 | Uuid::parse_str("F9168C5E-CEB2F4faaFB6BFF329BF39FA1E4" ), |
| 371 | Err(Error(ErrorKind::GroupCount { count: 2 })) |
| 372 | ); |
| 373 | |
| 374 | assert_eq!( |
| 375 | Uuid::parse_str("F9168C5E-CEB2-4faaFB6BFF329BF39FA1E4" ), |
| 376 | Err(Error(ErrorKind::GroupCount { count: 3 })) |
| 377 | ); |
| 378 | |
| 379 | assert_eq!( |
| 380 | Uuid::parse_str("F9168C5E-CEB2-4faa-B6BFF329BF39FA1E4" ), |
| 381 | Err(Error(ErrorKind::GroupCount { count: 4 })) |
| 382 | ); |
| 383 | |
| 384 | assert_eq!( |
| 385 | Uuid::parse_str("F9168C5E-CEB2-4faa" ), |
| 386 | Err(Error(ErrorKind::GroupCount { count: 3 })) |
| 387 | ); |
| 388 | |
| 389 | assert_eq!( |
| 390 | Uuid::parse_str("F9168C5E-CEB2-4faaXB6BFF329BF39FA1E4" ), |
| 391 | Err(Error(ErrorKind::Char { |
| 392 | character: 'X' , |
| 393 | index: 19, |
| 394 | })) |
| 395 | ); |
| 396 | |
| 397 | assert_eq!( |
| 398 | Uuid::parse_str("{F9168C5E-CEB2-4faa9B6BFF329BF39FA1E41" ), |
| 399 | Err(Error(ErrorKind::Char { |
| 400 | character: '{' , |
| 401 | index: 1, |
| 402 | })) |
| 403 | ); |
| 404 | |
| 405 | assert_eq!( |
| 406 | Uuid::parse_str("{F9168C5E-CEB2-4faa9B6BFF329BF39FA1E41}" ), |
| 407 | Err(Error(ErrorKind::GroupCount { count: 3 })) |
| 408 | ); |
| 409 | |
| 410 | assert_eq!( |
| 411 | Uuid::parse_str("F9168C5E-CEB-24fa-eB6BFF32-BF39FA1E4" ), |
| 412 | Err(Error(ErrorKind::GroupLength { |
| 413 | group: 1, |
| 414 | len: 3, |
| 415 | index: 10, |
| 416 | })) |
| 417 | ); |
| 418 | |
| 419 | // // (group, found, expecting) |
| 420 | // // |
| 421 | assert_eq!( |
| 422 | Uuid::parse_str("01020304-1112-2122-3132-41424344" ), |
| 423 | Err(Error(ErrorKind::GroupLength { |
| 424 | group: 4, |
| 425 | len: 8, |
| 426 | index: 25, |
| 427 | })) |
| 428 | ); |
| 429 | |
| 430 | assert_eq!( |
| 431 | Uuid::parse_str("67e5504410b1426f9247bb680e5fe0c" ), |
| 432 | Err(Error(ErrorKind::SimpleLength { len: 31 })) |
| 433 | ); |
| 434 | |
| 435 | assert_eq!( |
| 436 | Uuid::parse_str("67e5504410b1426f9247bb680e5fe0c88" ), |
| 437 | Err(Error(ErrorKind::SimpleLength { len: 33 })) |
| 438 | ); |
| 439 | |
| 440 | assert_eq!( |
| 441 | Uuid::parse_str("67e5504410b1426f9247bb680e5fe0cg8" ), |
| 442 | Err(Error(ErrorKind::Char { |
| 443 | character: 'g' , |
| 444 | index: 32, |
| 445 | })) |
| 446 | ); |
| 447 | |
| 448 | assert_eq!( |
| 449 | Uuid::parse_str("67e5504410b1426%9247bb680e5fe0c8" ), |
| 450 | Err(Error(ErrorKind::Char { |
| 451 | character: '%' , |
| 452 | index: 16, |
| 453 | })) |
| 454 | ); |
| 455 | |
| 456 | assert_eq!( |
| 457 | Uuid::parse_str("231231212212423424324323477343246663" ), |
| 458 | Err(Error(ErrorKind::SimpleLength { len: 36 })) |
| 459 | ); |
| 460 | |
| 461 | assert_eq!( |
| 462 | Uuid::parse_str("{00000000000000000000000000000000}" ), |
| 463 | Err(Error(ErrorKind::GroupCount { count: 1 })) |
| 464 | ); |
| 465 | |
| 466 | assert_eq!( |
| 467 | Uuid::parse_str("67e5504410b1426f9247bb680e5fe0c" ), |
| 468 | Err(Error(ErrorKind::SimpleLength { len: 31 })) |
| 469 | ); |
| 470 | |
| 471 | assert_eq!( |
| 472 | Uuid::parse_str("67e550X410b1426f9247bb680e5fe0cd" ), |
| 473 | Err(Error(ErrorKind::Char { |
| 474 | character: 'X' , |
| 475 | index: 7, |
| 476 | })) |
| 477 | ); |
| 478 | |
| 479 | assert_eq!( |
| 480 | Uuid::parse_str("67e550-4105b1426f9247bb680e5fe0c" ), |
| 481 | Err(Error(ErrorKind::GroupCount { count: 2 })) |
| 482 | ); |
| 483 | |
| 484 | assert_eq!( |
| 485 | Uuid::parse_str("F9168C5E-CEB2-4faa-B6BF1-02BF39FA1E4" ), |
| 486 | Err(Error(ErrorKind::GroupLength { |
| 487 | group: 3, |
| 488 | len: 5, |
| 489 | index: 20, |
| 490 | })) |
| 491 | ); |
| 492 | |
| 493 | assert_eq!( |
| 494 | Uuid::parse_str(" \u{bcf3c}" ), |
| 495 | Err(Error(ErrorKind::Char { |
| 496 | character: ' \u{bcf3c}' , |
| 497 | index: 1 |
| 498 | })) |
| 499 | ); |
| 500 | } |
| 501 | |
| 502 | #[test ] |
| 503 | fn test_roundtrip_default() { |
| 504 | let uuid_orig = new(); |
| 505 | let orig_str = uuid_orig.to_string(); |
| 506 | let uuid_out = Uuid::parse_str(&orig_str).unwrap(); |
| 507 | assert_eq!(uuid_orig, uuid_out); |
| 508 | } |
| 509 | |
| 510 | #[test ] |
| 511 | fn test_roundtrip_hyphenated() { |
| 512 | let uuid_orig = new(); |
| 513 | let orig_str = uuid_orig.hyphenated().to_string(); |
| 514 | let uuid_out = Uuid::parse_str(&orig_str).unwrap(); |
| 515 | assert_eq!(uuid_orig, uuid_out); |
| 516 | } |
| 517 | |
| 518 | #[test ] |
| 519 | fn test_roundtrip_simple() { |
| 520 | let uuid_orig = new(); |
| 521 | let orig_str = uuid_orig.simple().to_string(); |
| 522 | let uuid_out = Uuid::parse_str(&orig_str).unwrap(); |
| 523 | assert_eq!(uuid_orig, uuid_out); |
| 524 | } |
| 525 | |
| 526 | #[test ] |
| 527 | fn test_roundtrip_urn() { |
| 528 | let uuid_orig = new(); |
| 529 | let orig_str = uuid_orig.urn().to_string(); |
| 530 | let uuid_out = Uuid::parse_str(&orig_str).unwrap(); |
| 531 | assert_eq!(uuid_orig, uuid_out); |
| 532 | } |
| 533 | |
| 534 | #[test ] |
| 535 | fn test_roundtrip_braced() { |
| 536 | let uuid_orig = new(); |
| 537 | let orig_str = uuid_orig.braced().to_string(); |
| 538 | let uuid_out = Uuid::parse_str(&orig_str).unwrap(); |
| 539 | assert_eq!(uuid_orig, uuid_out); |
| 540 | } |
| 541 | |
| 542 | #[test ] |
| 543 | fn test_roundtrip_parse_urn() { |
| 544 | let uuid_orig = new(); |
| 545 | let orig_str = uuid_orig.urn().to_string(); |
| 546 | let uuid_out = Uuid::from_bytes(parse_urn(orig_str.as_bytes()).unwrap()); |
| 547 | assert_eq!(uuid_orig, uuid_out); |
| 548 | } |
| 549 | |
| 550 | #[test ] |
| 551 | fn test_roundtrip_parse_braced() { |
| 552 | let uuid_orig = new(); |
| 553 | let orig_str = uuid_orig.braced().to_string(); |
| 554 | let uuid_out = Uuid::from_bytes(parse_braced(orig_str.as_bytes()).unwrap()); |
| 555 | assert_eq!(uuid_orig, uuid_out); |
| 556 | } |
| 557 | |
| 558 | #[test ] |
| 559 | fn test_try_parse_ascii_non_utf8() { |
| 560 | assert!(Uuid::try_parse_ascii(b"67e55044-10b1-426f-9247-bb680e5 \0e0c8" ).is_err()); |
| 561 | } |
| 562 | } |
| 563 | |