Skip to main content

chio_guards/response_sanitization/
vault.rs

1use std::collections::HashMap;
2use std::sync::Mutex;
3
4use super::formatting::fingerprint;
5
6// ---------------------------------------------------------------------------
7// Tokenize store: opaque-id -> original mapping.
8// ---------------------------------------------------------------------------
9
10/// Shared token vault used by the `Tokenize` redaction strategy.
11#[derive(Debug, Default)]
12pub struct TokenVault {
13    inner: Mutex<TokenVaultInner>,
14}
15
16#[derive(Debug, Default)]
17struct TokenVaultInner {
18    counter: u64,
19    map: HashMap<String, String>,
20}
21
22impl TokenVault {
23    pub fn new() -> Self {
24        Self::default()
25    }
26
27    pub fn insert(&self, value: &str) -> String {
28        let mut inner = match self.inner.lock() {
29            Ok(g) => g,
30            Err(poisoned) => poisoned.into_inner(),
31        };
32        inner.counter = inner.counter.saturating_add(1);
33        let fp = fingerprint(value);
34        let id = format!("tok_{}_{}", inner.counter, fp);
35        inner.map.insert(id.clone(), value.to_string());
36        id
37    }
38
39    pub fn get(&self, token: &str) -> Option<String> {
40        let inner = match self.inner.lock() {
41            Ok(g) => g,
42            Err(poisoned) => poisoned.into_inner(),
43        };
44        inner.map.get(token).cloned()
45    }
46
47    pub fn len(&self) -> usize {
48        let inner = match self.inner.lock() {
49            Ok(g) => g,
50            Err(poisoned) => poisoned.into_inner(),
51        };
52        inner.map.len()
53    }
54
55    pub fn is_empty(&self) -> bool {
56        self.len() == 0
57    }
58}