Define PreferredUsernameError and use it

This commit is contained in:
Kitaiti Makoto 2023-01-15 08:51:38 +09:00
parent 83ed168f9c
commit cd9cb311c7

View file

@ -1,4 +1,3 @@
use ::anyhow::{self, anyhow};
use activitystreams::{ use activitystreams::{
actor::{ApActor, Group, Person}, actor::{ApActor, Group, Person},
base::{AnyBase, Base, Extends}, base::{AnyBase, Base, Extends},
@ -247,16 +246,24 @@ pub trait IntoId {
fn into_id(self) -> Id; fn into_id(self) -> Id;
} }
#[derive(thiserror::Error, Debug)]
pub enum PreferredUsernameError {
#[error("preferredUsername must be longer than 2 characters")]
TooShort,
#[error("Invaliad character at {character:?}: {position:?}")]
InvalidCharacter { character: char, position: usize },
}
#[repr(transparent)] #[repr(transparent)]
#[derive(Shrinkwrap, PartialEq, Eq, Clone, Serialize, Deserialize, Debug)] #[derive(Shrinkwrap, PartialEq, Eq, Clone, Serialize, Deserialize, Debug)]
pub struct PreferredUsername(String); pub struct PreferredUsername(String);
// Mastodon allows only /[a-z0-9_]+([a-z0-9_\.-]+[a-z0-9_]+)?/i for `preferredUsername` // Mastodon allows only /[a-z0-9_]+([a-z0-9_\.-]+[a-z0-9_]+)?/i for `preferredUsername`
impl PreferredUsername { impl PreferredUsername {
fn validate(name: &str) -> anyhow::Result<()> { fn validate(name: &str) -> std::result::Result<(), PreferredUsernameError> {
let len = name.len(); let len = name.len();
if len < 3 { if len < 3 {
return Err(anyhow!("FQN must be longer than 2 characters")); return Err(PreferredUsernameError::TooShort);
} }
match name.chars().enumerate().find(|(pos, c)| { match name.chars().enumerate().find(|(pos, c)| {
if pos == &0 || pos == &(len - 1) { if pos == &0 || pos == &(len - 1) {
@ -268,7 +275,10 @@ impl PreferredUsername {
} }
} }
}) { }) {
Some((pos, c)) => Err(anyhow!("Invaliad character at {}: {}", pos, c)), Some((pos, c)) => Err(PreferredUsernameError::InvalidCharacter {
character: c,
position: pos,
}),
None => Ok(()), None => Ok(()),
} }
} }
@ -280,7 +290,7 @@ impl PreferredUsername {
Self(name) Self(name)
} }
pub fn new(name: String) -> anyhow::Result<Self> { pub fn new(name: String) -> std::result::Result<Self, PreferredUsernameError> {
Self::validate(&name).map(|_| unsafe { Self::new_unchecked(name) }) Self::validate(&name).map(|_| unsafe { Self::new_unchecked(name) })
} }
} }
@ -292,7 +302,7 @@ impl fmt::Display for PreferredUsername {
} }
impl TryFrom<String> for PreferredUsername { impl TryFrom<String> for PreferredUsername {
type Error = anyhow::Error; type Error = PreferredUsernameError;
fn try_from(name: String) -> std::result::Result<Self, Self::Error> { fn try_from(name: String) -> std::result::Result<Self, Self::Error> {
Self::new(name) Self::new(name)
@ -300,7 +310,7 @@ impl TryFrom<String> for PreferredUsername {
} }
impl TryFrom<&str> for PreferredUsername { impl TryFrom<&str> for PreferredUsername {
type Error = anyhow::Error; type Error = PreferredUsernameError;
fn try_from(name: &str) -> std::result::Result<Self, Self::Error> { fn try_from(name: &str) -> std::result::Result<Self, Self::Error> {
Self::new(name.to_owned()) Self::new(name.to_owned())
@ -320,7 +330,7 @@ impl AsRef<str> for PreferredUsername {
} }
impl FromStr for PreferredUsername { impl FromStr for PreferredUsername {
type Err = anyhow::Error; type Err = PreferredUsernameError;
fn from_str(name: &str) -> std::result::Result<Self, Self::Err> { fn from_str(name: &str) -> std::result::Result<Self, Self::Err> {
name.try_into() name.try_into()