identifiers: Clean up error enum

This commit is contained in:
Jonas Platte 2022-04-27 19:09:13 +02:00
parent e3ee951856
commit 9cfee27722
No known key found for this signature in database
GPG Key ID: BBA95679259D342F
14 changed files with 36 additions and 60 deletions

View File

@ -74,17 +74,14 @@ mod tests {
#[test] #[test]
fn missing_key_algorithm() { fn missing_key_algorithm() {
assert_eq!( assert_eq!(<&DeviceKeyId>::try_from(":JLAFKJWSCS").unwrap_err(), IdParseError::Empty);
<&DeviceKeyId>::try_from(":JLAFKJWSCS").unwrap_err(),
IdParseError::InvalidKeyAlgorithm
);
} }
#[test] #[test]
fn missing_delimiter() { fn missing_delimiter() {
assert_eq!( assert_eq!(
<&DeviceKeyId>::try_from("ed25519|JLAFKJWSCS").unwrap_err(), <&DeviceKeyId>::try_from("ed25519|JLAFKJWSCS").unwrap_err(),
IdParseError::MissingDelimiter, IdParseError::MissingColon,
); );
} }

View File

@ -268,7 +268,10 @@ impl MatrixToUri {
return Err(MatrixToError::WrongBaseUrl.into()); return Err(MatrixToError::WrongBaseUrl.into());
}; };
let url = Url::parse(MATRIX_TO_BASE_URL.trim_end_matches("#/"))?.join(without_base)?; let url = Url::parse(MATRIX_TO_BASE_URL.trim_end_matches("#/"))
.expect("matrix.to base URL is valid")
.join(without_base)
.map_err(|_| MatrixToError::InvalidUrl)?;
let id = MatrixId::parse_with_sigil(url.path())?; let id = MatrixId::parse_with_sigil(url.path())?;
let mut via = vec![]; let mut via = vec![];
@ -428,7 +431,7 @@ impl MatrixUri {
/// Try parsing a `&str` into a `MatrixUri`. /// Try parsing a `&str` into a `MatrixUri`.
pub fn parse(s: &str) -> Result<Self, Error> { pub fn parse(s: &str) -> Result<Self, Error> {
let url = Url::parse(s)?; let url = Url::parse(s).map_err(|_| MatrixToError::InvalidUrl)?;
if url.scheme() != MATRIX_SCHEME { if url.scheme() != MATRIX_SCHEME {
return Err(MatrixUriError::WrongScheme.into()); return Err(MatrixUriError::WrongScheme.into());
@ -950,7 +953,10 @@ mod tests {
#[test] #[test]
fn parse_matrixuri_invalid_uri() { fn parse_matrixuri_invalid_uri() {
assert_eq!(MatrixUri::parse("").unwrap_err(), Error::InvalidUri); assert_eq!(
MatrixUri::parse("").unwrap_err(),
Error::InvalidMatrixToUri(MatrixToError::InvalidUrl)
);
} }
#[test] #[test]

View File

@ -140,7 +140,7 @@ mod tests {
#[test] #[test]
fn missing_room_alias_id_delimiter() { fn missing_room_alias_id_delimiter() {
assert_eq!(<&RoomAliasId>::try_from("#ruma").unwrap_err(), IdParseError::MissingDelimiter); assert_eq!(<&RoomAliasId>::try_from("#ruma").unwrap_err(), IdParseError::MissingColon);
} }
#[test] #[test]

View File

@ -195,10 +195,7 @@ mod tests {
#[test] #[test]
fn missing_room_id_delimiter() { fn missing_room_id_delimiter() {
assert_eq!( assert_eq!(<&RoomId>::try_from("!29fhd83h92h0").unwrap_err(), IdParseError::MissingColon);
<&RoomId>::try_from("!29fhd83h92h0").unwrap_err(),
IdParseError::MissingDelimiter
);
} }
#[test] #[test]

View File

@ -309,7 +309,7 @@ mod tests {
#[test] #[test]
fn empty_room_version_id() { fn empty_room_version_id() {
assert_eq!(RoomVersionId::try_from(""), Err(IdParseError::EmptyRoomVersionId)); assert_eq!(RoomVersionId::try_from(""), Err(IdParseError::Empty));
} }
#[test] #[test]

View File

@ -319,7 +319,7 @@ mod tests {
#[test] #[test]
fn missing_user_id_delimiter() { fn missing_user_id_delimiter() {
assert_eq!(<&UserId>::try_from("@carl").unwrap_err(), IdParseError::MissingDelimiter); assert_eq!(<&UserId>::try_from("@carl").unwrap_err(), IdParseError::MissingColon);
} }
#[test] #[test]

View File

@ -6,7 +6,7 @@ pub fn validate(s: &str) -> Result<(), Error> {
} else if !s.chars().all(|c| c.is_alphanumeric() || ".=_-".contains(c)) { } else if !s.chars().all(|c| c.is_alphanumeric() || ".=_-".contains(c)) {
return Err(Error::InvalidCharacters); return Err(Error::InvalidCharacters);
} else if s.is_empty() { } else if s.is_empty() {
return Err(Error::EmptyClientSecret); return Err(Error::Empty);
} }
Ok(()) Ok(())

View File

@ -1,10 +1,10 @@
use crate::Error; use crate::Error;
pub fn validate(s: &str) -> Result<(), Error> { pub fn validate(s: &str) -> Result<(), Error> {
let colon_idx = s.find(':').ok_or(Error::MissingDelimiter)?; let colon_idx = s.find(':').ok_or(Error::MissingColon)?;
if colon_idx == 0 { if colon_idx == 0 {
Err(Error::InvalidKeyAlgorithm) Err(Error::Empty)
} else { } else {
// Any non-empty string is accepted as a key algorithm for forwards compatibility // Any non-empty string is accepted as a key algorithm for forwards compatibility
Ok(()) Ok(())

View File

@ -6,39 +6,21 @@ use std::str::Utf8Error;
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, thiserror::Error)] #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, thiserror::Error)]
#[non_exhaustive] #[non_exhaustive]
pub enum Error { pub enum Error {
/// The client secret is empty. /// The identifier or a required part of it is empty.
#[error("client secret is empty")] #[error("identifier or required part of it is empty")]
EmptyClientSecret, Empty,
/// The room name is empty. /// The identifier contains invalid characters.
#[error("room name is empty")] #[error("identifier contains invalid characters")]
EmptyRoomName,
/// The room version ID is empty.
#[error("room version ID is empty")]
EmptyRoomVersionId,
/// The ID's localpart contains invalid characters.
///
/// Only relevant for user IDs.
#[error("localpart contains invalid characters")]
InvalidCharacters, InvalidCharacters,
/// The key algorithm is invalid (e.g. empty).
#[error("invalid key algorithm specified")]
InvalidKeyAlgorithm,
/// The key version contains outside of [a-zA-Z0-9_].
#[error("key ID version contains invalid characters")]
InvalidKeyVersion,
/// The string isn't a valid Matrix ID. /// The string isn't a valid Matrix ID.
#[error("invalid matrix ID: {0}")] #[error("invalid matrix ID: {0}")]
InvalidMatrixId(#[from] MatrixIdError), InvalidMatrixId(#[from] MatrixIdError),
/// The string isn't a valid Matrix.to URI. /// The string isn't a valid Matrix.to URI.
#[error("invalid matrix.to URI: {0}")] #[error("invalid matrix.to URI: {0}")]
InvalidMatrixToRef(#[from] MatrixToError), InvalidMatrixToUri(#[from] MatrixToError),
/// The string isn't a valid Matrix URI. /// The string isn't a valid Matrix URI.
#[error("invalid matrix URI: {0}")] #[error("invalid matrix URI: {0}")]
@ -52,10 +34,6 @@ pub enum Error {
#[error("server name is not a valid IP address or domain name")] #[error("server name is not a valid IP address or domain name")]
InvalidServerName, InvalidServerName,
/// The string isn't a valid URI.
#[error("invalid URI")]
InvalidUri,
/// The string isn't valid UTF-8. /// The string isn't valid UTF-8.
#[error("invalid UTF-8")] #[error("invalid UTF-8")]
InvalidUtf8, InvalidUtf8,
@ -67,7 +45,7 @@ pub enum Error {
/// The ID is missing the colon delimiter between localpart and server name, or between key /// The ID is missing the colon delimiter between localpart and server name, or between key
/// algorithm and key name / version. /// algorithm and key name / version.
#[error("required colon is missing")] #[error("required colon is missing")]
MissingDelimiter, MissingColon,
/// The ID is missing the correct leading sigil. /// The ID is missing the correct leading sigil.
#[error("leading sigil is incorrect or missing")] #[error("leading sigil is incorrect or missing")]
@ -80,12 +58,6 @@ impl From<Utf8Error> for Error {
} }
} }
impl From<url::ParseError> for Error {
fn from(_: url::ParseError) -> Self {
Self::InvalidUri
}
}
/// An error occurred while validating an MXC URI. /// An error occurred while validating an MXC URI.
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, thiserror::Error)] #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, thiserror::Error)]
#[non_exhaustive] #[non_exhaustive]
@ -147,6 +119,10 @@ pub enum MatrixIdError {
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, thiserror::Error)] #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, thiserror::Error)]
#[non_exhaustive] #[non_exhaustive]
pub enum MatrixToError { pub enum MatrixToError {
/// String is not a valid URI.
#[error("given string is not a valid URL")]
InvalidUrl,
/// String did not start with `https://matrix.to/#/`. /// String did not start with `https://matrix.to/#/`.
#[error("base URL is not https://matrix.to/#/")] #[error("base URL is not https://matrix.to/#/")]
WrongBaseUrl, WrongBaseUrl,

View File

@ -3,8 +3,8 @@ use std::num::NonZeroU8;
use crate::Error; use crate::Error;
pub fn validate(s: &str) -> Result<NonZeroU8, Error> { pub fn validate(s: &str) -> Result<NonZeroU8, Error> {
let colon_idx = NonZeroU8::new(s.find(':').ok_or(Error::MissingDelimiter)? as u8) let colon_idx =
.ok_or(Error::InvalidKeyAlgorithm)?; NonZeroU8::new(s.find(':').ok_or(Error::MissingColon)? as u8).ok_or(Error::MissingColon)?;
#[cfg(not(feature = "compat"))] #[cfg(not(feature = "compat"))]
validate_version(&s[colon_idx.get() as usize + 1..])?; validate_version(&s[colon_idx.get() as usize + 1..])?;
@ -15,7 +15,7 @@ pub fn validate(s: &str) -> Result<NonZeroU8, Error> {
#[cfg(not(feature = "compat"))] #[cfg(not(feature = "compat"))]
fn validate_version(version: &str) -> Result<(), Error> { fn validate_version(version: &str) -> Result<(), Error> {
if version.is_empty() { if version.is_empty() {
return Err(Error::EmptyRoomVersionId); return Err(Error::Empty);
} else if !version.chars().all(|c| c.is_alphanumeric() || c == '_') { } else if !version.chars().all(|c| c.is_alphanumeric() || c == '_') {
return Err(Error::InvalidCharacters); return Err(Error::InvalidCharacters);
} }

View File

@ -37,7 +37,7 @@ fn validate_id(id: &str, valid_sigils: &[char]) -> Result<(), Error> {
/// Checks an identifier that contains a localpart and hostname for validity. /// Checks an identifier that contains a localpart and hostname for validity.
fn parse_id(id: &str, valid_sigils: &[char]) -> Result<usize, Error> { fn parse_id(id: &str, valid_sigils: &[char]) -> Result<usize, Error> {
validate_id(id, valid_sigils)?; validate_id(id, valid_sigils)?;
let colon_idx = id.find(':').ok_or(Error::MissingDelimiter)?; let colon_idx = id.find(':').ok_or(Error::MissingColon)?;
server_name::validate(&id[colon_idx + 1..])?; server_name::validate(&id[colon_idx + 1..])?;
Ok(colon_idx) Ok(colon_idx)
} }

View File

@ -2,7 +2,7 @@ use crate::Error;
pub fn validate(value: &str) -> Result<(), Error> { pub fn validate(value: &str) -> Result<(), Error> {
match value.len() { match value.len() {
0 => Err(Error::EmptyRoomName), 0 => Err(Error::Empty),
1..=255 => Ok(()), 1..=255 => Ok(()),
_ => Err(Error::MaximumLengthExceeded), _ => Err(Error::MaximumLengthExceeded),
} }

View File

@ -5,7 +5,7 @@ const MAX_CODE_POINTS: usize = 32;
pub fn validate(s: &str) -> Result<(), Error> { pub fn validate(s: &str) -> Result<(), Error> {
if s.is_empty() { if s.is_empty() {
Err(Error::EmptyRoomVersionId) Err(Error::Empty)
} else if s.chars().count() > MAX_CODE_POINTS { } else if s.chars().count() > MAX_CODE_POINTS {
Err(Error::MaximumLengthExceeded) Err(Error::MaximumLengthExceeded)
} else { } else {

View File

@ -6,7 +6,7 @@ pub fn validate(s: &str) -> Result<(), Error> {
} else if !s.chars().all(|c| c.is_alphanumeric() || ".=_-".contains(c)) { } else if !s.chars().all(|c| c.is_alphanumeric() || ".=_-".contains(c)) {
return Err(Error::InvalidCharacters); return Err(Error::InvalidCharacters);
} else if s.is_empty() { } else if s.is_empty() {
return Err(Error::EmptyClientSecret); return Err(Error::Empty);
} }
Ok(()) Ok(())