1use std::{any::TypeId, collections::HashMap};
7
8#[derive(Clone, Debug, Default, Eq, PartialEq)]
10#[non_exhaustive]
11pub enum CloudConfiguration {
12 #[default]
14 AzurePublic,
15
16 AzureGovernment,
18
19 AzureChina,
21
22 Custom(CustomConfiguration),
43}
44
45#[derive(Clone, Debug, Default, Eq, PartialEq)]
47#[non_exhaustive]
48pub struct CustomConfiguration {
49 pub authority_host: String,
51
52 pub audiences: Audiences,
54}
55
56impl From<CustomConfiguration> for CloudConfiguration {
57 fn from(config: CustomConfiguration) -> Self {
58 Self::Custom(config)
59 }
60}
61
62#[derive(Clone, Debug, Default, Eq, PartialEq)]
64pub struct Audiences(HashMap<TypeId, String>);
65
66impl Audiences {
67 pub fn new() -> Self {
69 Self(HashMap::new())
70 }
71
72 pub fn get<T: 'static>(&self) -> Option<&str> {
74 self.0.get(&TypeId::of::<T>()).map(|s| s.as_str())
75 }
76
77 pub fn insert<T: 'static>(&mut self, audience: String) {
79 self.0.insert(TypeId::of::<T>(), audience);
80 }
81
82 pub fn with<T: 'static>(mut self, audience: String) -> Self {
84 self.0.insert(TypeId::of::<T>(), audience);
85 self
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[test]
94 fn custom() {
95 struct A;
96 struct B;
97 struct C;
98
99 let cloud = CustomConfiguration {
100 authority_host: "https://login.mycloud.local".to_string(),
101 audiences: Audiences::new()
102 .with::<A>("A".to_string())
103 .with::<B>("B".to_string()),
104 }
105 .into();
106
107 let CloudConfiguration::Custom(mut custom) = cloud else {
108 unreachable!();
109 };
110
111 assert_eq!(custom.authority_host, "https://login.mycloud.local");
112 assert_eq!(custom.audiences.get::<A>(), Some("A"));
113 assert_eq!(custom.audiences.get::<B>(), Some("B"));
114 assert_eq!(custom.audiences.get::<C>(), None);
115
116 custom.audiences.insert::<C>("C".to_string());
117 assert_eq!(custom.audiences.get::<C>(), Some("C"));
118 }
119
120 #[test]
121 fn default() {
122 assert_eq!(
123 CloudConfiguration::AzurePublic,
124 CloudConfiguration::default()
125 );
126 }
127}