//! Version 0 Prefstrings use crate::{ InstanceSettings, user_preferences::{Preference, ParseError}, WeightedTable, }; /// A parsed version of the V0 prefstring /// /// See the [prefstring specification][1] for more information about how this is interpretted. /// /// [1]: https://fem.mint.lgbt/Emi/PronounsToday/raw/branch/main/doc/User-Preference-String-Spec.txt pub struct UserPreferencesV0 { pub default_weight: u8, pub default_enabled: bool, pub commands: Vec, } impl Preference for UserPreferencesV0 { fn into_weighted_table<'a>(&self, settings: &'a InstanceSettings) -> WeightedTable<'a> { todo!() } /// ``` /// # use pronouns_today::user_preferences::{Preference, v0::{Command, UserPreferencesV0}}; /// let pbytes = &[ 0x00, 0x81, 0x08, 0xcf, 0x80 ][..]; /// let prefs = UserPreferencesV0::from_prefstring_bytes(&pbytes).unwrap(); /// assert_eq!(prefs.default_weight, 1); /// assert!(prefs.default_enabled); /// assert_eq!(prefs.commands, vec![ /// Command::SetWeight(8), /// Command::Move { toggle_enabled: true, distance: 15 }, /// Command::Move { toggle_enabled: false, distance: 0 }, /// ]); /// ``` fn from_prefstring_bytes(pbytes: &[u8]) -> Result { // Some simple error checks if pbytes.len() == 0 { return Err(ParseError::ZeroLengthPrefstring); } else if pbytes[0] != 00 { return Err(ParseError::VersionMismatch { expected_version: 0..1, expected_variant: 0..1, actual_version_byte: pbytes[0], }) } else if pbytes.len() == 1 { return Err( ParseError::MalformedContent( "Version 0 prefstrings must be at least two bytes long, but this one was just one byte long".into() ) ) } // Extract the defaults from byte 1 Ok(UserPreferencesV0 { default_enabled: pbytes[1] & 0b10000000 > 0, default_weight: pbytes[1] & 0b01111111, commands: pbytes[2..].iter().map(|b| Command::from(*b)).collect(), }) } fn into_prefstring_bytes(&self) -> Vec { todo!() } } #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] pub enum Command { SetWeight(u8), Move { toggle_enabled: bool, distance: u8, } } impl From for Command { /// ``` /// use pronouns_today::user_preferences::v0::Command; /// assert_eq!( /// Command::from(0b01001000), /// Command::SetWeight(0b01001000) /// ); /// assert_eq!( /// Command::from(0b11000000), /// Command::Move { /// toggle_enabled: true, /// distance: 0b00000000 /// } /// ); /// assert_eq!( /// Command::from(0b10101000), /// Command::Move { /// toggle_enabled: false, /// distance: 0b00101000 /// } /// ); /// ``` fn from(b: u8) -> Self { if b & 0b10000000 > 0 { Command::Move { toggle_enabled: b & 0b01000000 > 0, distance: b & 0b00111111, } } else { Command::SetWeight(b) } } }