diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:18:32 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:18:32 +0000 |
commit | 4547b622d8d29df964fa2914213088b148c498fc (patch) | |
tree | 9fc6b25f3c3add6b745be9a2400a6e96140046e9 /vendor/uuid/src/parser | |
parent | Releasing progress-linux version 1.66.0+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-4547b622d8d29df964fa2914213088b148c498fc.tar.xz rustc-4547b622d8d29df964fa2914213088b148c498fc.zip |
Merging upstream version 1.67.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/uuid/src/parser')
-rw-r--r-- | vendor/uuid/src/parser/error.rs | 149 | ||||
-rw-r--r-- | vendor/uuid/src/parser/mod.rs | 447 |
2 files changed, 596 insertions, 0 deletions
diff --git a/vendor/uuid/src/parser/error.rs b/vendor/uuid/src/parser/error.rs new file mode 100644 index 000000000..01d76e810 --- /dev/null +++ b/vendor/uuid/src/parser/error.rs @@ -0,0 +1,149 @@ +use crate::std::fmt;
+
+/// An error that can occur while parsing a [`Uuid`] string.
+///
+/// [`Uuid`]: ../struct.Uuid.html
+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+#[allow(clippy::enum_variant_names)]
+pub(crate) enum Error {
+ /// Invalid character in the [`Uuid`] string.
+ ///
+ /// [`Uuid`]: ../struct.Uuid.html
+ InvalidCharacter {
+ /// The expected characters.
+ expected: &'static str,
+ /// The invalid character found.
+ found: char,
+ /// The invalid character position.
+ index: usize,
+ /// Indicates the [`Uuid`] starts with `urn:uuid:`.
+ ///
+ /// This is a special case for [`Urn`] adapter parsing.
+ ///
+ /// [`Uuid`]: ../Uuid.html
+ urn: UrnPrefix,
+ },
+ /// Invalid number of segments in the [`Uuid`] string.
+ ///
+ /// [`Uuid`]: ../struct.Uuid.html
+ InvalidGroupCount {
+ /// The expected number of segments.
+ // TODO: explain multiple segment count.
+ // BODY: Parsers can expect a range of Uuid segment count.
+ // This needs to be expanded on.
+ expected: ExpectedLength,
+ /// The number of segments found.
+ found: usize,
+ },
+ /// Invalid length of a segment in a [`Uuid`] string.
+ ///
+ /// [`Uuid`]: ../struct.Uuid.html
+ InvalidGroupLength {
+ /// The expected length of the segment.
+ expected: ExpectedLength,
+ /// The length of segment found.
+ found: usize,
+ /// The segment with invalid length.
+ group: usize,
+ },
+ /// Invalid length of the [`Uuid`] string.
+ ///
+ /// [`Uuid`]: ../struct.Uuid.html
+ InvalidLength {
+ /// The expected length(s).
+ // TODO: explain multiple lengths.
+ // BODY: Parsers can expect a range of Uuid lenghts.
+ // This needs to be expanded on.
+ expected: ExpectedLength,
+ /// The invalid length found.
+ found: usize,
+ },
+}
+
+/// The expected length.
+#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
+pub(crate) enum ExpectedLength {
+ /// Expected any one of the given values.
+ Any(&'static [usize]),
+ /// Expected the given value.
+ Exact(usize),
+}
+
+/// Urn prefix value.
+#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
+pub(crate) enum UrnPrefix {
+ /// The `urn:uuid:` prefix should optionally provided.
+ Optional,
+}
+
+impl Error {
+ fn _description(&self) -> &str {
+ match *self {
+ Error::InvalidCharacter { .. } => "invalid character",
+ Error::InvalidGroupCount { .. } => "invalid number of groups",
+ Error::InvalidGroupLength { .. } => "invalid group length",
+ Error::InvalidLength { .. } => "invalid length",
+ }
+ }
+}
+
+impl fmt::Display for ExpectedLength {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match *self {
+ ExpectedLength::Any(crits) => write!(f, "one of {:?}", crits),
+ ExpectedLength::Exact(crit) => write!(f, "{}", crit),
+ }
+ }
+}
+
+impl fmt::Display for Error {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{}: ", self._description())?;
+
+ match *self {
+ Error::InvalidCharacter {
+ expected,
+ found,
+ index,
+ urn,
+ } => {
+ let urn_str = match urn {
+ UrnPrefix::Optional => {
+ " an optional prefix of `urn:uuid:` followed by"
+ }
+ };
+
+ write!(
+ f,
+ "expected{} {}, found {} at {}",
+ urn_str, expected, found, index
+ )
+ }
+ Error::InvalidGroupCount {
+ ref expected,
+ found,
+ } => write!(f, "expected {}, found {}", expected, found),
+ Error::InvalidGroupLength {
+ ref expected,
+ found,
+ group,
+ } => write!(
+ f,
+ "expected {}, found {} in group {}",
+ expected, found, group,
+ ),
+ Error::InvalidLength {
+ ref expected,
+ found,
+ } => write!(f, "expected {}, found {}", expected, found),
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+mod std_support {
+ use super::*;
+ use crate::std::error;
+
+ impl error::Error for Error {}
+}
diff --git a/vendor/uuid/src/parser/mod.rs b/vendor/uuid/src/parser/mod.rs new file mode 100644 index 000000000..a80f696b0 --- /dev/null +++ b/vendor/uuid/src/parser/mod.rs @@ -0,0 +1,447 @@ +// Copyright 2013-2014 The Rust Project Developers.
+// Copyright 2018 The Uuid Project Developers.
+//
+// See the COPYRIGHT file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! [`Uuid`] parsing constructs and utilities.
+//!
+//! [`Uuid`]: ../struct.Uuid.html
+
+pub(crate) mod error;
+pub(crate) use self::error::Error;
+
+use crate::{adapter, Uuid};
+
+/// Check if the length matches any of the given criteria lengths.
+fn len_matches_any(len: usize, crits: &[usize]) -> bool {
+ for crit in crits {
+ if len == *crit {
+ return true;
+ }
+ }
+
+ false
+}
+
+/// Check if the length matches any criteria lengths in the given range
+/// (inclusive).
+#[allow(dead_code)]
+fn len_matches_range(len: usize, min: usize, max: usize) -> bool {
+ for crit in min..=max {
+ if len == crit {
+ return true;
+ }
+ }
+
+ false
+}
+
+// Accumulated length of each hyphenated group in hex digits.
+const ACC_GROUP_LENS: [usize; 5] = [8, 12, 16, 20, 32];
+
+// Length of each hyphenated group in hex digits.
+const GROUP_LENS: [usize; 5] = [8, 4, 4, 4, 12];
+
+impl Uuid {
+ /// Parses a `Uuid` from a string of hexadecimal digits with optional
+ /// hyphens.
+ ///
+ /// Any of the formats generated by this module (simple, hyphenated, urn)
+ /// are supported by this parsing function.
+ pub fn parse_str(mut input: &str) -> Result<Uuid, crate::Error> {
+ // Ensure length is valid for any of the supported formats
+ let len = input.len();
+
+ if len == adapter::Urn::LENGTH && input.starts_with("urn:uuid:") {
+ input = &input[9..];
+ } else if !len_matches_any(
+ len,
+ &[adapter::Hyphenated::LENGTH, adapter::Simple::LENGTH],
+ ) {
+ Err(Error::InvalidLength {
+ expected: error::ExpectedLength::Any(&[
+ adapter::Hyphenated::LENGTH,
+ adapter::Simple::LENGTH,
+ ]),
+ found: len,
+ })?;
+ }
+
+ // `digit` counts only hexadecimal digits, `i_char` counts all chars.
+ let mut digit = 0;
+ let mut group = 0;
+ let mut acc = 0;
+ let mut buffer = [0u8; 16];
+
+ for (i_char, chr) in input.bytes().enumerate() {
+ if digit as usize >= adapter::Simple::LENGTH && group != 4 {
+ if group == 0 {
+ Err(Error::InvalidLength {
+ expected: error::ExpectedLength::Any(&[
+ adapter::Hyphenated::LENGTH,
+ adapter::Simple::LENGTH,
+ ]),
+ found: len,
+ })?;
+ }
+
+ Err(Error::InvalidGroupCount {
+ expected: error::ExpectedLength::Any(&[1, 5]),
+ found: group + 1,
+ })?;
+ }
+
+ if digit % 2 == 0 {
+ // First digit of the byte.
+ match chr {
+ // Calulate upper half.
+ b'0'..=b'9' => acc = chr - b'0',
+ b'a'..=b'f' => acc = chr - b'a' + 10,
+ b'A'..=b'F' => acc = chr - b'A' + 10,
+ // Found a group delimiter
+ b'-' => {
+ // TODO: remove the u8 cast
+ // BODY: this only needed until we switch to
+ // ParseError
+ if ACC_GROUP_LENS[group] as u8 != digit {
+ // Calculate how many digits this group consists of
+ // in the input.
+ let found = if group > 0 {
+ // TODO: remove the u8 cast
+ // BODY: this only needed until we switch to
+ // ParseError
+ digit - ACC_GROUP_LENS[group - 1] as u8
+ } else {
+ digit
+ };
+
+ Err(Error::InvalidGroupLength {
+ expected: error::ExpectedLength::Exact(
+ GROUP_LENS[group],
+ ),
+ found: found as usize,
+ group,
+ })?;
+ }
+ // Next group, decrement digit, it is incremented again
+ // at the bottom.
+ group += 1;
+ digit -= 1;
+ }
+ _ => {
+ Err(Error::InvalidCharacter {
+ expected: "0123456789abcdefABCDEF-",
+ found: input[i_char..].chars().next().unwrap(),
+ index: i_char,
+ urn: error::UrnPrefix::Optional,
+ })?;
+ }
+ }
+ } else {
+ // Second digit of the byte, shift the upper half.
+ acc *= 16;
+ match chr {
+ b'0'..=b'9' => acc += chr - b'0',
+ b'a'..=b'f' => acc += chr - b'a' + 10,
+ b'A'..=b'F' => acc += chr - b'A' + 10,
+ b'-' => {
+ // The byte isn't complete yet.
+ let found = if group > 0 {
+ // TODO: remove the u8 cast
+ // BODY: this only needed until we switch to
+ // ParseError
+ digit - ACC_GROUP_LENS[group - 1] as u8
+ } else {
+ digit
+ };
+
+ Err(Error::InvalidGroupLength {
+ expected: error::ExpectedLength::Exact(
+ GROUP_LENS[group],
+ ),
+ found: found as usize,
+ group,
+ })?;
+ }
+ _ => {
+ Err(Error::InvalidCharacter {
+ expected: "0123456789abcdefABCDEF-",
+ found: input[i_char..].chars().next().unwrap(),
+ index: i_char,
+ urn: error::UrnPrefix::Optional,
+ })?;
+ }
+ }
+ buffer[(digit / 2) as usize] = acc;
+ }
+ digit += 1;
+ }
+
+ // Now check the last group.
+ // TODO: remove the u8 cast
+ // BODY: this only needed until we switch to
+ // ParseError
+ if ACC_GROUP_LENS[4] as u8 != digit {
+ Err(Error::InvalidGroupLength {
+ expected: error::ExpectedLength::Exact(GROUP_LENS[4]),
+ found: (digit as usize - ACC_GROUP_LENS[3]),
+ group,
+ })?;
+ }
+
+ Ok(Uuid::from_bytes(buffer))
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::{adapter, std::string::ToString, test_util};
+
+ #[test]
+ fn test_parse_uuid_v4() {
+ const EXPECTED_UUID_LENGTHS: error::ExpectedLength =
+ error::ExpectedLength::Any(&[
+ adapter::Hyphenated::LENGTH,
+ adapter::Simple::LENGTH,
+ ]);
+
+ const EXPECTED_GROUP_COUNTS: error::ExpectedLength =
+ error::ExpectedLength::Any(&[1, 5]);
+
+ const EXPECTED_CHARS: &'static str = "0123456789abcdefABCDEF-";
+
+ // Invalid
+ assert_eq!(
+ Uuid::parse_str("").map_err(crate::Error::expect_parser),
+ Err(Error::InvalidLength {
+ expected: EXPECTED_UUID_LENGTHS,
+ found: 0,
+ })
+ );
+
+ assert_eq!(
+ Uuid::parse_str("!").map_err(crate::Error::expect_parser),
+ Err(Error::InvalidLength {
+ expected: EXPECTED_UUID_LENGTHS,
+ found: 1
+ })
+ );
+
+ assert_eq!(
+ Uuid::parse_str("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E45")
+ .map_err(crate::Error::expect_parser),
+ Err(Error::InvalidLength {
+ expected: EXPECTED_UUID_LENGTHS,
+ found: 37,
+ })
+ );
+
+ assert_eq!(
+ Uuid::parse_str("F9168C5E-CEB2-4faa-BBF-329BF39FA1E4")
+ .map_err(crate::Error::expect_parser),
+ Err(Error::InvalidLength {
+ expected: EXPECTED_UUID_LENGTHS,
+ found: 35
+ })
+ );
+
+ assert_eq!(
+ Uuid::parse_str("F9168C5E-CEB2-4faa-BGBF-329BF39FA1E4")
+ .map_err(crate::Error::expect_parser),
+ Err(Error::InvalidCharacter {
+ expected: EXPECTED_CHARS,
+ found: 'G',
+ index: 20,
+ urn: error::UrnPrefix::Optional,
+ })
+ );
+
+ assert_eq!(
+ Uuid::parse_str("F9168C5E-CEB2F4faaFB6BFF329BF39FA1E4")
+ .map_err(crate::Error::expect_parser),
+ Err(Error::InvalidGroupCount {
+ expected: EXPECTED_GROUP_COUNTS,
+ found: 2
+ })
+ );
+
+ assert_eq!(
+ Uuid::parse_str("F9168C5E-CEB2-4faaFB6BFF329BF39FA1E4")
+ .map_err(crate::Error::expect_parser),
+ Err(Error::InvalidGroupCount {
+ expected: EXPECTED_GROUP_COUNTS,
+ found: 3,
+ })
+ );
+
+ assert_eq!(
+ Uuid::parse_str("F9168C5E-CEB2-4faa-B6BFF329BF39FA1E4")
+ .map_err(crate::Error::expect_parser),
+ Err(Error::InvalidGroupCount {
+ expected: EXPECTED_GROUP_COUNTS,
+ found: 4,
+ })
+ );
+
+ assert_eq!(
+ Uuid::parse_str("F9168C5E-CEB2-4faa")
+ .map_err(crate::Error::expect_parser),
+ Err(Error::InvalidLength {
+ expected: EXPECTED_UUID_LENGTHS,
+ found: 18,
+ })
+ );
+
+ assert_eq!(
+ Uuid::parse_str("F9168C5E-CEB2-4faaXB6BFF329BF39FA1E4")
+ .map_err(crate::Error::expect_parser),
+ Err(Error::InvalidCharacter {
+ expected: EXPECTED_CHARS,
+ found: 'X',
+ index: 18,
+ urn: error::UrnPrefix::Optional,
+ })
+ );
+
+ assert_eq!(
+ Uuid::parse_str("F9168C5E-CEB-24fa-eB6BFF32-BF39FA1E4")
+ .map_err(crate::Error::expect_parser),
+ Err(Error::InvalidGroupLength {
+ expected: error::ExpectedLength::Exact(4),
+ found: 3,
+ group: 1,
+ })
+ );
+ // (group, found, expecting)
+ //
+ assert_eq!(
+ Uuid::parse_str("01020304-1112-2122-3132-41424344")
+ .map_err(crate::Error::expect_parser),
+ Err(Error::InvalidGroupLength {
+ expected: error::ExpectedLength::Exact(12),
+ found: 8,
+ group: 4,
+ })
+ );
+
+ assert_eq!(
+ Uuid::parse_str("67e5504410b1426f9247bb680e5fe0c")
+ .map_err(crate::Error::expect_parser),
+ Err(Error::InvalidLength {
+ expected: EXPECTED_UUID_LENGTHS,
+ found: 31,
+ })
+ );
+
+ assert_eq!(
+ Uuid::parse_str("67e5504410b1426f9247bb680e5fe0c88")
+ .map_err(crate::Error::expect_parser),
+ Err(Error::InvalidLength {
+ expected: EXPECTED_UUID_LENGTHS,
+ found: 33,
+ })
+ );
+
+ assert_eq!(
+ Uuid::parse_str("67e5504410b1426f9247bb680e5fe0cg8")
+ .map_err(crate::Error::expect_parser),
+ Err(Error::InvalidLength {
+ expected: EXPECTED_UUID_LENGTHS,
+ found: 33,
+ })
+ );
+
+ assert_eq!(
+ Uuid::parse_str("67e5504410b1426%9247bb680e5fe0c8")
+ .map_err(crate::Error::expect_parser),
+ Err(Error::InvalidCharacter {
+ expected: EXPECTED_CHARS,
+ found: '%',
+ index: 15,
+ urn: error::UrnPrefix::Optional,
+ })
+ );
+
+ assert_eq!(
+ Uuid::parse_str("231231212212423424324323477343246663")
+ .map_err(crate::Error::expect_parser),
+ Err(Error::InvalidLength {
+ expected: EXPECTED_UUID_LENGTHS,
+ found: 36,
+ })
+ );
+
+ // Valid
+ assert!(Uuid::parse_str("00000000000000000000000000000000").is_ok());
+ assert!(Uuid::parse_str("67e55044-10b1-426f-9247-bb680e5fe0c8").is_ok());
+ assert!(Uuid::parse_str("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4").is_ok());
+ assert!(Uuid::parse_str("67e5504410b1426f9247bb680e5fe0c8").is_ok());
+ assert!(Uuid::parse_str("01020304-1112-2122-3132-414243444546").is_ok());
+ assert!(Uuid::parse_str(
+ "urn:uuid:67e55044-10b1-426f-9247-bb680e5fe0c8"
+ )
+ .is_ok());
+
+ // Nil
+ let nil = Uuid::nil();
+ assert_eq!(
+ Uuid::parse_str("00000000000000000000000000000000").unwrap(),
+ nil
+ );
+ assert_eq!(
+ Uuid::parse_str("00000000-0000-0000-0000-000000000000").unwrap(),
+ nil
+ );
+
+ // Round-trip
+ let uuid_orig = test_util::new();
+ let orig_str = uuid_orig.to_string();
+ let uuid_out = Uuid::parse_str(&orig_str).unwrap();
+ assert_eq!(uuid_orig, uuid_out);
+
+ // Test error reporting
+ assert_eq!(
+ Uuid::parse_str("67e5504410b1426f9247bb680e5fe0c")
+ .map_err(crate::Error::expect_parser),
+ Err(Error::InvalidLength {
+ expected: EXPECTED_UUID_LENGTHS,
+ found: 31,
+ })
+ );
+ assert_eq!(
+ Uuid::parse_str("67e550X410b1426f9247bb680e5fe0cd")
+ .map_err(crate::Error::expect_parser),
+ Err(Error::InvalidCharacter {
+ expected: EXPECTED_CHARS,
+ found: 'X',
+ index: 6,
+ urn: error::UrnPrefix::Optional,
+ })
+ );
+ assert_eq!(
+ Uuid::parse_str("67e550-4105b1426f9247bb680e5fe0c")
+ .map_err(crate::Error::expect_parser),
+ Err(Error::InvalidGroupLength {
+ expected: error::ExpectedLength::Exact(8),
+ found: 6,
+ group: 0,
+ })
+ );
+ assert_eq!(
+ Uuid::parse_str("F9168C5E-CEB2-4faa-B6BF1-02BF39FA1E4")
+ .map_err(crate::Error::expect_parser),
+ Err(Error::InvalidGroupLength {
+ expected: error::ExpectedLength::Exact(4),
+ found: 5,
+ group: 3,
+ })
+ );
+ }
+}
|