diff --git a/parsers/src/data_forms/validate.rs b/parsers/src/data_forms/validate.rs index e2e3e518..cfd716e8 100644 --- a/parsers/src/data_forms/validate.rs +++ b/parsers/src/data_forms/validate.rs @@ -80,6 +80,46 @@ generate_element!( ] ); +/// Enum representing errors that can occur while parsing a `Datatype`. +#[derive(Debug, Clone, PartialEq)] +pub enum DatatypeError { + /// Error indicating that a prefix is missing in the validation datatype. + MissingPrefix { + /// The invalid string that caused this error. + input: String, + }, + + /// Error indicating that the validation datatype is invalid. + InvalidType { + /// The invalid string that caused this error. + input: String, + }, + + /// Error indicating that the validation datatype is unknown. + UnknownType { + /// The invalid string that caused this error. + input: String, + }, +} + +impl std::error::Error for DatatypeError {} + +impl Display for DatatypeError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + DatatypeError::MissingPrefix { input } => { + write!(f, "Missing prefix in validation datatype '{input}'.") + } + DatatypeError::InvalidType { input } => { + write!(f, "Invalid validation datatype '{input}'.") + } + DatatypeError::UnknownType { input } => { + write!(f, "Unknown validation datatype '{input}'.") + } + } + } +} + /// Data Forms Validation Datatypes /// /// https://xmpp.org/registrar/xdv-datatypes.html @@ -186,7 +226,11 @@ impl TryFrom for Validate { check_no_unknown_attributes!(elem, "item", ["datatype"]); let mut validate = Validate { - datatype: elem.attr("datatype").map(Datatype::from_str).transpose()?, + datatype: elem + .attr("datatype") + .map(Datatype::from_str) + .transpose() + .map_err(|err| FromElementError::Invalid(Error::TextParseError(err.into())))?, method: None, list_range: None, }; @@ -274,16 +318,15 @@ impl From for Element { } impl FromStr for Datatype { - type Err = Error; + type Err = DatatypeError; fn from_str(s: &str) -> Result { let mut parts = s.splitn(2, ":"); let Some(prefix) = parts.next() else { - return Err(Error::Other( - "Encountered invalid validation datatype which is missing a prefix.", - ) - .into()); + return Err(DatatypeError::MissingPrefix { + input: s.to_string(), + }); }; match prefix { @@ -302,7 +345,9 @@ impl FromStr for Datatype { } let Some(datatype) = parts.next() else { - return Err(Error::Other("Encountered invalid validation datatype.").into()); + return Err(DatatypeError::InvalidType { + input: s.to_string(), + }); }; let parsed_datatype = match datatype { @@ -319,7 +364,11 @@ impl FromStr for Datatype { "short" => Datatype::Short, "string" => Datatype::String, "time" => Datatype::Time, - _ => return Err(Error::Other("Encountered invalid validation datatype.").into()), + _ => { + return Err(DatatypeError::UnknownType { + input: s.to_string(), + }) + } }; Ok(parsed_datatype) @@ -360,10 +409,20 @@ mod tests { use super::*; #[test] - fn test_parse_datatype() -> Result<(), Error> { + fn test_parse_datatype() -> Result<(), DatatypeError> { assert_eq!(Datatype::AnyUri, "xs:anyURI".parse()?); - assert!("xs:anyuri".parse::().is_err()); - assert!("xs:".parse::().is_err()); + assert_eq!( + Err(DatatypeError::UnknownType { + input: "xs:anyuri".to_string() + }), + "xs:anyuri".parse::(), + ); + assert_eq!( + "xs:".parse::(), + Err(DatatypeError::UnknownType { + input: "xs:".to_string() + }) + ); assert_eq!( Datatype::AnyUri.into_attribute_value(), Some("xs:anyURI".to_string())