mod operations; mod settings; mod values; use std::{ fmt::{Display, Formatter}, str::FromStr, }; pub use operations::*; use secrecy::{CloneableSecret, DebugSecret, SerializableSecret, Zeroize}; use serde::{Deserialize, Serialize}; pub use settings::*; pub use values::*; use crate::{instance::Instance, object::GiteratedObject}; /// A user, defined by its username and instance. /// /// # Textual Format /// A user's textual reference is defined as: /// /// `{username: String}:{instance: Instance}` /// /// # Examples /// For the user with the username `barson` and the instance `giterated.dev`, /// the following [`User`] initialization would be valid: /// /// ``` /// let user = User { /// username: String::from("barson"), /// instance: Instance::from_str("giterated.dev").unwrap() /// }; /// /// // This is correct /// assert_eq!(User::from_str("barson:giterated.dev").unwrap(), user); /// ``` #[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] pub struct User { pub username: String, pub instance: Instance, } impl GiteratedObject for User { fn object_name() -> &'static str { "user" } fn from_object_str(object_str: &str) -> Result { Ok(User::from_str(object_str).unwrap()) } } impl Display for User { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{}:{}", self.username, self.instance.url) } } impl From for User { fn from(user_string: String) -> Self { User::from_str(&user_string).unwrap() } } impl FromStr for User { type Err = UserParseError; fn from_str(s: &str) -> Result { if s.contains('/') { return Err(UserParseError); } let mut colon_split = s.split(':'); let username = colon_split.next().ok_or(UserParseError)?.to_string(); let instance = Instance::from_str(colon_split.next().ok_or(UserParseError)?) .map_err(|_| UserParseError)?; Ok(Self { username, instance }) } } #[derive(thiserror::Error, Debug)] #[error("failed to parse user")] pub struct UserParseError; #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Password(pub String); impl Zeroize for Password { fn zeroize(&mut self) { self.0.zeroize() } } impl SerializableSecret for Password {} impl CloneableSecret for Password {} impl DebugSecret for Password {}