aws_smithy_types/
config_bag.rs

1/*
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6//! Layers and layered bags of configuration data.
7//!
8//! The [`ConfigBag`](crate::config_bag::ConfigBag) structure is used to store and pass around configuration for client operations.
9//! Interacting with it may be required in order to write an `Interceptor` or `RuntimePlugin` to
10//! customize a client.
11//!
12//! A `ConfigBag` is essentially a stack of several immutable and sharable layers, with a single _mutable_ layer at
13//! the top of the stack that is called "interceptor state". The intent of this last mutable layer is to allow for
14//! more performant mutation of config within the execution of an operation.
15//!
16//! There are three separate layer types to be aware of when using a `ConfigBag`:
17//! 1. [`Layer`](crate::config_bag::Layer) - A mutable layer. This is usually only used for adding config
18//!    to the `ConfigBag`, but is also used for the interceptor state.
19//! 2. [`CloneableLayer`](crate::config_bag::CloneableLayer) - Identical to `Layer`, except that it requires
20//!    `Clone` bounds on the items added to it so that it can be deep cloned. Can be converted to a `Layer`
21//!    while retaining the cloneability of its items such that the resulting layer could be cloned as long as
22//!    nothing else is added to it later. A `Layer` cannot be converted back into a `CloneableLayer`.
23//! 3. [`FrozenLayer`](crate::config_bag::FrozenLayer) - Basically an [`Arc`](std::sync::Arc) wrapper around
24//!    a `Layer`. This wrapper is used to make the layer immutable, and to make it shareable between multiple
25//!    `ConfigBag` instances. The frozen layer can be converted back to a `Layer` if there is only a single reference to it.
26//!
27//! All of `Layer`, `CloneableLayer`, `FrozenLayer`, and `ConfigBag` are considered to be "bag" types.
28//! That is, they store arbitrary types so long as they implement the [`Storable`](crate::config_bag::Storable) trait.
29//!
30//! A `Storable` requires a `Storer` to be configured, and the storer allows for storables to be stored
31//! in two different modes:
32//! 1. [`StoreReplace`](crate::config_bag::StoreReplace) - Only one value of this type is allowed in a bag, and
33//!    calling [`store_put()`](crate::config_bag::Layer::store_put) multiple times will replace the existing value
34//!    in the bag. Calling [`load::<T>()`](crate::config_bag::Layer::load) returns exactly one value, if present.
35//! 2. [`StoreAppend`](crate::config_bag::StoreAppend) - Multiple values of this type are allowed in a bag, and
36//!    calling [`store_append()`](crate::config_bag::Layer::store_append) will add an additional value of this type
37//!    to the bag. Calling [`load::<T>()`](crate::config_bag::Layer::load) returns an iterator over multiple values.
38//!
39//! # Examples
40//!
41//! Creating a storable data type with `StoreReplace`:
42//!
43//! ```no_run
44//! use aws_smithy_types::config_bag::{Storable, StoreReplace};
45//!
46//! #[derive(Debug)]
47//! struct SomeDataType {
48//!     some_data: String,
49//! }
50//! impl Storable for SomeDataType {
51//!     type Storer = StoreReplace<Self>;
52//! }
53//! ```
54//!
55//! Creating a storable data type with `StoreAppend`:
56//!
57//! ```no_run
58//! use aws_smithy_types::config_bag::{Storable, StoreAppend};
59//!
60//! #[derive(Debug)]
61//! struct SomeDataType {
62//!     some_data: String,
63//! }
64//! impl Storable for SomeDataType {
65//!     type Storer = StoreAppend<Self>;
66//! }
67//! ```
68//!
69//! Storing a storable in a bag when it is configured for `StoreReplace`:
70//!
71//! ```no_run
72//! # use aws_smithy_types::config_bag::{Storable, StoreReplace};
73//! # #[derive(Clone, Debug)]
74//! # struct SomeDataType { some_data: String }
75//! # impl Storable for SomeDataType { type Storer = StoreReplace<Self>; }
76//! use aws_smithy_types::config_bag::{CloneableLayer, Layer};
77//!
78//! let mut layer = Layer::new("example");
79//! layer.store_put(SomeDataType { some_data: "some data".to_string() });
80//!
81//! // `store_put` can be called again to replace the original value:
82//! layer.store_put(SomeDataType { some_data: "replacement".to_string() });
83//!
84//! // Note: `SomeDataType` below must implement `Clone` to work with `CloneableLayer`
85//! let mut cloneable = CloneableLayer::new("example");
86//! cloneable.store_put(SomeDataType { some_data: "some data".to_string() });
87//! ```
88//!
89//! Storing a storable in a bag when it is configured for `StoreAppend`:
90//!
91//! ```no_run
92//! # use aws_smithy_types::config_bag::{Storable, StoreAppend};
93//! # #[derive(Clone, Debug)]
94//! # struct SomeDataType { some_data: String }
95//! # impl Storable for SomeDataType { type Storer = StoreAppend<Self>; }
96//! use aws_smithy_types::config_bag::{CloneableLayer, Layer};
97//!
98//! let mut layer = Layer::new("example");
99//! layer.store_append(SomeDataType { some_data: "1".to_string() });
100//! layer.store_append(SomeDataType { some_data: "2".to_string() });
101//! ```
102//!
103//! Loading a `StoreReplace` value from a bag:
104//!
105//! ```no_run
106//! # use aws_smithy_types::config_bag::{Storable, StoreReplace};
107//! # #[derive(Clone, Debug)]
108//! # struct SomeDataType { some_data: String }
109//! # impl Storable for SomeDataType { type Storer = StoreReplace<Self>; }
110//! # use aws_smithy_types::config_bag::Layer;
111//! # let layer = Layer::new("example");
112//! let maybe_value: Option<&SomeDataType> = layer.load::<SomeDataType>();
113//! ```
114//!
115//! Loading a `StoreAppend` value from a bag:
116//!
117//! ```no_run
118//! # use aws_smithy_types::config_bag::{Storable, StoreAppend};
119//! # #[derive(Clone, Debug)]
120//! # struct SomeDataType { some_data: String }
121//! # impl Storable for SomeDataType { type Storer = StoreAppend<Self>; }
122//! # use aws_smithy_types::config_bag::Layer;
123//! # let layer = Layer::new("example");
124//! let values: Vec<SomeDataType> = layer.load::<SomeDataType>().cloned().collect();
125//!
126//! // or iterate over them directly:
127//! for value in layer.load::<SomeDataType>() {
128//!     # let _ = value;
129//!     // ...
130//! }
131//! ```
132//!
133mod storable;
134mod typeid_map;
135
136use crate::config_bag::typeid_map::TypeIdMap;
137use crate::type_erasure::TypeErasedBox;
138use std::any::{type_name, TypeId};
139use std::borrow::Cow;
140use std::fmt::{Debug, Formatter};
141use std::iter::Rev;
142use std::marker::PhantomData;
143use std::ops::Deref;
144use std::slice::Iter;
145use std::sync::Arc;
146
147pub use storable::{AppendItemIter, Storable, Store, StoreAppend, StoreReplace};
148
149/// [`FrozenLayer`] is the immutable and shareable form of [`Layer`].
150///
151/// See the [module docs](crate::config_bag) for more documentation.
152#[derive(Clone, Debug)]
153#[must_use]
154pub struct FrozenLayer(Arc<Layer>);
155
156impl FrozenLayer {
157    /// Attempts to convert this bag directly into a [`Layer`] if no other references exist.
158    pub fn try_modify(self) -> Option<Layer> {
159        Arc::try_unwrap(self.0).ok()
160    }
161}
162
163impl Deref for FrozenLayer {
164    type Target = Layer;
165
166    fn deref(&self) -> &Self::Target {
167        &self.0
168    }
169}
170
171impl From<Layer> for FrozenLayer {
172    fn from(layer: Layer) -> Self {
173        FrozenLayer(Arc::new(layer))
174    }
175}
176
177/// Private module to keep Value type while avoiding "private type in public latest"
178pub(crate) mod value {
179    #[derive(Clone, Debug)]
180    pub enum Value<T> {
181        Set(T),
182        ExplicitlyUnset(&'static str),
183    }
184
185    impl<T: Default> Default for Value<T> {
186        fn default() -> Self {
187            Self::Set(Default::default())
188        }
189    }
190}
191use value::Value;
192
193/// [`CloneableLayer`] allows itself to be cloned. This is useful when a type that implements
194/// `Clone` wishes to store a config layer.
195///
196/// It ensures that all the items in `CloneableLayer` are `Clone` upon entry, e.g. when they are
197/// first stored, the mutable methods require that they have a `Clone` bound on them.
198///
199/// While [`FrozenLayer`] is also cloneable, which is a shallow clone via `Arc`, `CloneableLayer`
200/// performs a deep clone that newly allocates all the items stored in it.
201///
202/// Cloneable enforces that non clone items cannot be added
203/// ```rust,compile_fail
204/// use aws_smithy_types::config_bag::Storable;
205/// use aws_smithy_types::config_bag::StoreReplace;
206/// use aws_smithy_types::config_bag::CloneableLayer;
207/// #[derive(Debug)]
208/// struct MyNotCloneStruct;
209///
210/// impl Storable for MyNotCloneStruct {
211///     type Storer = StoreReplace<MyNotCloneStruct>;
212/// }
213/// let mut layer = CloneableLayer::new("layer");
214/// layer.store_put(MyNotCloneStruct);
215/// ```
216///
217/// See the [module docs](crate::config_bag) for more documentation.
218#[derive(Debug, Default)]
219pub struct CloneableLayer(Layer);
220
221impl Deref for CloneableLayer {
222    type Target = Layer;
223
224    fn deref(&self) -> &Self::Target {
225        &self.0
226    }
227}
228
229impl Clone for CloneableLayer {
230    fn clone(&self) -> Self {
231        Self(
232            self.try_clone()
233                .expect("only cloneable types can be inserted"),
234        )
235    }
236}
237
238impl From<CloneableLayer> for Layer {
239    fn from(cloneable_layer: CloneableLayer) -> Layer {
240        cloneable_layer.0
241    }
242}
243
244// We need to "override" the mutable methods to encode the information that an item being stored
245// implements `Clone`. For the immutable methods, they can just be delegated via the `Deref` trait.
246impl CloneableLayer {
247    /// Creates a new `CloneableLayer` with a given name
248    pub fn new(name: impl Into<Cow<'static, str>>) -> Self {
249        Self(Layer::new(name))
250    }
251
252    /// Converts this layer into a frozen layer that can no longer be mutated.
253    pub fn freeze(self) -> FrozenLayer {
254        self.0.into()
255    }
256
257    /// Removes `T` from this bag
258    pub fn unset<T: Send + Sync + Clone + Debug + 'static>(&mut self) -> &mut Self {
259        self.put_directly_cloneable::<StoreReplace<T>>(Value::ExplicitlyUnset(type_name::<T>()));
260        self
261    }
262
263    fn put_directly_cloneable<T: Store>(&mut self, value: T::StoredType) -> &mut Self
264    where
265        T::StoredType: Clone,
266    {
267        self.0.props.insert(
268            TypeId::of::<T::StoredType>(),
269            TypeErasedBox::new_with_clone(value),
270        );
271        self
272    }
273
274    /// Stores `item` of type `T` into the config bag, overriding a previous value of the same type
275    pub fn store_put<T>(&mut self, item: T) -> &mut Self
276    where
277        T: Storable<Storer = StoreReplace<T>> + Clone,
278    {
279        self.put_directly_cloneable::<StoreReplace<T>>(Value::Set(item));
280        self
281    }
282
283    /// Stores `item` of type `T` into the config bag, overriding a previous value of the same type,
284    /// or unsets it by passing a `None`
285    pub fn store_or_unset<T>(&mut self, item: Option<T>) -> &mut Self
286    where
287        T: Storable<Storer = StoreReplace<T>> + Clone,
288    {
289        let item = match item {
290            Some(item) => Value::Set(item),
291            None => Value::ExplicitlyUnset(type_name::<T>()),
292        };
293        self.put_directly_cloneable::<StoreReplace<T>>(item);
294        self
295    }
296
297    /// Stores `item` of type `T` into the config bag, appending it to the existing list of the same
298    /// type
299    pub fn store_append<T>(&mut self, item: T) -> &mut Self
300    where
301        T: Storable<Storer = StoreAppend<T>> + Clone,
302    {
303        match self.get_mut_or_default::<StoreAppend<T>>() {
304            Value::Set(list) => list.push(item),
305            v @ Value::ExplicitlyUnset(_) => *v = Value::Set(vec![item]),
306        }
307        self
308    }
309
310    /// Clears the value of type `T` from the config bag
311    pub fn clear<T>(&mut self)
312    where
313        T: Storable<Storer = StoreAppend<T>> + Clone,
314    {
315        self.put_directly_cloneable::<StoreAppend<T>>(Value::ExplicitlyUnset(type_name::<T>()));
316    }
317
318    fn get_mut_or_default<T: Send + Sync + Store + 'static>(&mut self) -> &mut T::StoredType
319    where
320        T::StoredType: Default + Clone,
321    {
322        self.0
323            .props
324            .entry(TypeId::of::<T::StoredType>())
325            .or_insert_with(|| TypeErasedBox::new_with_clone(T::StoredType::default()))
326            .downcast_mut()
327            .expect("typechecked")
328    }
329}
330
331/// A named layer comprising a config bag
332///
333/// See the [module docs](crate::config_bag) for more documentation.
334#[derive(Default)]
335pub struct Layer {
336    name: Cow<'static, str>,
337    props: TypeIdMap<TypeErasedBox>,
338}
339
340impl Debug for Layer {
341    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
342        struct Items<'a>(&'a Layer);
343        impl Debug for Items<'_> {
344            fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
345                f.debug_list().entries(self.0.props.values()).finish()
346            }
347        }
348        f.debug_struct("Layer")
349            .field("name", &self.name)
350            .field("items", &Items(self))
351            .finish()
352    }
353}
354
355impl Layer {
356    fn try_clone(&self) -> Option<Self> {
357        let new_props = self
358            .props
359            .iter()
360            .flat_map(|(tyid, erased)| erased.try_clone().map(|e| (*tyid, e)))
361            .collect::<TypeIdMap<_>>();
362        if new_props.len() == self.props.len() {
363            Some(Layer {
364                name: self.name.clone(),
365                props: new_props,
366            })
367        } else {
368            None
369        }
370    }
371
372    /// Inserts `value` into the layer directly
373    fn put_directly<T: Store>(&mut self, value: T::StoredType) -> &mut Self {
374        self.props
375            .insert(TypeId::of::<T::StoredType>(), TypeErasedBox::new(value));
376        self
377    }
378
379    /// Returns true if this layer is empty.
380    pub fn is_empty(&self) -> bool {
381        self.props.is_empty()
382    }
383
384    /// Converts this layer into a frozen layer that can no longer be mutated.
385    pub fn freeze(self) -> FrozenLayer {
386        self.into()
387    }
388
389    /// Create a new Layer with a given name
390    pub fn new(name: impl Into<Cow<'static, str>>) -> Self {
391        let name = name.into();
392        Self {
393            name,
394            props: Default::default(),
395        }
396    }
397
398    /// Changes the name of this layer.
399    pub fn with_name(self, name: impl Into<Cow<'static, str>>) -> Self {
400        Self {
401            name: name.into(),
402            props: self.props,
403        }
404    }
405
406    /// Load a storable item from the bag
407    pub fn load<T: Storable>(&self) -> <T::Storer as Store>::ReturnedType<'_> {
408        T::Storer::merge_iter(ItemIter {
409            inner: BagIter {
410                head: Some(self),
411                tail: [].iter().rev(),
412            },
413            t: Default::default(),
414        })
415    }
416
417    /// Remove `T` from this bag
418    pub fn unset<T: Send + Sync + Debug + 'static>(&mut self) -> &mut Self {
419        self.put_directly::<StoreReplace<T>>(Value::ExplicitlyUnset(type_name::<T>()));
420        self
421    }
422
423    /// Stores `item` of type `T` into the config bag, overriding a previous value of the same type
424    pub fn store_put<T>(&mut self, item: T) -> &mut Self
425    where
426        T: Storable<Storer = StoreReplace<T>>,
427    {
428        self.put_directly::<StoreReplace<T>>(Value::Set(item));
429        self
430    }
431
432    /// Stores `item` of type `T` into the config bag, overriding a previous value of the same type,
433    /// or unsets it by passing a `None`
434    pub fn store_or_unset<T>(&mut self, item: Option<T>) -> &mut Self
435    where
436        T: Storable<Storer = StoreReplace<T>>,
437    {
438        let item = match item {
439            Some(item) => Value::Set(item),
440            None => Value::ExplicitlyUnset(type_name::<T>()),
441        };
442        self.put_directly::<StoreReplace<T>>(item);
443        self
444    }
445
446    /// This can only be used for types that use [`StoreAppend`]
447    /// ```
448    /// use aws_smithy_types::config_bag::{ConfigBag, Layer, Storable, StoreAppend, StoreReplace};
449    /// let mut layer_1 = Layer::new("example");
450    /// #[derive(Debug, PartialEq, Eq)]
451    /// struct Interceptor(&'static str);
452    /// impl Storable for Interceptor {
453    ///     type Storer = StoreAppend<Interceptor>;
454    /// }
455    ///
456    /// layer_1.store_append(Interceptor("321"));
457    /// layer_1.store_append(Interceptor("654"));
458    ///
459    /// let mut layer_2 = Layer::new("second layer");
460    /// layer_2.store_append(Interceptor("987"));
461    ///
462    /// let bag = ConfigBag::of_layers(vec![layer_1, layer_2]);
463    ///
464    /// assert_eq!(
465    ///     bag.load::<Interceptor>().collect::<Vec<_>>(),
466    ///     vec![&Interceptor("987"), &Interceptor("654"), &Interceptor("321")]
467    /// );
468    /// ```
469    pub fn store_append<T>(&mut self, item: T) -> &mut Self
470    where
471        T: Storable<Storer = StoreAppend<T>>,
472    {
473        match self.get_mut_or_default::<StoreAppend<T>>() {
474            Value::Set(list) => list.push(item),
475            v @ Value::ExplicitlyUnset(_) => *v = Value::Set(vec![item]),
476        }
477        self
478    }
479
480    /// Clears the value of type `T` from the config bag
481    ///
482    /// This internally marks the item of type `T` as cleared as opposed to wiping it out from the
483    /// config bag.
484    pub fn clear<T>(&mut self)
485    where
486        T: Storable<Storer = StoreAppend<T>>,
487    {
488        self.put_directly::<StoreAppend<T>>(Value::ExplicitlyUnset(type_name::<T>()));
489    }
490
491    /// Retrieves the value of type `T` from this layer if exists
492    fn get<T: Send + Sync + Store + 'static>(&self) -> Option<&T::StoredType> {
493        self.props
494            .get(&TypeId::of::<T::StoredType>())
495            .map(|t| t.downcast_ref().expect("typechecked"))
496    }
497
498    /// Returns a mutable reference to `T` if it is stored in this layer
499    fn get_mut<T: Send + Sync + Store + 'static>(&mut self) -> Option<&mut T::StoredType> {
500        self.props
501            .get_mut(&TypeId::of::<T::StoredType>())
502            .map(|t| t.downcast_mut().expect("typechecked"))
503    }
504
505    /// Returns a mutable reference to `T` if it is stored in this layer, otherwise returns the
506    /// [`Default`] implementation of `T`
507    fn get_mut_or_default<T: Send + Sync + Store + 'static>(&mut self) -> &mut T::StoredType
508    where
509        T::StoredType: Default,
510    {
511        self.props
512            .entry(TypeId::of::<T::StoredType>())
513            .or_insert_with(|| TypeErasedBox::new(T::StoredType::default()))
514            .downcast_mut()
515            .expect("typechecked")
516    }
517}
518
519/// Layered configuration structure
520///
521/// See the [module docs](crate::config_bag) for more documentation.
522#[must_use]
523pub struct ConfigBag {
524    interceptor_state: Layer,
525    tail: Vec<FrozenLayer>,
526}
527
528impl Debug for ConfigBag {
529    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
530        struct Layers<'a>(&'a ConfigBag);
531        impl Debug for Layers<'_> {
532            fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
533                f.debug_list().entries(self.0.layers()).finish()
534            }
535        }
536        f.debug_struct("ConfigBag")
537            .field("layers", &Layers(self))
538            .finish()
539    }
540}
541
542impl ConfigBag {
543    /// Create a new config bag "base".
544    pub fn base() -> Self {
545        ConfigBag {
546            interceptor_state: Layer {
547                name: Cow::Borrowed("interceptor_state"),
548                props: Default::default(),
549            },
550            tail: vec![],
551        }
552    }
553
554    /// Create a [`ConfigBag`] consisting of the given layers.
555    pub fn of_layers(layers: impl IntoIterator<Item = Layer>) -> Self {
556        let mut bag = ConfigBag::base();
557        for layer in layers {
558            bag.push_layer(layer);
559        }
560        bag
561    }
562
563    /// Add the given layer to the config bag.
564    pub fn push_layer(&mut self, layer: Layer) -> &mut Self {
565        self.tail.push(layer.freeze());
566        self
567    }
568
569    /// Add a frozen/shared layer to the config bag.
570    pub fn push_shared_layer(&mut self, layer: FrozenLayer) -> &mut Self {
571        self.tail.push(layer);
572        self
573    }
574
575    /// Return a mutable reference to the interceptor state.
576    pub fn interceptor_state(&mut self) -> &mut Layer {
577        &mut self.interceptor_state
578    }
579
580    /// Load a value (or values) of type `T` depending on how `T` implements [`Storable`]
581    pub fn load<T: Storable>(&self) -> <T::Storer as Store>::ReturnedType<'_> {
582        self.sourced_get::<T::Storer>()
583    }
584
585    /// Return a mutable reference to `T` if found within the interceptor state.
586    ///
587    /// This method does not search the tail of the config bag (i.e., the collection of frozen layers).
588    ///
589    /// If the caller is unsure whether `T` exists in the interceptor state,
590    /// consider using [`Self::get_mut`] instead, which requires `T` to implement `Clone`, however.
591    pub fn get_mut_from_interceptor_state<T>(&mut self) -> Option<&mut T>
592    where
593        T: Storable<Storer = StoreReplace<T>> + Send + Sync + Debug + 'static,
594    {
595        match self.interceptor_state.get_mut::<StoreReplace<T>>() {
596            Some(Value::ExplicitlyUnset(_)) => None,
597            Some(Value::Set(t)) => Some(t),
598            None => None,
599        }
600    }
601
602    /// Return a mutable reference to `T` if found within the config bag
603    ///
604    /// This method requires `T` to implement `Clone` because, if the requested item is found in the tail of the config bag,
605    /// it will be cloned and moved to the head (i.e., the interceptor state).
606    ///
607    /// If the caller is certain that `T` already exists in the interceptor state,
608    /// consider using [`Self::get_mut_from_interceptor_state`] instead, which does not require `T` to be `Clone`.
609    pub fn get_mut<T>(&mut self) -> Option<&mut T>
610    where
611        T: Storable<Storer = StoreReplace<T>> + Send + Sync + Debug + Clone + 'static,
612    {
613        if self
614            .interceptor_state
615            .get_mut::<StoreReplace<T>>()
616            .is_none()
617        {
618            let new_item = match self.tail.iter().find_map(|b| b.load::<T>()) {
619                Some(item) => item.clone(),
620                None => return None,
621            };
622            self.interceptor_state.store_put(new_item);
623        }
624        self.get_mut_from_interceptor_state()
625    }
626
627    /// Returns a mutable reference to `T` if it is stored in the top layer of the bag
628    ///
629    /// - If `T` is in a deeper layer of the bag, that value will be cloned and inserted into the top layer
630    /// - If `T` is not present in the bag, the [`Default`] implementation will be used.
631    pub fn get_mut_or_default<T>(&mut self) -> &mut T
632    where
633        T: Storable<Storer = StoreReplace<T>> + Send + Sync + Debug + Clone + Default + 'static,
634    {
635        self.get_mut_or_else(|| T::default())
636    }
637
638    /// Returns a mutable reference to `T` if it is stored in the top layer of the bag
639    ///
640    /// - If `T` is in a deeper layer of the bag, that value will be cloned and inserted into the top layer
641    /// - If `T` is not present in the bag, `default` will be used to construct a new value
642    pub fn get_mut_or_else<T>(&mut self, default: impl Fn() -> T) -> &mut T
643    where
644        T: Storable<Storer = StoreReplace<T>> + Send + Sync + Debug + Clone + 'static,
645    {
646        // this code looks weird to satisfy the borrow checker—we can't keep the result of `get_mut`
647        // alive (even in a returned branch) and then call `store_put`. So: drop the borrow immediately
648        // store, the value, then pull it right back
649        if self.get_mut::<T>().is_none() {
650            self.interceptor_state.store_put((default)());
651            return self
652                .get_mut()
653                .expect("item was just stored in the top layer");
654        }
655        // above it was None
656        self.get_mut().unwrap()
657    }
658
659    /// Add another layer to this configuration bag
660    ///
661    /// Hint: If you want to re-use this layer, call `freeze` first.
662    ///
663    /// # Examples
664    /// ```
665    /// use aws_smithy_types::config_bag::{ConfigBag, Layer, Storable, StoreReplace};
666    ///
667    /// #[derive(Debug, Eq, PartialEq)]
668    /// struct ExampleStr(&'static str);
669    /// impl Storable for ExampleStr {
670    ///     type Storer = StoreReplace<Self>;
671    /// }
672    ///
673    /// #[derive(Debug, Eq, PartialEq)]
674    /// struct ExampleInt(i32);
675    /// impl Storable for ExampleInt {
676    ///     type Storer = StoreReplace<Self>;
677    /// }
678    ///
679    /// let mut bag = ConfigBag::base();
680    /// bag = bag.with_fn("first", |layer: &mut Layer| { layer.store_put(ExampleStr("a")); });
681    ///
682    /// // We can now load the example string out
683    /// assert_eq!(bag.load::<ExampleStr>(), Some(&ExampleStr("a")));
684    ///
685    /// // But there isn't a number stored in the bag yet
686    /// assert_eq!(bag.load::<ExampleInt>(), None);
687    ///
688    /// // Add a layer with an example int
689    /// bag = bag.with_fn("second", |layer: &mut Layer| { layer.store_put(ExampleInt(1)); });
690    ///
691    /// // Now the example int can be retrieved
692    /// assert_eq!(bag.load::<ExampleInt>(), Some(&ExampleInt(1)));
693    /// ```
694    pub fn with_fn(
695        self,
696        name: impl Into<Cow<'static, str>>,
697        next: impl Fn(&mut Layer),
698    ) -> ConfigBag {
699        let mut new_layer = Layer::new(name);
700        next(&mut new_layer);
701        let ConfigBag {
702            interceptor_state: head,
703            mut tail,
704        } = self;
705        tail.push(head.freeze());
706        ConfigBag {
707            interceptor_state: new_layer,
708            tail,
709        }
710    }
711
712    /// Add a new layer with `name` after freezing the top layer so far
713    pub fn add_layer(self, name: impl Into<Cow<'static, str>>) -> ConfigBag {
714        self.with_fn(name, |_| {})
715    }
716
717    /// Return a value (or values) of type `T` depending on how it has been stored in a `ConfigBag`
718    ///
719    /// It flexibly chooses to return a single value vs. an iterator of values depending on how
720    /// `T` implements a [`Store`] trait.
721    pub fn sourced_get<T: Store>(&self) -> T::ReturnedType<'_> {
722        let stored_type_iter = ItemIter {
723            inner: self.layers(),
724            t: PhantomData,
725        };
726        T::merge_iter(stored_type_iter)
727    }
728
729    fn layers(&self) -> BagIter<'_> {
730        BagIter {
731            head: Some(&self.interceptor_state),
732            tail: self.tail.iter().rev(),
733        }
734    }
735}
736
737/// Iterator of items returned from [`ConfigBag`].
738pub struct ItemIter<'a, T> {
739    inner: BagIter<'a>,
740    t: PhantomData<T>,
741}
742
743impl<'a, T> Debug for ItemIter<'a, T> {
744    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
745        write!(f, "ItemIter")
746    }
747}
748
749impl<'a, T: 'a> Iterator for ItemIter<'a, T>
750where
751    T: Store,
752{
753    type Item = &'a T::StoredType;
754
755    fn next(&mut self) -> Option<Self::Item> {
756        match self.inner.next() {
757            Some(layer) => layer.get::<T>().or_else(|| self.next()),
758            None => None,
759        }
760    }
761}
762
763/// Iterator over the layers of a config bag
764struct BagIter<'a> {
765    head: Option<&'a Layer>,
766    tail: Rev<Iter<'a, FrozenLayer>>,
767}
768
769impl<'a> Iterator for BagIter<'a> {
770    type Item = &'a Layer;
771
772    fn next(&mut self) -> Option<Self::Item> {
773        if let Some(head) = self.head.take() {
774            Some(head)
775        } else {
776            self.tail.next().map(|t| t.deref())
777        }
778    }
779}
780
781#[cfg(test)]
782mod test {
783    use super::ConfigBag;
784    use crate::config_bag::{CloneableLayer, Layer, Storable, StoreAppend, StoreReplace};
785
786    #[test]
787    fn layered_property_bag() {
788        #[derive(Debug)]
789        struct Prop1;
790        impl Storable for Prop1 {
791            type Storer = StoreReplace<Self>;
792        }
793        #[derive(Debug)]
794        struct Prop2;
795        impl Storable for Prop2 {
796            type Storer = StoreReplace<Self>;
797        }
798        let layer_a = |bag: &mut Layer| {
799            bag.store_put(Prop1);
800        };
801
802        let layer_b = |bag: &mut Layer| {
803            bag.store_put(Prop2);
804        };
805
806        #[derive(Debug)]
807        struct Prop3;
808        impl Storable for Prop3 {
809            type Storer = StoreReplace<Self>;
810        }
811
812        let mut base_bag = ConfigBag::base()
813            .with_fn("a", layer_a)
814            .with_fn("b", layer_b);
815        base_bag.interceptor_state().store_put(Prop3);
816        assert!(base_bag.load::<Prop1>().is_some());
817
818        #[derive(Debug)]
819        struct Prop4;
820        impl Storable for Prop4 {
821            type Storer = StoreReplace<Self>;
822        }
823
824        let layer_c = |bag: &mut Layer| {
825            bag.store_put(Prop4);
826            bag.unset::<Prop3>();
827        };
828
829        let final_bag = base_bag.with_fn("c", layer_c);
830
831        assert!(final_bag.load::<Prop4>().is_some());
832        assert!(final_bag.load::<Prop1>().is_some());
833        assert!(final_bag.load::<Prop2>().is_some());
834        // we unset prop3
835        assert!(final_bag.load::<Prop3>().is_none());
836        println!("{:#?}", final_bag);
837    }
838
839    #[test]
840    fn config_bag() {
841        let bag = ConfigBag::base();
842        #[derive(Debug)]
843        struct Region(&'static str);
844        impl Storable for Region {
845            type Storer = StoreReplace<Self>;
846        }
847        let bag = bag.with_fn("service config", |layer: &mut Layer| {
848            layer.store_put(Region("asdf"));
849        });
850
851        assert_eq!(bag.load::<Region>().unwrap().0, "asdf");
852
853        #[derive(Debug)]
854        struct SigningName(&'static str);
855        impl Storable for SigningName {
856            type Storer = StoreReplace<Self>;
857        }
858        let operation_config = bag.with_fn("operation", |layer: &mut Layer| {
859            layer.store_put(SigningName("s3"));
860        });
861
862        assert_eq!(operation_config.load::<SigningName>().unwrap().0, "s3");
863
864        #[derive(Debug)]
865        struct Prop;
866        impl Storable for Prop {
867            type Storer = StoreReplace<Self>;
868        }
869        let mut open_bag = operation_config.with_fn("my_custom_info", |_bag: &mut Layer| {});
870        open_bag.interceptor_state().store_put(Prop);
871
872        assert_eq!(open_bag.layers().count(), 4);
873    }
874
875    #[test]
876    fn store_append() {
877        let mut layer = Layer::new("test");
878        #[derive(Debug, PartialEq, Eq)]
879        struct Interceptor(&'static str);
880        impl Storable for Interceptor {
881            type Storer = StoreAppend<Interceptor>;
882        }
883
884        layer.clear::<Interceptor>();
885        // you can only call store_append because interceptor is marked with a vec
886        layer.store_append(Interceptor("123"));
887        layer.store_append(Interceptor("456"));
888
889        let mut second_layer = Layer::new("next");
890        second_layer.store_append(Interceptor("789"));
891
892        let mut bag = ConfigBag::of_layers(vec![layer, second_layer]);
893
894        assert_eq!(
895            bag.load::<Interceptor>().collect::<Vec<_>>(),
896            vec![
897                &Interceptor("789"),
898                &Interceptor("456"),
899                &Interceptor("123")
900            ]
901        );
902
903        let mut final_layer = Layer::new("final");
904        final_layer.clear::<Interceptor>();
905        bag.push_layer(final_layer);
906        assert_eq!(bag.load::<Interceptor>().count(), 0);
907    }
908
909    #[test]
910    fn store_append_many_layers() {
911        #[derive(Debug, PartialEq, Eq, Clone)]
912        struct TestItem(i32, i32);
913        impl Storable for TestItem {
914            type Storer = StoreAppend<TestItem>;
915        }
916        let mut expected = vec![];
917        let mut bag = ConfigBag::base();
918        for layer_idx in 0..100 {
919            let mut layer = Layer::new(format!("{}", layer_idx));
920            for item in 0..100 {
921                expected.push(TestItem(layer_idx, item));
922                layer.store_append(TestItem(layer_idx, item));
923            }
924            bag.push_layer(layer);
925        }
926        expected.reverse();
927        assert_eq!(
928            bag.load::<TestItem>().cloned().collect::<Vec<_>>(),
929            expected
930        );
931    }
932
933    #[test]
934    fn adding_layers() {
935        let mut layer_1 = Layer::new("layer1");
936
937        let mut layer_2 = Layer::new("layer2");
938
939        #[derive(Clone, Debug, PartialEq, Eq, Default)]
940        struct Foo(usize);
941        impl Storable for Foo {
942            type Storer = StoreReplace<Foo>;
943        }
944
945        layer_1.store_put(Foo(0));
946        layer_2.store_put(Foo(1));
947
948        let layer_1 = layer_1.freeze();
949        let layer_2 = layer_2.freeze();
950
951        let mut bag_1 = ConfigBag::base();
952        let mut bag_2 = ConfigBag::base();
953        bag_1
954            .push_shared_layer(layer_1.clone())
955            .push_shared_layer(layer_2.clone());
956        bag_2.push_shared_layer(layer_2).push_shared_layer(layer_1);
957
958        // bags have same layers but in different orders
959        assert_eq!(bag_1.load::<Foo>(), Some(&Foo(1)));
960        assert_eq!(bag_2.load::<Foo>(), Some(&Foo(0)));
961
962        bag_1.interceptor_state().store_put(Foo(3));
963        assert_eq!(bag_1.load::<Foo>(), Some(&Foo(3)));
964    }
965
966    #[test]
967    fn get_mut_or_else() {
968        #[derive(Clone, Debug, PartialEq, Eq, Default)]
969        struct Foo(usize);
970        impl Storable for Foo {
971            type Storer = StoreReplace<Foo>;
972        }
973
974        let mut bag = ConfigBag::base();
975        assert_eq!(bag.get_mut::<Foo>(), None);
976        assert_eq!(bag.get_mut_or_default::<Foo>(), &Foo(0));
977        bag.get_mut_or_default::<Foo>().0 += 1;
978        assert_eq!(bag.load::<Foo>(), Some(&Foo(1)));
979
980        let old_ref = bag.load::<Foo>().unwrap();
981        assert_eq!(old_ref, &Foo(1));
982
983        // there is one in the bag, so it can be returned
984        //let mut next = bag.add_layer("next");
985        bag.get_mut::<Foo>().unwrap().0 += 1;
986        let new_ref = bag.load::<Foo>().unwrap();
987        assert_eq!(new_ref, &Foo(2));
988
989        bag.interceptor_state().unset::<Foo>();
990        // if it was unset, we can't clone the current one, that would be wrong
991        assert_eq!(bag.get_mut::<Foo>(), None);
992        assert_eq!(bag.get_mut_or_default::<Foo>(), &Foo(0));
993    }
994
995    #[test]
996    fn get_mut_from_interceptor_state() {
997        // excludes `Clone` to verify `get_mut_from_interceptor_state` works with types without the `Clone` trait
998        #[derive(Debug, PartialEq, Eq, Default)]
999        struct Foo(usize);
1000        impl Storable for Foo {
1001            type Storer = StoreReplace<Self>;
1002        }
1003
1004        #[derive(Clone, Debug, PartialEq, Eq, Default)]
1005        struct Bar(usize);
1006        impl Storable for Bar {
1007            type Storer = StoreReplace<Self>;
1008        }
1009
1010        let mut bag = ConfigBag::base();
1011        assert!(bag.get_mut_from_interceptor_state::<Foo>().is_none());
1012
1013        bag.interceptor_state().store_put(Foo(1));
1014        assert_eq!(
1015            bag.get_mut_from_interceptor_state::<Foo>(),
1016            Some(&mut Foo(1))
1017        );
1018
1019        // `Bar` is stored in the tail of the config bag.
1020        let mut layer = Layer::new("test");
1021        layer.store_put(Bar(1));
1022        bag.push_layer(layer);
1023
1024        // the method under test should not find `Bar`, as it does not reside in the interceptor state.
1025        assert!(bag.get_mut_from_interceptor_state::<Bar>().is_none());
1026    }
1027
1028    #[test]
1029    fn cloning_layers() {
1030        #[derive(Clone, Debug)]
1031        struct TestStr(String);
1032        impl Storable for TestStr {
1033            type Storer = StoreReplace<TestStr>;
1034        }
1035        let mut layer_1 = CloneableLayer::new("layer_1");
1036        let expected_str = "I can be cloned";
1037        layer_1.store_put(TestStr(expected_str.to_owned()));
1038        let layer_1_cloned = layer_1.clone();
1039        assert_eq!(expected_str, &layer_1_cloned.load::<TestStr>().unwrap().0);
1040
1041        // Should still be cloneable after unsetting a field
1042        layer_1.unset::<TestStr>();
1043        assert!(layer_1.try_clone().unwrap().load::<TestStr>().is_none());
1044
1045        // It is cloneable multiple times in succession
1046        let _ = layer_1
1047            .try_clone()
1048            .expect("clone 1")
1049            .try_clone()
1050            .expect("clone 2");
1051
1052        #[derive(Clone, Debug)]
1053        struct Rope(String);
1054        impl Storable for Rope {
1055            type Storer = StoreAppend<Rope>;
1056        }
1057        let mut layer_2 = CloneableLayer::new("layer_2");
1058        layer_2.store_append(Rope("A".to_owned()));
1059        layer_2.store_append(Rope("big".to_owned()));
1060        layer_2.store_append(Rope("rope".to_owned()));
1061        let layer_2_cloned = layer_2.clone();
1062        let rope = layer_2_cloned.load::<Rope>().cloned().collect::<Vec<_>>();
1063        assert_eq!(
1064            "A big rope",
1065            rope.iter()
1066                .rev()
1067                .map(|r| r.0.clone())
1068                .collect::<Vec<_>>()
1069                .join(" ")
1070        );
1071    }
1072}