PronounsToday/src/user_preferences/mod.rs

98 lines
3.9 KiB
Rust

//! 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;
use crate::{InstanceSettings, Pronoun};
use base64::{decode, encode};
use chrono::{Local, NaiveDate};
/// 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 randomly select a pronoun set unique to
/// a given date and name.
///
/// 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<'a> {
V0(v0::UserPreferencesV0<'a>)
}
/// Functionality provided by any version of user preferences
///
/// See also: [`UserPreferences`]
pub trait Preference<'a> {
/// Randomly select a pronoun set for a given date and name.
///
/// This function should be *pure*, and any randomness must be emulating using PRNG. That is
/// to say, for any given date and name, this preference object must always produce the same
/// pronoun set.
fn select_pronouns_on_date(&self, date: NaiveDate, name: Option<&str>) -> &'a Pronoun;
/// A shorthand for calling [`Preference::select_pronouns_on_date()`] with today's date
///
/// The date is generated for the system's time and timezone
fn select_pronouns(&self, name: Option<&str>) -> &'a Pronoun {
self.select_pronouns_on_date(Local::today().naive_local(), name)
}
/// 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], settings: &'a InstanceSettings) -> Self 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<u8>;
/// 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, settings: &'a InstanceSettings) -> Result<Self, base64::DecodeError> where Self: Sized {
decode(prefstring).map(|ps| Self::from_prefstring_bytes(ps.as_ref(), settings))
}
/// 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 {
encode(self.into_prefstring_bytes())
}
}
impl<'a> Preference<'a> for UserPreferences<'a> {
fn select_pronouns_on_date(&self, date: NaiveDate, name: Option<&str>) -> &'a Pronoun {
match self {
UserPreferences::V0(pref) => pref,
}.select_pronouns_on_date(date, name)
}
fn from_prefstring_bytes(bytes: &[u8], settings: &'a InstanceSettings) -> Self {
todo!()
}
fn into_prefstring_bytes(&self) -> Vec<u8> {
todo!()
}
}