1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0
 */

//! Types and traits for enabling caching

mod expiring_cache;
mod lazy_caching;
mod no_caching;

pub use expiring_cache::ExpiringCache;
pub use lazy_caching::Builder as LazyBuilder;
use no_caching::NoCredentialsCache;

use crate::provider::{future, SharedCredentialsProvider};
use aws_smithy_types::config_bag::{Storable, StoreReplace};
use std::sync::Arc;

/// Asynchronous Cached Credentials Provider
pub trait ProvideCachedCredentials: Send + Sync + std::fmt::Debug {
    /// Returns a future that provides cached credentials.
    fn provide_cached_credentials<'a>(&'a self) -> future::ProvideCredentials<'a>
    where
        Self: 'a;
}

/// Credentials cache wrapper that may be shared
///
/// Newtype wrapper around `ProvideCachedCredentials` that implements `Clone` using an internal
/// `Arc`.
#[derive(Clone, Debug)]
pub struct SharedCredentialsCache(Arc<dyn ProvideCachedCredentials>);

impl SharedCredentialsCache {
    /// Create a new `SharedCredentialsCache` from `ProvideCachedCredentials`
    ///
    /// The given `cache` will be wrapped in an internal `Arc`. If your
    /// cache is already in an `Arc`, use `SharedCredentialsCache::from(cache)` instead.
    pub fn new(provider: impl ProvideCachedCredentials + 'static) -> Self {
        Self(Arc::new(provider))
    }
}

impl AsRef<dyn ProvideCachedCredentials> for SharedCredentialsCache {
    fn as_ref(&self) -> &(dyn ProvideCachedCredentials + 'static) {
        self.0.as_ref()
    }
}

impl From<Arc<dyn ProvideCachedCredentials>> for SharedCredentialsCache {
    fn from(cache: Arc<dyn ProvideCachedCredentials>) -> Self {
        SharedCredentialsCache(cache)
    }
}

impl ProvideCachedCredentials for SharedCredentialsCache {
    fn provide_cached_credentials<'a>(&'a self) -> future::ProvideCredentials<'a>
    where
        Self: 'a,
    {
        self.0.provide_cached_credentials()
    }
}

impl Storable for SharedCredentialsCache {
    type Storer = StoreReplace<SharedCredentialsCache>;
}

#[derive(Clone, Debug)]
pub(crate) enum Inner {
    Lazy(lazy_caching::Builder),
    NoCaching,
}

/// `CredentialsCache` allows for configuring and creating a credentials cache.
///
/// # Examples
///
/// ```no_run
/// use aws_credential_types::Credentials;
/// use aws_credential_types::cache::CredentialsCache;
/// use aws_credential_types::credential_fn::provide_credentials_fn;
/// use aws_credential_types::provider::SharedCredentialsProvider;
///
/// let credentials_cache = CredentialsCache::lazy_builder()
///     .into_credentials_cache()
///     .create_cache(SharedCredentialsProvider::new(provide_credentials_fn(|| async {
///         // An async process to retrieve credentials would go here:
///         Ok(Credentials::new(
///             "example",
///             "example",
///             None,
///             None,
///             "my_provider_name"
///         ))
///     })));
/// ```
#[derive(Clone, Debug)]
pub struct CredentialsCache {
    pub(crate) inner: Inner,
}

impl CredentialsCache {
    /// Creates a [`CredentialsCache`] from the default [`LazyBuilder`].
    pub fn lazy() -> Self {
        Self::lazy_builder().into_credentials_cache()
    }

    /// Returns the default [`LazyBuilder`].
    pub fn lazy_builder() -> LazyBuilder {
        lazy_caching::Builder::new()
    }

    /// Creates a [`CredentialsCache`] that offers no caching ability.
    pub fn no_caching() -> Self {
        Self {
            inner: Inner::NoCaching,
        }
    }

    /// Creates a [`SharedCredentialsCache`] wrapping a concrete caching implementation.
    pub fn create_cache(self, provider: SharedCredentialsProvider) -> SharedCredentialsCache {
        match self.inner {
            Inner::Lazy(builder) => SharedCredentialsCache::new(builder.build(provider)),
            Inner::NoCaching => SharedCredentialsCache::new(NoCredentialsCache::new(provider)),
        }
    }
}

impl Storable for CredentialsCache {
    type Storer = StoreReplace<CredentialsCache>;
}