mod private { pub trait Sealed {} } /// A trait for various settings that should be contained here. /// /// **Note**: this trait is sealed to prevent external /// implementations, as it wouldn't make sense to add new settings /// that aren't used by Kittybox itself. pub trait Setting: private::Sealed + std::fmt::Debug + Default + Clone + serde::Serialize + serde::de::DeserializeOwned + /*From +*/ Send + Sync + 'static { /// The data that the setting carries. type Data: std::fmt::Debug + Send + Sync; /// The string ID for the setting, usable as an identifier in the database. const ID: &'static str; /// Unwrap the setting type, returning owned data contained within. fn into_inner(self) -> Self::Data; /// Create a new instance of this type containing certain data. fn new(data: Self::Data) -> Self; } /// A website's title, shown in the header. #[derive(Debug, serde::Deserialize, serde::Serialize, Clone, PartialEq, Eq)] pub struct SiteName(pub(crate) String); impl Default for SiteName { fn default() -> Self { Self("Kittybox".to_string()) } } impl AsRef for SiteName { fn as_ref(&self) -> &str { self.0.as_str() } } impl private::Sealed for SiteName {} impl Setting for SiteName { type Data = String; const ID: &'static str = "site_name"; fn into_inner(self) -> String { self.0 } fn new(data: Self::Data) -> Self { Self(data) } } /// Participation status in the IndieWeb Webring: https://πŸ•ΈπŸ’.ws/dashboard #[derive(Debug, Default, serde::Deserialize, serde::Serialize, Clone, Copy, PartialEq, Eq)] pub struct Webring(bool); impl private::Sealed for Webring {} impl Setting for Webring { type Data = bool; const ID: &'static str = "webring"; fn into_inner(self) -> Self::Data { self.0 } fn new(data: Self::Data) -> Self { Self(data) } }