aws_smithy_runtime/client/
config_override.rs1use aws_smithy_async::rt::sleep::SharedAsyncSleep;
7use aws_smithy_runtime_api::client::runtime_components::RuntimeComponentsBuilder;
8use aws_smithy_types::config_bag::{
9 CloneableLayer, FrozenLayer, Layer, Storable, Store, StoreReplace,
10};
11
12macro_rules! component {
13 ($typ:ty, $accessor:ident, $latest_accessor:ident, $doc:tt) => {
14 #[doc = $doc]
15 pub fn $accessor(&self) -> Option<$typ> {
16 fallback_component!(self, $typ, $accessor)
17 }
18
19 #[doc = $doc]
20 pub fn $latest_accessor(&self) -> Option<$typ> {
21 latest_component!(self, $typ, $accessor)
22 }
23 };
24}
25macro_rules! fallback_component {
26 ($self:ident, $typ:ty, $accessor:ident) => {
27 match &$self.inner {
28 Inner::Initial(initial) => initial.components.$accessor(),
29 Inner::Override(overrid) => overrid
30 .components
31 .$accessor()
32 .or_else(|| overrid.initial_components.$accessor()),
33 }
34 };
35}
36macro_rules! latest_component {
37 ($self:ident, $typ:ty, $accessor:ident) => {
38 match &$self.inner {
39 Inner::Initial(initial) => initial.components.$accessor(),
40 Inner::Override(overrid) => overrid.components.$accessor(),
41 }
42 };
43}
44
45struct Initial<'a> {
46 config: &'a mut CloneableLayer,
47 components: &'a mut RuntimeComponentsBuilder,
48}
49
50struct Override<'a> {
51 initial_config: FrozenLayer,
52 initial_components: &'a RuntimeComponentsBuilder,
53 config: &'a mut CloneableLayer,
54 components: &'a mut RuntimeComponentsBuilder,
55}
56
57enum Inner<'a> {
58 Initial(Initial<'a>),
59 Override(Override<'a>),
60}
61
62pub struct Resolver<'a> {
76 inner: Inner<'a>,
77}
78
79impl<'a> Resolver<'a> {
80 pub fn initial(
82 config: &'a mut CloneableLayer,
83 components: &'a mut RuntimeComponentsBuilder,
84 ) -> Self {
85 Self {
86 inner: Inner::Initial(Initial { config, components }),
87 }
88 }
89
90 pub fn overrid(
92 initial_config: FrozenLayer,
93 initial_components: &'a RuntimeComponentsBuilder,
94 config: &'a mut CloneableLayer,
95 components: &'a mut RuntimeComponentsBuilder,
96 ) -> Self {
97 Self {
98 inner: Inner::Override(Override {
99 initial_config,
100 initial_components,
101 config,
102 components,
103 }),
104 }
105 }
106
107 pub fn is_initial(&self) -> bool {
109 matches!(self.inner, Inner::Initial(_))
110 }
111
112 pub fn config_mut(&mut self) -> &mut CloneableLayer {
114 match &mut self.inner {
115 Inner::Initial(initial) => initial.config,
116 Inner::Override(overrid) => overrid.config,
117 }
118 }
119
120 pub fn runtime_components_mut(&mut self) -> &mut RuntimeComponentsBuilder {
122 match &mut self.inner {
123 Inner::Initial(initial) => initial.components,
124 Inner::Override(overrid) => overrid.components,
125 }
126 }
127
128 pub fn is_latest_set<T>(&self) -> bool
132 where
133 T: Storable<Storer = StoreReplace<T>>,
134 {
135 self.config().load::<T>().is_some()
136 }
137
138 pub fn is_set<T>(&self) -> bool
140 where
141 T: Storable<Storer = StoreReplace<T>>,
142 {
143 match &self.inner {
144 Inner::Initial(initial) => initial.config.load::<T>().is_some(),
145 Inner::Override(overrid) => {
146 overrid.initial_config.load::<T>().is_some() || overrid.config.load::<T>().is_some()
147 }
148 }
149 }
150
151 pub fn resolve_config<T>(&self) -> <T::Storer as Store>::ReturnedType<'_>
153 where
154 T: Storable<Storer = StoreReplace<T>>,
155 {
156 let mut maybe_value = self.config().load::<T>();
157 if maybe_value.is_none() {
158 if let Inner::Override(overrid) = &self.inner {
160 maybe_value = overrid.initial_config.load::<T>()
161 }
162 }
163 maybe_value
164 }
165
166 component!(
168 SharedAsyncSleep,
169 sleep_impl,
170 latest_sleep_impl,
171 "The async sleep implementation."
172 );
173
174 fn config(&self) -> &Layer {
175 match &self.inner {
176 Inner::Initial(initial) => initial.config,
177 Inner::Override(overrid) => overrid.config,
178 }
179 }
180}
181
182#[cfg(test)]
183mod tests {
184 use super::*;
185 use aws_smithy_types::config_bag::CloneableLayer;
186
187 #[derive(Clone, Debug)]
188 struct TestStorable(String);
189 impl Storable for TestStorable {
190 type Storer = StoreReplace<Self>;
191 }
192
193 #[test]
194 fn initial_mode_config() {
195 let mut config = CloneableLayer::new("test");
196 let mut components = RuntimeComponentsBuilder::new("test");
197
198 let mut resolver = Resolver::initial(&mut config, &mut components);
199 assert!(resolver.is_initial());
200 assert!(!resolver.is_latest_set::<TestStorable>());
201 assert!(!resolver.is_set::<TestStorable>());
202 assert!(resolver.resolve_config::<TestStorable>().is_none());
203
204 resolver.config_mut().store_put(TestStorable("test".into()));
205 assert!(resolver.is_latest_set::<TestStorable>());
206 assert!(resolver.is_set::<TestStorable>());
207 assert_eq!("test", resolver.resolve_config::<TestStorable>().unwrap().0);
208 }
209
210 #[test]
211 fn override_mode_config() {
212 let mut initial_config = CloneableLayer::new("initial");
213 let initial_components = RuntimeComponentsBuilder::new("initial");
214 let mut config = CloneableLayer::new("override");
215 let mut components = RuntimeComponentsBuilder::new("override");
216
217 let resolver = Resolver::overrid(
218 initial_config.clone().freeze(),
219 &initial_components,
220 &mut config,
221 &mut components,
222 );
223 assert!(!resolver.is_initial());
224 assert!(!resolver.is_latest_set::<TestStorable>());
225 assert!(!resolver.is_set::<TestStorable>());
226 assert!(resolver.resolve_config::<TestStorable>().is_none());
227
228 initial_config.store_put(TestStorable("test".into()));
229 let resolver = Resolver::overrid(
230 initial_config.clone().freeze(),
231 &initial_components,
232 &mut config,
233 &mut components,
234 );
235 assert!(!resolver.is_latest_set::<TestStorable>());
236 assert!(resolver.is_set::<TestStorable>());
237 assert_eq!("test", resolver.resolve_config::<TestStorable>().unwrap().0);
238
239 initial_config.unset::<TestStorable>();
240 config.store_put(TestStorable("test".into()));
241 let resolver = Resolver::overrid(
242 initial_config.clone().freeze(),
243 &initial_components,
244 &mut config,
245 &mut components,
246 );
247 assert!(resolver.is_latest_set::<TestStorable>());
248 assert!(resolver.is_set::<TestStorable>());
249 assert_eq!("test", resolver.resolve_config::<TestStorable>().unwrap().0);
250
251 initial_config.store_put(TestStorable("override me".into()));
252 config.store_put(TestStorable("override".into()));
253 let resolver = Resolver::overrid(
254 initial_config.freeze(),
255 &initial_components,
256 &mut config,
257 &mut components,
258 );
259 assert!(resolver.is_latest_set::<TestStorable>());
260 assert!(resolver.is_set::<TestStorable>());
261 assert_eq!(
262 "override",
263 resolver.resolve_config::<TestStorable>().unwrap().0
264 );
265 }
266}