aws_smithy_types/config_bag/
storable.rs

1/*
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6use crate::config_bag::value::Value;
7use crate::config_bag::ItemIter;
8use std::fmt::{Debug, Formatter};
9use std::iter::Rev;
10use std::marker::PhantomData;
11use std::slice;
12
13/// Trait defining how types can be stored and loaded from the config bag
14pub trait Store: Sized + Send + Sync + 'static {
15    /// Denote the returned type when loaded from the config bag
16    type ReturnedType<'a>: Send + Sync;
17    /// Denote the stored type when stored into the config bag
18    type StoredType: Send + Sync + Debug;
19
20    /// Create a returned type from an iterable of items
21    fn merge_iter(iter: ItemIter<'_, Self>) -> Self::ReturnedType<'_>;
22}
23
24/// Store an item in the config bag by replacing the existing value
25///
26/// See the [module docs](crate::config_bag) for more documentation.
27#[non_exhaustive]
28pub struct StoreReplace<U>(PhantomData<U>);
29
30impl<U> Debug for StoreReplace<U> {
31    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
32        write!(f, "StoreReplace")
33    }
34}
35
36/// Store an item in the config bag by effectively appending it to a list
37///
38/// See the [module docs](crate::config_bag) for more documentation.
39#[non_exhaustive]
40pub struct StoreAppend<U>(PhantomData<U>);
41
42impl<U> Debug for StoreAppend<U> {
43    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
44        write!(f, "StoreAppend")
45    }
46}
47
48/// Trait that marks the implementing types as able to be stored in the config bag
49///
50/// See the [module docs](crate::config_bag) for more documentation.
51pub trait Storable: Send + Sync + Debug + 'static {
52    /// Specify how an item is stored in the config bag, e.g. [`StoreReplace`] and [`StoreAppend`]
53    type Storer: Store;
54}
55
56impl<U: Send + Sync + Debug + 'static> Store for StoreReplace<U> {
57    type ReturnedType<'a> = Option<&'a U>;
58    type StoredType = Value<U>;
59
60    fn merge_iter(mut iter: ItemIter<'_, Self>) -> Self::ReturnedType<'_> {
61        iter.next().and_then(|item| match item {
62            Value::Set(item) => Some(item),
63            Value::ExplicitlyUnset(_) => None,
64        })
65    }
66}
67
68impl<U: Send + Sync + Debug + 'static> Store for StoreAppend<U> {
69    type ReturnedType<'a> = AppendItemIter<'a, U>;
70    type StoredType = Value<Vec<U>>;
71
72    fn merge_iter(iter: ItemIter<'_, Self>) -> Self::ReturnedType<'_> {
73        AppendItemIter {
74            inner: iter,
75            cur: None,
76        }
77    }
78}
79
80/// Iterator of items returned by [`StoreAppend`]
81pub struct AppendItemIter<'a, U> {
82    inner: ItemIter<'a, StoreAppend<U>>,
83    cur: Option<Rev<slice::Iter<'a, U>>>,
84}
85
86impl<U> Debug for AppendItemIter<'_, U> {
87    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
88        write!(f, "AppendItemIter")
89    }
90}
91
92impl<'a, U: 'a> Iterator for AppendItemIter<'a, U>
93where
94    U: Send + Sync + Debug + 'static,
95{
96    type Item = &'a U;
97
98    fn next(&mut self) -> Option<Self::Item> {
99        if let Some(buf) = &mut self.cur {
100            match buf.next() {
101                Some(item) => return Some(item),
102                None => self.cur = None,
103            }
104        }
105        match self.inner.next() {
106            None => None,
107            Some(Value::Set(u)) => {
108                self.cur = Some(u.iter().rev());
109                self.next()
110            }
111            Some(Value::ExplicitlyUnset(_)) => None,
112        }
113    }
114}