1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
use std::str::FromStr;

/// Storage Zones with their own API endpoints.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[allow(missing_docs)]
pub enum StorageZone {
    Falkenstein,
    LosAngeles,
    NewYork,
    Singapore,
    Sydney,
}

impl StorageZone {
    /// The root API URL for this Storage Zone.
    #[must_use]
    pub fn url(self) -> &'static str {
        match self {
            Self::Falkenstein => "storage.bunnycdn.com",
            Self::LosAngeles => "la.storage.bunnycdn.com",
            Self::NewYork => "ny.storage.bunnycdn.com",
            Self::Singapore => "sg.storage.bunnycdn.com",
            Self::Sydney => "syd.storage.bunnycdn.com",
        }
    }

    fn is_falkenstein(s: &str) -> bool {
         s.eq_ignore_ascii_case("falkenstein") ||
            s.eq_ignore_ascii_case(Self::Falkenstein.url())
    }

    fn is_los_angeles(s: &str) -> bool {
        s.eq_ignore_ascii_case("los angeles") ||
            s.eq_ignore_ascii_case("losangeles") ||
            s.eq_ignore_ascii_case("los-angeles") ||
            s.eq_ignore_ascii_case("los_angeles") ||
            s.eq_ignore_ascii_case("la") ||
            s.eq_ignore_ascii_case(Self::LosAngeles.url())
    }

    fn is_new_york(s: &str) -> bool {
        s.eq_ignore_ascii_case("new york") ||
            s.eq_ignore_ascii_case("newyork") ||
            s.eq_ignore_ascii_case("new-york") ||
            s.eq_ignore_ascii_case("new_york") ||
            s.eq_ignore_ascii_case("ny") ||
            s.eq_ignore_ascii_case(Self::NewYork.url())
    }

    fn is_singapore(s: &str) -> bool {
         s.eq_ignore_ascii_case("singapore") ||
            s.eq_ignore_ascii_case("sg") ||
            s.eq_ignore_ascii_case(Self::Singapore.url())
    }

    fn is_sydney(s: &str) -> bool {
         s.eq_ignore_ascii_case("sydney") ||
            s.eq_ignore_ascii_case("syd") ||
            s.eq_ignore_ascii_case(Self::Sydney.url())
    }
}

/// Could not convert a [`String`] into a [`StorageZone`].
#[derive(Debug, thiserror::Error)]
#[allow(clippy::module_name_repetitions)]
#[error("unknown storage zone: {0}")]
pub struct UnknownStorageZone(String);

impl FromStr for StorageZone {
    type Err = UnknownStorageZone;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if Self::is_falkenstein(s) {
            Ok(Self::Falkenstein)
        } else if Self::is_los_angeles(s) {
            Ok(Self::LosAngeles)
        } else if Self::is_new_york(s) {
            Ok(Self::NewYork)
        } else if Self::is_singapore(s) {
            Ok(Self::Singapore)
        } else if Self::is_sydney(s) {
            Ok(Self::Sydney)
        } else {
            Err(UnknownStorageZone(s.to_string()))
        }
    }
}