1pub const DEFAULT_REGION: &str = "us-east-1";
2pub const DEFAULT_PARTITION: &str = "aws";
3pub const DEFAULT_URL_SUFFIX: &str = "amazonaws.com";
4
5const CN_REGIONS: &[&str] = &["cn-north-1", "cn-northwest-1"];
6const GOV_REGIONS: &[&str] = &["us-gov-east-1", "us-gov-west-1"];
7
8pub const AVAILABILITY_ZONES: &[(&str, &[&str])] = &[
9 ("af-south-1", &["af-south-1a", "af-south-1b", "af-south-1c"]),
10 ("ap-east-1", &["ap-east-1a", "ap-east-1b", "ap-east-1c"]),
11 ("ap-east-2", &["ap-east-2a", "ap-east-2b", "ap-east-2c"]),
12 ("ap-northeast-1", &["ap-northeast-1a", "ap-northeast-1b", "ap-northeast-1c", "ap-northeast-1d"]),
13 ("ap-northeast-2", &["ap-northeast-2a", "ap-northeast-2b", "ap-northeast-2c", "ap-northeast-2d"]),
14 ("ap-northeast-3", &["ap-northeast-3a", "ap-northeast-3b", "ap-northeast-3c"]),
15 ("ap-south-1", &["ap-south-1a", "ap-south-1b", "ap-south-1c"]),
16 ("ap-south-2", &["ap-south-2a", "ap-south-2b", "ap-south-2c"]),
17 ("ap-southeast-1", &["ap-southeast-1a", "ap-southeast-1b", "ap-southeast-1c"]),
18 ("ap-southeast-2", &["ap-southeast-2a", "ap-southeast-2b", "ap-southeast-2c"]),
19 ("ap-southeast-3", &["ap-southeast-3a", "ap-southeast-3b", "ap-southeast-3c"]),
20 ("ap-southeast-4", &["ap-southeast-4a", "ap-southeast-4b", "ap-southeast-4c"]),
21 ("ap-southeast-5", &["ap-southeast-5a", "ap-southeast-5b", "ap-southeast-5c"]),
22 ("ap-southeast-6", &["ap-southeast-6a", "ap-southeast-6b", "ap-southeast-6c"]),
23 ("ap-southeast-7", &["ap-southeast-7a", "ap-southeast-7b", "ap-southeast-7c"]),
24 ("ca-central-1", &["ca-central-1a", "ca-central-1b", "ca-central-1c", "ca-central-1d"]),
25 ("ca-west-1", &["ca-west-1a", "ca-west-1b", "ca-west-1c"]),
26 ("cn-north-1", &["cn-north-1a", "cn-north-1b", "cn-north-1c"]),
27 ("cn-northwest-1", &["cn-northwest-1a", "cn-northwest-1b", "cn-northwest-1c"]),
28 ("eu-central-1", &["eu-central-1a", "eu-central-1b", "eu-central-1c"]),
29 ("eu-central-2", &["eu-central-2a", "eu-central-2b", "eu-central-2c"]),
30 ("eu-isoe-west-1", &["eu-isoe-west-1a", "eu-isoe-west-1b", "eu-isoe-west-1c"]),
31 ("eu-north-1", &["eu-north-1a", "eu-north-1b", "eu-north-1c"]),
32 ("eu-south-1", &["eu-south-1a", "eu-south-1b", "eu-south-1c"]),
33 ("eu-south-2", &["eu-south-2a", "eu-south-2b", "eu-south-2c"]),
34 ("eu-west-1", &["eu-west-1a", "eu-west-1b", "eu-west-1c"]),
35 ("eu-west-2", &["eu-west-2a", "eu-west-2b", "eu-west-2c"]),
36 ("eu-west-3", &["eu-west-3a", "eu-west-3b", "eu-west-3c"]),
37 ("eusc-de-east-1", &["eusc-de-east-1a", "eusc-de-east-1b", "eusc-de-east-1c"]),
38 ("il-central-1", &["il-central-1a", "il-central-1b", "il-central-1c"]),
39 ("me-central-1", &["me-central-1a", "me-central-1b", "me-central-1c"]),
40 ("me-south-1", &["me-south-1a", "me-south-1b", "me-south-1c"]),
41 ("mx-central-1", &["mx-central-1a", "mx-central-1b", "mx-central-1c"]),
42 ("sa-east-1", &["sa-east-1a", "sa-east-1b", "sa-east-1c"]),
43 ("us-east-1", &["us-east-1a", "us-east-1b", "us-east-1c", "us-east-1d", "us-east-1e", "us-east-1f"]),
44 ("us-east-2", &["us-east-2a", "us-east-2b", "us-east-2c"]),
45 ("us-gov-east-1", &["us-gov-east-1a", "us-gov-east-1b", "us-gov-east-1c"]),
46 ("us-gov-west-1", &["us-gov-west-1a", "us-gov-west-1b", "us-gov-west-1c"]),
47 ("us-iso-east-1", &["us-iso-east-1a", "us-iso-east-1b", "us-iso-east-1c"]),
48 ("us-iso-west-1", &["us-iso-west-1a", "us-iso-west-1b", "us-iso-west-1c"]),
49 ("us-isob-east-1", &["us-isob-east-1a", "us-isob-east-1b", "us-isob-east-1c"]),
50 ("us-isof-east-1", &["us-isof-east-1a", "us-isof-east-1b", "us-isof-east-1c"]),
51 ("us-isof-south-1", &["us-isof-south-1a", "us-isof-south-1b", "us-isof-south-1c"]),
52 ("us-west-1", &["us-west-1a", "us-west-1c"]),
53 ("us-west-2", &["us-west-2a", "us-west-2b", "us-west-2c", "us-west-2d"]),
54];
55
56const AWS_REGION_NAMES: [&str; AVAILABILITY_ZONES.len()] = {
57 let mut names = [""; AVAILABILITY_ZONES.len()];
58 let mut i = 0;
59 while i < AVAILABILITY_ZONES.len() {
60 names[i] = AVAILABILITY_ZONES[i].0;
61 i += 1;
62 }
63 names
64};
65
66pub const AWS_REGIONS: &[&str] = &AWS_REGION_NAMES;
67
68pub fn is_known_region(region: &str) -> bool {
69 AWS_REGIONS.contains(®ion)
70}
71
72pub fn availability_zones_for_region(region: &str) -> Option<&'static [&'static str]> {
73 AVAILABILITY_ZONES.iter().find(|(name, _)| *name == region).map(|(_, zones)| *zones)
74}
75
76pub fn partition_for_region(region: &str) -> &'static str {
77 if CN_REGIONS.contains(®ion) {
78 "aws-cn"
79 } else if GOV_REGIONS.contains(®ion) {
80 "aws-us-gov"
81 } else {
82 DEFAULT_PARTITION
83 }
84}
85
86pub fn url_suffix_for_region(region: &str) -> &'static str {
87 if CN_REGIONS.contains(®ion) { "amazonaws.com.cn" } else { DEFAULT_URL_SUFFIX }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
95 fn partition_for_standard_regions() {
96 assert_eq!(partition_for_region("us-east-1"), "aws");
97 assert_eq!(partition_for_region("eu-west-1"), "aws");
98 assert_eq!(partition_for_region("ap-southeast-1"), "aws");
99 }
100
101 #[test]
102 fn partition_for_china_regions() {
103 assert_eq!(partition_for_region("cn-north-1"), "aws-cn");
104 assert_eq!(partition_for_region("cn-northwest-1"), "aws-cn");
105 }
106
107 #[test]
108 fn partition_for_govcloud_regions() {
109 assert_eq!(partition_for_region("us-gov-east-1"), "aws-us-gov");
110 assert_eq!(partition_for_region("us-gov-west-1"), "aws-us-gov");
111 }
112
113 #[test]
114 fn url_suffix_for_standard_regions() {
115 assert_eq!(url_suffix_for_region("us-east-1"), "amazonaws.com");
116 assert_eq!(url_suffix_for_region("eu-west-1"), "amazonaws.com");
117 assert_eq!(url_suffix_for_region("us-gov-west-1"), "amazonaws.com");
118 }
119
120 #[test]
121 fn url_suffix_for_china_regions() {
122 assert_eq!(url_suffix_for_region("cn-north-1"), "amazonaws.com.cn");
123 assert_eq!(url_suffix_for_region("cn-northwest-1"), "amazonaws.com.cn");
124 }
125
126 #[test]
127 fn aws_regions_derives_from_availability_zones() {
128 assert_eq!(AWS_REGIONS.len(), AVAILABILITY_ZONES.len());
129 for ((region, _), name) in AVAILABILITY_ZONES.iter().zip(AWS_REGIONS.iter()) {
130 assert_eq!(region, name, "AWS_REGIONS must mirror AVAILABILITY_ZONES region names in order");
131 }
132 }
133
134 #[test]
135 fn availability_zones_table_is_sorted_and_unique() {
136 for pair in AVAILABILITY_ZONES.windows(2) {
137 assert!(
138 pair[0].0 < pair[1].0,
139 "AVAILABILITY_ZONES must be sorted by region: {} !< {}",
140 pair[0].0,
141 pair[1].0
142 );
143 }
144 }
145
146 #[test]
147 fn availability_zones_lookup_matches_region() {
148 assert_eq!(
149 availability_zones_for_region("us-east-1"),
150 Some(["us-east-1a", "us-east-1b", "us-east-1c", "us-east-1d", "us-east-1e", "us-east-1f"].as_slice())
151 );
152 assert_eq!(availability_zones_for_region("us-west-1"), Some(["us-west-1a", "us-west-1c"].as_slice()));
153 assert_eq!(availability_zones_for_region("mars-north-1"), None);
154 }
155
156 #[test]
157 fn is_known_region_covers_gov_cn_and_rejects_unknown() {
158 assert!(is_known_region("us-east-1"));
159 assert!(is_known_region("us-gov-west-1"));
160 assert!(is_known_region("cn-north-1"));
161 assert!(is_known_region("ap-east-2"));
162 assert!(!is_known_region("mars-north-1"));
163 }
164}