Skip to main content

eml_nl/utils/
voting_channel.rs

1use thiserror::Error;
2
3use crate::{EMLError, EMLValueResultExt as _, utils::StringValueData};
4
5/// Voting channel used in the election.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7pub enum VotingChannelType {
8    /// A physical polling station
9    Polling,
10    /// Votes by mail
11    Postal,
12}
13
14impl VotingChannelType {
15    /// Create a new VotingChannelType from a string, validating its format.
16    pub fn new(s: impl AsRef<str>) -> Result<Self, EMLError> {
17        Self::from_eml_value(s).wrap_value_error()
18    }
19
20    /// Create a [`VotingChannelType`] from a `&str`, if possible.
21    pub fn from_eml_value(s: impl AsRef<str>) -> Result<Self, UnknownVotingChannelError> {
22        let data = s.as_ref();
23        match data {
24            "polling" => Ok(VotingChannelType::Polling),
25            "postal" => Ok(VotingChannelType::Postal),
26            _ => Err(UnknownVotingChannelError(data.to_string())),
27        }
28    }
29
30    /// Get the `&str` representation of this [`VotingChannelType`].
31    pub fn to_eml_value(&self) -> &'static str {
32        match self {
33            VotingChannelType::Polling => "polling",
34            VotingChannelType::Postal => "postal",
35        }
36    }
37}
38
39/// Error returned when an unknown voting channel string is encountered.
40#[derive(Debug, Clone, Error, PartialEq, Eq)]
41#[error("Unknown voting channel: {0}")]
42pub struct UnknownVotingChannelError(String);
43
44impl StringValueData for VotingChannelType {
45    type Error = UnknownVotingChannelError;
46
47    fn parse_from_str(s: &str) -> Result<Self, Self::Error>
48    where
49        Self: Sized,
50    {
51        Self::from_eml_value(s)
52    }
53
54    fn to_raw_value(&self) -> String {
55        self.to_eml_value().to_string()
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62
63    #[test]
64    fn test_valid_voting_channel_types() {
65        let valid_channels = ["polling", "postal"];
66        for channel in valid_channels {
67            assert!(
68                VotingChannelType::from_eml_value(channel).is_ok(),
69                "VotingChannelType should accept valid channel: {}",
70                channel
71            );
72        }
73    }
74
75    #[test]
76    fn test_invalid_voting_channel_types() {
77        let invalid_channels = ["", "test", "abc"];
78        for channel in invalid_channels {
79            assert!(
80                VotingChannelType::from_eml_value(channel).is_err(),
81                "VotingChannelType should reject invalid channel: {}",
82                channel
83            );
84        }
85    }
86}