//! Pronoun selection & parsing for various version of user preferences //! //! There may be several possible representations of parsed prefstrings, each of which possibly //! with a different algorithm for selecting pronouns, and a different way of parsing itself. This //! module houses the implementations for each of these versions. pub mod v0; mod error; pub use error::ParseError; use crate::{InstanceSettings, Pronoun, WeightedTable}; use data_encoding::BASE32_NOPAD; /// A user's preferences for the probabilities of certain pronouns /// /// This is the parsed version of a prefstring. The actual implementation details may vary across /// versions, but universally they must be able to at least produce a weighted list of pronouns, /// representing the probabilities the user wants for each pronoun set. /// /// To this end, all versions of the user preferences implement [`Preference`]. For convenience, /// `UserPreferences` also implements [`Preference`]. /// /// Because parsing a prefstring must be done in relation to an [`InstanceSettings`], the /// `UserPreferences` struct shares a lifetime with the settings it was created with. #[non_exhaustive] pub enum UserPreferences { V0(v0::UserPreferencesV0) } /// Functionality provided by any version of user preferences /// /// See also: [`UserPreferences`] pub trait Preference { /// Produce a weighted list of pronouns based on these preferences /// /// This is a one-directional conversion to a [`WeightedTable`]. This method is a /// crucial step to randomly selecting a pronoun set based on a user's preferences, as /// any selection is done by using a [`WeightedTable`]. All preference versions must /// implement this method. fn into_weighted_table<'a>(&self, settings: &'a InstanceSettings) -> Result, ParseError>; /// Parse a given prefstring, after it's extraction from base64 /// /// This should attempt to parse the data contained in a prefstring into the appropriate /// format. Prefstrings will already have been parsed from base64 before being passed to the /// implementation. Users looking to turn a b64 prefstring into a `Preference` should use /// [`Preference::from_prefstring()`] fn from_prefstring_bytes(bytes: &[u8]) -> Result where Self: Sized; /// Serialize these preferences into as few bytes as possible /// /// This should produce a series of bytes that, when passed to /// [`Preference::from_prefstring_bytes()`] should produce this `Preference` object again. /// This should be done in accordance with the [prefstring specification][1]. /// /// [1]: https://fem.mint.lgbt/Emi/PronounsToday/raw/branch/main/doc/User-Preference-String-Spec.txt fn into_prefstring_bytes(&self) -> Vec; /// Parse a base64 prefstring /// /// This is the primary method of creating a `Preference` object from a prefstring. The /// default implementation calls the underlying [`Preference::from_prefstring_bytes()`] method. fn from_prefstring(prefstring: &str) -> Result where Self: Sized { BASE32_NOPAD.decode(prefstring.as_ref()) .map_err(ParseError::Base32Error) .and_then(|ps| Self::from_prefstring_bytes(&ps)) } /// Serialize into a base64 prefstring /// /// This is the primary method of creating a prefstring from a `Preference` object. The /// default implementation calls the underlying [`Preference::into_prefstring_bytes()`] method. fn into_prefstring(&self) -> String { BASE32_NOPAD.encode(&self.into_prefstring_bytes()) } } impl Preference for UserPreferences { fn into_weighted_table<'a>(&self, settings: &'a InstanceSettings) -> Result, ParseError> { match self { UserPreferences::V0(pref) => pref, }.into_weighted_table(settings) } fn from_prefstring_bytes(bytes: &[u8]) -> Result where Self: Sized { todo!() } fn into_prefstring_bytes(&self) -> Vec { todo!() } }