carbonintensity/
target.rs

1use crate::Region;
2
3/// Carbon intensity target, e.g. a postcode or a region
4#[derive(Debug, Clone, PartialEq)]
5pub enum Target {
6    National,
7    Postcode(String),
8    Region(Region),
9}
10
11/// Creates a `Target` from a `String`
12///
13/// If the string is equal to 'national' or is empty returns `Target::National.
14/// If it contains a valid `Region` id this returns a `Target::Region`,
15/// otherwise it returns a `Target::Postcode`.
16///
17/// Note how this is infallible because it balls back to `Target::Postcode`.
18///
19/// ```
20/// # use carbonintensity::{Target, Region};
21/// let target = Target::from("13".to_string());
22/// assert_eq!(target, Target::Region(Region::London));
23///
24/// let target = Target::from("BS7".to_string());
25/// let bs7 = Target::Postcode("BS7".to_string());
26/// assert_eq!(target, bs7);
27/// ```
28impl From<String> for Target {
29    fn from(s: String) -> Self {
30        if s.trim().is_empty() | s.trim().eq_ignore_ascii_case("national") {
31            return Self::National;
32        }
33
34        // Check if input can be parsed as a Region
35        if let Ok(region) = s.parse::<Region>() {
36            return Self::Region(region);
37        }
38
39        // Assumes the string was a postcode
40        Self::Postcode(s)
41    }
42}
43
44impl std::fmt::Display for Target {
45    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46        let target = match self {
47            Target::National => "National".to_string(),
48            Target::Postcode(postcode) => format!("postcode {postcode}"),
49            Target::Region(region) => region.to_string(),
50        };
51
52        write!(f, "{target}")
53    }
54}