aws_sdk_secretsmanager/
idempotency_token.rs

1// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
2/*
3 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7use aws_smithy_types::config_bag::{Storable, StoreReplace};
8use std::sync::Mutex;
9
10pub(crate) fn uuid_v4(input: u128) -> String {
11    let mut out = String::with_capacity(36);
12    // u4-aligned index into [input]
13    let mut rnd_idx: u8 = 0;
14    const HEX_CHARS: &[u8; 16] = b"0123456789abcdef";
15
16    for str_idx in 0..36 {
17        if str_idx == 8 || str_idx == 13 || str_idx == 18 || str_idx == 23 {
18            out.push('-');
19        // UUID version character
20        } else if str_idx == 14 {
21            out.push('4');
22        } else {
23            let mut dat: u8 = ((input >> (rnd_idx * 4)) & 0x0F) as u8;
24            // UUID variant bits
25            if str_idx == 19 {
26                dat |= 0b00001000;
27            }
28            rnd_idx += 1;
29            out.push(HEX_CHARS[dat as usize] as char);
30        }
31    }
32    out
33}
34
35/// IdempotencyTokenProvider generates idempotency tokens for idempotent API requests
36///
37/// Generally, customers will not need to interact with this at all. A sensible default will be
38/// provided automatically during config construction. However, if you need deterministic behavior
39/// for testing, two options are available:
40/// 1. Utilize the From<&'static str>` implementation to hard code an idempotency token
41/// 2. Seed the token provider with [`IdempotencyTokenProvider::with_seed`](IdempotencyTokenProvider::with_seed)
42#[derive(Debug)]
43pub struct IdempotencyTokenProvider {
44    inner: Inner,
45}
46
47#[derive(Debug)]
48enum Inner {
49    Static(&'static str),
50    Random(Mutex<fastrand::Rng>),
51}
52
53pub fn default_provider() -> IdempotencyTokenProvider {
54    IdempotencyTokenProvider::random()
55}
56
57impl From<&'static str> for IdempotencyTokenProvider {
58    fn from(token: &'static str) -> Self {
59        Self::fixed(token)
60    }
61}
62
63impl Storable for IdempotencyTokenProvider {
64    type Storer = StoreReplace<IdempotencyTokenProvider>;
65}
66
67impl IdempotencyTokenProvider {
68    pub fn make_idempotency_token(&self) -> String {
69        match &self.inner {
70            Inner::Static(token) => token.to_string(),
71            Inner::Random(rng) => {
72                let input: u128 = rng.lock().unwrap().u128(..);
73                uuid_v4(input)
74            }
75        }
76    }
77
78    pub fn with_seed(seed: u64) -> Self {
79        Self {
80            inner: Inner::Random(Mutex::new(fastrand::Rng::with_seed(seed))),
81        }
82    }
83
84    pub fn random() -> Self {
85        Self {
86            inner: Inner::Random(Mutex::new(fastrand::Rng::new())),
87        }
88    }
89
90    pub fn fixed(token: &'static str) -> Self {
91        Self { inner: Inner::Static(token) }
92    }
93}
94
95impl Clone for IdempotencyTokenProvider {
96    fn clone(&self) -> Self {
97        match &self.inner {
98            Inner::Static(token) => IdempotencyTokenProvider::fixed(token),
99            Inner::Random(_) => IdempotencyTokenProvider::random(),
100        }
101    }
102}