1use std::{collections::BTreeMap, sync::Arc};
8
9use async_trait::async_trait;
10use parking_lot::RwLock;
11use yugendb_core::{
12 Batch, BatchOperation, BatchResult, Capabilities, CollectionName, DeleteOptions, Driver, Key,
13 Namespace, ReadOptions, Result, ScanOptions, StoredValue, WriteOptions, YugenDbError,
14};
15
16#[must_use]
20pub fn memory() -> MemoryDriver {
21 MemoryDriver::new()
22}
23
24#[derive(Debug, Clone, Default)]
26pub struct MemoryDriver {
27 entries: Arc<RwLock<BTreeMap<StorageKey, StoredValue>>>,
28}
29
30impl MemoryDriver {
31 #[must_use]
33 pub fn new() -> Self {
34 Self::default()
35 }
36
37 #[must_use]
42 pub fn len(&self) -> usize {
43 self.entries.read().len()
44 }
45
46 #[must_use]
48 pub fn is_empty(&self) -> bool {
49 self.entries.read().is_empty()
50 }
51
52 pub fn clear(&self) {
54 self.entries.write().clear();
55 }
56}
57
58#[async_trait]
59impl Driver for MemoryDriver {
60 fn name(&self) -> &'static str {
61 "memory"
62 }
63
64 fn capabilities(&self) -> Capabilities {
65 Capabilities::memory()
66 }
67
68 async fn initialise(&self) -> Result<()> {
69 Ok(())
70 }
71
72 async fn finalise(&self) -> Result<()> {
73 Ok(())
74 }
75
76 async fn get(
77 &self,
78 namespace: &Namespace,
79 collection: &CollectionName,
80 key: &Key,
81 options: &ReadOptions,
82 ) -> Result<Option<StoredValue>> {
83 let storage_key = StorageKey::new(namespace, collection, key);
84 let entries = self.entries.read();
85 let Some(value) = entries.get(&storage_key) else {
86 return Ok(None);
87 };
88
89 if value.is_expired() && !options.allow_expired {
90 return Ok(None);
91 }
92
93 Ok(Some(value.clone()))
94 }
95
96 async fn set(
97 &self,
98 namespace: &Namespace,
99 collection: &CollectionName,
100 key: &Key,
101 value: StoredValue,
102 options: &WriteOptions,
103 ) -> Result<()> {
104 let storage_key = StorageKey::new(namespace, collection, key);
105 let mut entries = self.entries.write();
106
107 if !options.overwrite
108 && entries
109 .get(&storage_key)
110 .is_some_and(|existing| !existing.is_expired())
111 {
112 return Err(YugenDbError::conflict(
113 "memory driver refused to overwrite an existing value",
114 ));
115 }
116
117 entries.insert(storage_key, value);
118 Ok(())
119 }
120
121 async fn delete(
122 &self,
123 namespace: &Namespace,
124 collection: &CollectionName,
125 key: &Key,
126 options: &DeleteOptions,
127 ) -> Result<bool> {
128 let storage_key = StorageKey::new(namespace, collection, key);
129 let removed = self.entries.write().remove(&storage_key).is_some();
130
131 if options.must_exist && !removed {
132 return Err(YugenDbError::not_found(
133 "memory driver could not delete a missing value",
134 ));
135 }
136
137 Ok(removed)
138 }
139
140 async fn exists(
141 &self,
142 namespace: &Namespace,
143 collection: &CollectionName,
144 key: &Key,
145 ) -> Result<bool> {
146 let storage_key = StorageKey::new(namespace, collection, key);
147 let entries = self.entries.read();
148 Ok(entries
149 .get(&storage_key)
150 .is_some_and(|value| !value.is_expired()))
151 }
152
153 async fn scan_prefix(
154 &self,
155 namespace: &Namespace,
156 collection: &CollectionName,
157 options: &ScanOptions,
158 ) -> Result<Vec<(Key, StoredValue)>> {
159 let prefix = options.prefix.as_deref();
160 let entries = self.entries.read();
161 let mut results = Vec::new();
162
163 for (storage_key, value) in entries.iter() {
164 if storage_key.namespace != namespace.as_str() {
165 continue;
166 }
167
168 if storage_key.collection != collection.as_str() {
169 continue;
170 }
171
172 if prefix.is_some_and(|prefix| !storage_key.key.starts_with(prefix)) {
173 continue;
174 }
175
176 if value.is_expired() && !options.include_expired {
177 continue;
178 }
179
180 let key = Key::try_from(storage_key.key.as_str())?;
181 results.push((key, value.clone()));
182 }
183
184 results.sort_by(|(left, _), (right, _)| left.cmp(right));
185
186 if let Some(limit) = options.limit {
187 results.truncate(limit);
188 }
189
190 Ok(results)
191 }
192
193 async fn batch(&self, batch: Batch) -> Result<BatchResult> {
194 let mut entries = self.entries.write();
195 let mut set_count = 0;
196 let mut delete_count = 0;
197
198 for operation in batch.into_operations() {
199 match operation {
200 BatchOperation::Set {
201 namespace,
202 collection,
203 key,
204 value,
205 } => {
206 entries.insert(StorageKey::new(&namespace, &collection, &key), value);
207 set_count += 1;
208 }
209 BatchOperation::Delete {
210 namespace,
211 collection,
212 key,
213 } => {
214 if entries
215 .remove(&StorageKey::new(&namespace, &collection, &key))
216 .is_some()
217 {
218 delete_count += 1;
219 }
220 }
221 }
222 }
223
224 Ok(BatchResult::new(set_count, delete_count))
225 }
226}
227
228#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
229struct StorageKey {
230 namespace: String,
231 collection: String,
232 key: String,
233}
234
235impl StorageKey {
236 fn new(namespace: &Namespace, collection: &CollectionName, key: &Key) -> Self {
237 Self {
238 namespace: namespace.as_str().to_owned(),
239 collection: collection.as_str().to_owned(),
240 key: key.as_str().to_owned(),
241 }
242 }
243}