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]
fn missing_key_algorithm() {
assert_eq!(
<&DeviceKeyId>::try_from(":JLAFKJWSCS").unwrap_err(),
IdParseError::InvalidKeyAlgorithm
);
assert_eq!(<&DeviceKeyId>::try_from(":JLAFKJWSCS").unwrap_err(), IdParseError::Empty);
}
#[test]
fn missing_delimiter() {
assert_eq!(
<&DeviceKeyId>::try_from("ed25519|JLAFKJWSCS").unwrap_err(),
IdParseError::MissingDelimiter,
IdParseError::MissingColon,
);
}

View File

@ -268,7 +268,10 @@ impl MatrixToUri {
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 mut via = vec![];
@ -428,7 +431,7 @@ impl MatrixUri {
/// Try parsing a `&str` into a `MatrixUri`.
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 {
return Err(MatrixUriError::WrongScheme.into());
@ -950,7 +953,10 @@ mod tests {
#[test]
fn parse_matrixuri_invalid_uri() {
assert_eq!(MatrixUri::parse("").unwrap_err(), Error::InvalidUri);
assert_eq!(
MatrixUri::parse("").unwrap_err(),
Error::InvalidMatrixToUri(MatrixToError::InvalidUrl)
);
}
#[test]

View File

@ -140,7 +140,7 @@ mod tests {
#[test]
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]

View File

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

View File

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

View File

@ -319,7 +319,7 @@ mod tests {
#[test]
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]

View File

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

View File

@ -1,10 +1,10 @@
use crate::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 {
Err(Error::InvalidKeyAlgorithm)
Err(Error::Empty)
} else {
// Any non-empty string is accepted as a key algorithm for forwards compatibility
Ok(())

View File

@ -6,39 +6,21 @@ use std::str::Utf8Error;
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, thiserror::Error)]
#[non_exhaustive]
pub enum Error {
/// The client secret is empty.
#[error("client secret is empty")]
EmptyClientSecret,
/// The identifier or a required part of it is empty.
#[error("identifier or required part of it is empty")]
Empty,
/// The room name is empty.
#[error("room name is empty")]
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")]
/// The identifier contains invalid characters.
#[error("identifier contains invalid characters")]
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.
#[error("invalid matrix ID: {0}")]
InvalidMatrixId(#[from] MatrixIdError),
/// The string isn't a valid Matrix.to URI.
#[error("invalid matrix.to URI: {0}")]
InvalidMatrixToRef(#[from] MatrixToError),
InvalidMatrixToUri(#[from] MatrixToError),
/// The string isn't a valid Matrix URI.
#[error("invalid matrix URI: {0}")]
@ -52,10 +34,6 @@ pub enum Error {
#[error("server name is not a valid IP address or domain name")]
InvalidServerName,
/// The string isn't a valid URI.
#[error("invalid URI")]
InvalidUri,
/// The string isn't valid UTF-8.
#[error("invalid UTF-8")]
InvalidUtf8,
@ -67,7 +45,7 @@ pub enum Error {
/// The ID is missing the colon delimiter between localpart and server name, or between key
/// algorithm and key name / version.
#[error("required colon is missing")]
MissingDelimiter,
MissingColon,
/// The ID is missing the correct leading sigil.
#[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.
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, thiserror::Error)]
#[non_exhaustive]
@ -147,6 +119,10 @@ pub enum MatrixIdError {
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, thiserror::Error)]
#[non_exhaustive]
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/#/`.
#[error("base URL is not https://matrix.to/#/")]
WrongBaseUrl,

View File

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

View File

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

View File

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