use thiserror::Error;
use crate::{EMLError, EMLValueResultExt as _, utils::StringValueData};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum VotingMethod {
AMS,
FPP,
IRV,
NOR,
OPV,
RCV,
SPV,
STV,
Cumulative,
Approval,
Block,
SupporterList,
Partisan,
SupplementaryVote,
Other,
}
impl VotingMethod {
pub fn new(s: impl AsRef<str>) -> Result<Self, EMLError> {
Self::from_eml_value(s).wrap_value_error()
}
pub fn from_eml_value(s: impl AsRef<str>) -> Result<Self, UnknownVotingMethodError> {
let data = s.as_ref();
match data {
"AMS" => Ok(VotingMethod::AMS),
"FPP" => Ok(VotingMethod::FPP),
"IRV" => Ok(VotingMethod::IRV),
"NOR" => Ok(VotingMethod::NOR),
"OPV" => Ok(VotingMethod::OPV),
"RCV" => Ok(VotingMethod::RCV),
"SPV" => Ok(VotingMethod::SPV),
"STV" => Ok(VotingMethod::STV),
"cumulative" => Ok(VotingMethod::Cumulative),
"approval" => Ok(VotingMethod::Approval),
"block" => Ok(VotingMethod::Block),
"supporterlist" => Ok(VotingMethod::SupporterList),
"partisan" => Ok(VotingMethod::Partisan),
"supplementaryvote" => Ok(VotingMethod::SupplementaryVote),
"other" => Ok(VotingMethod::Other),
_ => Err(UnknownVotingMethodError(data.to_string())),
}
}
pub fn to_eml_value(&self) -> &'static str {
match self {
VotingMethod::AMS => "AMS",
VotingMethod::FPP => "FPP",
VotingMethod::IRV => "IRV",
VotingMethod::NOR => "NOR",
VotingMethod::OPV => "OPV",
VotingMethod::RCV => "RCV",
VotingMethod::SPV => "SPV",
VotingMethod::STV => "STV",
VotingMethod::Cumulative => "cumulative",
VotingMethod::Approval => "approval",
VotingMethod::Block => "block",
VotingMethod::SupporterList => "supporterlist",
VotingMethod::Partisan => "partisan",
VotingMethod::SupplementaryVote => "supplementaryvote",
VotingMethod::Other => "other",
}
}
}
#[derive(Debug, Clone, Error, PartialEq, Eq)]
#[error("Unknown voting method: {0}")]
pub struct UnknownVotingMethodError(String);
impl StringValueData for VotingMethod {
type Error = UnknownVotingMethodError;
fn parse_from_str(s: &str) -> Result<Self, Self::Error>
where
Self: Sized,
{
Self::from_eml_value(s)
}
fn to_raw_value(&self) -> String {
self.to_eml_value().to_string()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_voting_method_from_str() {
assert_eq!(VotingMethod::from_eml_value("AMS"), Ok(VotingMethod::AMS));
assert_eq!(VotingMethod::from_eml_value("FPP"), Ok(VotingMethod::FPP));
assert_eq!(VotingMethod::from_eml_value("SPV"), Ok(VotingMethod::SPV));
assert_eq!(
VotingMethod::from_eml_value("UNKNOWN"),
Err(UnknownVotingMethodError("UNKNOWN".to_string()))
);
}
#[test]
fn test_voting_method_to_str() {
assert_eq!(VotingMethod::AMS.to_eml_value(), "AMS");
assert_eq!(VotingMethod::FPP.to_eml_value(), "FPP");
assert_eq!(VotingMethod::SPV.to_eml_value(), "SPV");
}
}