PronounsToday/src/user_preferences/error.rs

132 lines
4.7 KiB
Rust

//! Errors that might occur when parsing or rendering prefstrings
//!
//! There are several possible points at which an error might occur when working with user
//! preference string. Each of these points are documented here, as well as
//! human-readable error messages and explainations of each.
use std::{
fmt,
ops::Range,
};
use data_encoding::DecodeError;
/// An error occured while trying to parse a user's prefstring
#[derive(Clone, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum ParseError {
/// The provided prefstring wasn't properly formatted base32 text
///
/// This could be because an implementation generated text with a different alphabet,
/// or the provided text isn't base32 at all. The [`DecodeError`] in the error is the
/// error that caused this exception.
Base32Error(DecodeError),
/// The version of the prefstring didn't match the version of the parser
///
/// This could occur when the prefstring is of a newer version than the parser, or the
/// parser is meant for a different version of the prefstring than expected.
///
/// Parsing typically works by having a master parser which supports all implemented
/// versions of prefstrings, and which delegates to several sub parsers. Each sub
/// parser handles one and only one version of the spec. This error could occur if,
/// for example, a v0 prefstring was fed to the v1 parser.
///
/// The `expected_version` and `expected_variant` properties denote the accepted
/// version or range of accepted versions that the parser supported. The `actual_`
/// properties denote what was received. These can be `None` if a version wasn't
/// specified.
///
/// If `actual_version` is [`Some`] then so must be `actual_variant`, and vice versa.
VersionMismatch {
expected_version: Range<u8>,
expected_variant: Range<u8>,
actual_version_byte: u8,
},
/// The `content` part of the prefstring was malformed
///
/// Whatever version of the specification the prefstring was being parsed with does
/// not allow whatever is going on in the prefstring. More details are provided in
/// human-readable form in the attached string.
MalformedContent(String),
/// The passed prefstring was zero-length
///
/// The minimum length for a prefstring is one byte, but the version that was passed
/// was zero bytes long. Often, this means that the developer should simply use the
/// instance default preferences.
ZeroLengthPrefstring,
/// The prefstring assumes the existance of more pronouns than exist
///
/// Often a symptom of a malformed prefstring, this error occurs when the prefstring
/// is correctly formatted, but when a [`crate::WeightedTable`] is formed
/// from it, the prefstring refers to a pronoun with an index greater than is in the
/// list. For example, setting the weight of pronoun set number 20 when there's only
/// 15 pronoun sets known by the instance.
///
/// This can be caused by reducing the number of available pronouns after a prefstring
/// has been generated, or by trying to parse a lucky malformed prefstring.
PrefstringExceedsPronounCount,
/// Attempted to roll or generate an empty table
///
/// Whatever you're doing, you would have ended up with an empty
/// [`crate::WeightedTable`], either by evaluating a prefstring that doesn't match any
/// pronouns, or by creating an invalid weighted table. Either way, you got this
/// error instead.
EmptyWeightedTable,
}
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
ParseError::Base32Error(e) => {
write!(f,
"A problem occured while deserializing the preference string as base32: {}",
e
)
},
ParseError::VersionMismatch {
expected_version,
expected_variant,
actual_version_byte,
} => {
write!(f,
"A parser meant to handle prefstring version {} through {} and
variants {} throught {} was given a prefstring of version {} and
variant {}.",
expected_version.start,
expected_version.end - 1,
expected_variant.start,
expected_variant.end - 1,
actual_version_byte >> 3,
actual_version_byte & 0b00000111,
)
},
ParseError::MalformedContent(msg) => {
write!(f,"The prefstring's content was malformed: {}", msg)
},
ParseError::ZeroLengthPrefstring => {
write!(f, "Tried to parse a zero-length prefstring")
},
ParseError::PrefstringExceedsPronounCount => {
write!(f, "The user preferences refers to pronouns beyond those that are known")
}
ParseError::EmptyWeightedTable => {
write!(f, "Attempted to create or roll an empty roll table")
}
}
}
}
impl From<DecodeError> for ParseError {
fn from(e: DecodeError) -> Self {
ParseError::Base32Error(e)
}
}