1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
//! Name error. use core::fmt; /// Name error. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct NameError { /// Target type. target: TargetNameType, /// The position of the first byte an error part starts. valid_up_to: usize, } impl NameError { /// Creates a new `NameError`. #[inline] #[must_use] pub(super) fn new(target: TargetNameType, valid_up_to: usize) -> Self { Self { target, valid_up_to, } } /// Returns the index in the given string up to which valid name was verified. /// /// Note that `&source_str[..err.valid_up_to()]` might be invalid when `valid_up_to` is zero. /// In other words, it depends on target type whether the empty string is valid or not. /// This error type does not assume anything about it. /// /// # Examples /// /// ``` /// # use xml_string::names::NameError; /// use xml_string::names::Ncname; /// /// let err_nonempty = Ncname::from_str("foo:bar").expect_err("NCName cannot have a colon"); /// assert_eq!(err_nonempty.valid_up_to(), 3); /// assert!(Ncname::from_str("foo").is_ok()); /// /// let err_empty = Ncname::from_str("").expect_err("NCName cannot be empty"); /// assert_eq!(err_empty.valid_up_to(), 0); /// assert!( /// Ncname::from_str("").is_err(), /// "Note that `&s[..err.valid_up_to()]` is not always valid for the empty source string" /// ); /// ``` #[inline] #[must_use] pub fn valid_up_to(&self) -> usize { self.valid_up_to } } impl fmt::Display for NameError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, "Failed to parse the string as {}: invalid from {} bytes", self.target.name(), self.valid_up_to ) } } #[cfg(feature = "std")] impl std::error::Error for NameError {} /// Target name type of a conversion. #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[non_exhaustive] pub(super) enum TargetNameType { /// [`Name`]. /// /// [`Name`]: https://www.w3.org/TR/REC-xml/#NT-Name Name, /// [`NCName`]. /// /// [`NCName`]: https://www.w3.org/TR/2009/REC-xml-names-20091208/#NT-NCName Ncname, /// [`Nmtoken`]. /// /// [`Nmtoken`]: https://www.w3.org/TR/REC-xml/#NT-Nmtoken Nmtoken, /// [`QName`]. /// /// [`QName`]: https://www.w3.org/TR/2009/REC-xml-names-20091208/#NT-QName Qname, /// [`URIQualifiedName`]. /// /// [`URIQualifiedName`]: /// https://www.w3.org/TR/2017/REC-xpath-31-20170321/#prod-xpath31-URIQualifiedName UriQualifiedName, } impl TargetNameType { /// Returns the target name type name. fn name(self) -> &'static str { match self { Self::Name => "Name", Self::Ncname => "NCName", Self::Nmtoken => "Nmtoken", Self::Qname => "QName", Self::UriQualifiedName => "URIQualifiedName", } } }