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}