1use std::marker::PhantomData;
21use std::sync::Arc;
22
23use serde::{de::DeserializeOwned, Serialize};
24use zeroize::Zeroizing;
25
26use crate::codec::{decode_value, encode_value, KeyDecode, KeyEncode};
27use crate::crypto::{open_row, seal_row, unwrap_dek, wrap_fresh_dek, KeyProvider, WrappedDek, KEY_LEN};
28use crate::engine::{Durability, KvEngine, Readable, WriteTx};
29use crate::error::{StoreError, StoreResult};
30use crate::table::Table;
31
32pub const DEK_WRAPPINGS_TABLE: &str = "_dek_wrappings";
36
37fn wrappings_table() -> Table<String, WrappedDek> {
38 Table::new(DEK_WRAPPINGS_TABLE)
39}
40
41pub struct Collection<K, V> {
44 name: String,
45 schema_version: u32,
46 wrapped_dek: WrappedDek,
48 key_provider: Arc<dyn KeyProvider>,
49 _types: PhantomData<fn() -> (K, V)>,
50}
51
52impl<K, V> std::fmt::Debug for Collection<K, V> {
53 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54 f.debug_struct("Collection")
56 .field("name", &self.name)
57 .field("schema_version", &self.schema_version)
58 .finish_non_exhaustive()
59 }
60}
61
62impl<K, V> Collection<K, V>
63where
64 K: KeyEncode + KeyDecode,
65 V: Serialize + DeserializeOwned,
66{
67 pub fn open<E: KvEngine>(
70 engine: &E,
71 key_provider: Arc<dyn KeyProvider>,
72 name: impl Into<String>,
73 schema_version: u32,
74 ) -> StoreResult<Self> {
75 let name = Self::checked_name(name)?;
76 let r = engine.begin_read()?;
77 let wrapped = wrappings_table()
78 .get(&r, &name)?
79 .ok_or_else(|| StoreError::CollectionNotFound(name.clone()))?;
80 Ok(Self::assemble(name, schema_version, wrapped, key_provider))
81 }
82
83 pub fn open_or_create<E: KvEngine>(
87 engine: &E,
88 key_provider: Arc<dyn KeyProvider>,
89 name: impl Into<String>,
90 schema_version: u32,
91 ) -> StoreResult<Self> {
92 let name = Self::checked_name(name)?;
93 let table = wrappings_table();
94
95 let mut w = engine.begin_write(Durability::Immediate)?;
96 if let Some(existing) = table.get(&w, &name)? {
97 drop(w);
99 return Ok(Self::assemble(name, schema_version, existing, key_provider));
100 }
101
102 let vault_key = key_provider.vault_key()?;
104 let (wrapped, _dek) = wrap_fresh_dek(&vault_key, &name)?;
105 table.put(&mut w, &name, &wrapped)?;
106 w.commit()?;
107
108 Ok(Self::assemble(name, schema_version, wrapped, key_provider))
109 }
110
111 fn assemble(
112 name: String,
113 schema_version: u32,
114 wrapped_dek: WrappedDek,
115 key_provider: Arc<dyn KeyProvider>,
116 ) -> Self {
117 Self {
118 name,
119 schema_version,
120 wrapped_dek,
121 key_provider,
122 _types: PhantomData,
123 }
124 }
125
126 fn checked_name(name: impl Into<String>) -> StoreResult<String> {
127 let name = name.into();
128 if name.starts_with('_') {
129 return Err(StoreError::ReservedName(name));
130 }
131 Ok(name)
132 }
133
134 pub fn name(&self) -> &str {
136 &self.name
137 }
138
139 pub fn schema_version(&self) -> u32 {
141 self.schema_version
142 }
143
144 fn dek(&self) -> StoreResult<Zeroizing<[u8; KEY_LEN]>> {
147 let vault_key = self.key_provider.vault_key()?;
148 Ok(unwrap_dek(&vault_key, &self.name, &self.wrapped_dek)?)
149 }
150
151 pub fn get(&self, tx: &impl Readable, key: &K) -> StoreResult<Option<V>> {
155 let key_bytes = key.encode();
156 let sealed = match tx.get_raw(&self.name, &key_bytes)? {
157 Some(bytes) => bytes,
158 None => return Ok(None),
159 };
160 let dek = self.dek()?;
161 let plain = open_row(&dek, &self.name, &key_bytes, self.schema_version, &sealed)?;
162 Ok(Some(decode_value(&plain)?))
163 }
164
165 pub fn put(&self, tx: &mut impl WriteTx, key: &K, value: &V) -> StoreResult<()> {
167 let key_bytes = key.encode();
168 let dek = self.dek()?;
169 let sealed = seal_row(
170 &dek,
171 &self.name,
172 &key_bytes,
173 self.schema_version,
174 &encode_value(value)?,
175 )?;
176 tx.put_raw(&self.name, &key_bytes, &sealed)
177 }
178
179 pub fn delete(&self, tx: &mut impl WriteTx, key: &K) -> StoreResult<bool> {
182 tx.delete_raw(&self.name, &key.encode())
183 }
184
185 pub fn range(&self, tx: &impl Readable, lo: &K, hi: &K) -> StoreResult<Vec<(K, V)>> {
188 let raw = tx.range_raw(&self.name, &lo.encode(), &hi.encode())?;
189 if raw.is_empty() {
190 return Ok(Vec::new());
191 }
192 let dek = self.dek()?;
193 raw.into_iter()
194 .map(|(key_bytes, sealed)| {
195 let plain = open_row(&dek, &self.name, &key_bytes, self.schema_version, &sealed)?;
196 Ok((K::decode(&key_bytes)?, decode_value(&plain)?))
197 })
198 .collect()
199 }
200}