1mod reader;
2pub use reader::*;
3mod types;
4pub use types::*;
5mod iter;
6pub use iter::*;
7
8use crate::{
9 fdb_blob, fdb_blob__bindgen_ty_1, fdb_blob_read, fdb_db_t, fdb_kv, fdb_kv_del, fdb_kv_get_obj,
10 fdb_kv_set_blob, fdb_kv_set_default, fdb_kvdb, fdb_kvdb_control_read, fdb_kvdb_control_write,
11 fdb_kvdb_deinit, fdb_kvdb_init, Error, FlashDispatch, RawHandle, FDB_KVDB_CTRL_SET_MAX_SIZE,
12 FDB_KVDB_CTRL_SET_NOT_FORMAT, FDB_KVDB_CTRL_SET_SEC_SIZE, FDB_KV_NAME_MAX,
13};
14use core::{
15 ffi::{c_char, c_void, CStr},
16 marker::PhantomData,
17};
18
19use embedded_storage::nor_flash::NorFlash;
20
21pub struct KVDB<S: NorFlash> {
22 inner: fdb_kvdb,
23 storage: S,
24 user_data: FlashDispatch,
25 key_buf: [u8; FDB_KV_NAME_MAX as usize + 1],
26 #[cfg(feature = "log")]
27 name_buf: [u8; FDB_KV_NAME_MAX as usize + 1],
28 initialized: bool,
29 _marker: PhantomData<*const ()>, }
32
33#[cfg(feature = "std")]
34impl KVDB<crate::storage::StdStorage> {
35 pub fn new_file(
47 name: &str,
48 path: &str,
49 sec_size: u32,
50 max_size: u32,
51 default_kvs: Option<&'static crate::fdb_default_kv>,
52 ) -> Result<Box<Self>, Error> {
53 let storage = crate::storage::StdStorage::new(
54 path,
55 name,
56 sec_size,
57 max_size,
58 crate::storage::FileStrategy::Multi,
59 )?;
60
61 let mut db = Box::new(KVDB::new(storage));
62 db.set_name(name)?;
63 db.init(default_kvs)?;
64 Ok(db)
65 }
66}
67
68impl<S: NorFlash> KVDB<S> {
69 pub fn new(storage: S) -> Self {
77 Self {
78 inner: Default::default(),
79 storage,
80 user_data: FlashDispatch::new::<S>(),
81 key_buf: [0; FDB_KV_NAME_MAX as usize + 1],
82 #[cfg(feature = "log")]
83 name_buf: [0; FDB_KV_NAME_MAX as usize + 1],
84 initialized: false,
85 _marker: PhantomData,
86 }
87 }
88
89 pub fn set_name(&mut self, name: &str) -> Result<(), Error> {
93 if name.len() > FDB_KV_NAME_MAX as usize {
94 return Err(Error::KvNameError);
95 }
96 #[cfg(feature = "log")]
97 {
98 self.name_buf[..name.len()].copy_from_slice(name.as_bytes());
99 self.name_buf[name.len()] = b'\0';
100 }
101 Ok(())
102 }
103
104 pub fn set_not_formatable(&mut self, enable: bool) {
109 self.fdb_kvdb_control_write(FDB_KVDB_CTRL_SET_NOT_FORMAT, enable);
110 }
111
112 pub fn not_formatable(&mut self) -> bool {
114 let mut enable = false;
115 self.fdb_kvdb_control_read(FDB_KVDB_CTRL_SET_NOT_FORMAT, &mut enable);
116 return enable;
117 }
118 pub fn init(
127 &mut self,
128 default_kvs: Option<&'static crate::fdb_default_kv>,
129 ) -> Result<(), Error> {
130 if self.initialized {
131 return Ok(());
132 }
133 let sec_size = S::ERASE_SIZE as u32;
135 let max_size = self.storage.capacity() as u32;
136
137 unsafe {
138 let db_ptr = self.handle() as fdb_db_t;
139 (*db_ptr).mode = crate::fdb_storage_type_FDB_STORAGE_CUSTOM;
140
141 self.fdb_kvdb_control_write(FDB_KVDB_CTRL_SET_SEC_SIZE, sec_size);
143 self.fdb_kvdb_control_write(FDB_KVDB_CTRL_SET_MAX_SIZE, max_size);
144
145 self.user_data.instance = &mut self.storage as *mut _ as *mut c_void;
147
148 #[cfg(feature = "log")]
149 let name = self.name_buf.as_ptr() as *const c_char;
150 #[cfg(not(feature = "log"))]
151 let name = b"\0".as_ptr() as *const c_char;
152
153 let default_kvs_ptr = match default_kvs {
154 Some(kvs) => kvs as *const _ as *mut _,
155 None => core::ptr::null_mut(),
156 };
157
158 let result = fdb_kvdb_init(
159 db_ptr as *mut fdb_kvdb,
160 name,
161 core::ptr::null(),
162 default_kvs_ptr,
163 &mut self.user_data as *mut _ as *mut c_void,
164 );
165
166 if result == crate::fdb_err_t_FDB_NO_ERR {
167 self.initialized = true;
168 Ok(())
169 } else {
170 Err(result.into())
171 }
172 }
173 }
174}
175impl<S: NorFlash> KVDB<S> {
176 fn to_cstr(&mut self, key: &str) -> Result<&CStr, Error> {
178 let key_len = key.len();
179 if key_len > FDB_KV_NAME_MAX as usize {
180 return Err(Error::KvNameError);
181 }
182 self.key_buf[..key_len].copy_from_slice(key.as_bytes());
183 self.key_buf[key_len] = 0;
184 Ok(unsafe { CStr::from_bytes_with_nul_unchecked(&self.key_buf[..key_len + 1]) })
186 }
187
188 #[inline]
190 fn fdb_kv_get_obj(&mut self, key: &str) -> Result<Option<KVEntry>, Error> {
191 let handle = self.handle();
192 let cstr_key = self.to_cstr(key)?;
193 let mut kv_obj = unsafe { core::mem::zeroed::<fdb_kv>() };
194 if unsafe { fdb_kv_get_obj(handle, cstr_key.as_ptr(), &mut kv_obj) }
196 == core::ptr::null_mut()
197 {
198 return Ok(None);
199 };
200 Ok(Some(kv_obj.into()))
201 }
202
203 #[inline]
205 fn fdb_blob_write(&mut self, key: &str, blob: &mut fdb_blob) -> Result<(), Error> {
206 let handle = self.handle();
207 let cstr_key = self.to_cstr(key)?;
208 Error::convert(unsafe { fdb_kv_set_blob(handle, cstr_key.as_ptr(), blob) })
209 }
210
211 #[inline]
213 fn fdb_blob_read(&mut self, blob: &mut fdb_blob) -> usize {
214 unsafe { fdb_blob_read(self.handle() as *mut _, blob) }
215 }
216
217 #[inline]
219 fn fdb_kvdb_control_write<T>(&mut self, cmd: u32, arg: T) {
220 fdb_kvdb_control_write(self.handle(), cmd, arg)
221 }
222
223 #[inline]
225 #[allow(dead_code)]
226 fn fdb_kvdb_control_read<T>(&self, cmd: u32, arg: &mut T) {
227 fdb_kvdb_control_read(self.handle(), cmd, arg)
228 }
229}
230
231impl<S: NorFlash> KVDB<S> {
232 pub fn set(&mut self, key: &str, value: &[u8]) -> Result<(), Error> {
240 let mut blob = fdb_blob_make_write(value); self.fdb_blob_write(key, &mut blob)
242 }
243
244 #[cfg(feature = "alloc")]
254 pub fn get(&mut self, key: &str) -> Result<Option<alloc::vec::Vec<u8>>, Error> {
255 match self.fdb_kv_get_obj(key)? {
256 Some(kv) => match kv.status() {
257 KVStatus::PRE_WRITE | KVStatus::Write => {
259 let mut data: alloc::vec::Vec<u8> =
262 alloc::vec::Vec::with_capacity(kv.value_len());
263 unsafe { data.set_len(kv.value_len()) }; let mut blob = fdb_blob_make_by(&mut data, &kv.into(), 0);
267
268 let read_len = self.fdb_blob_read(&mut blob);
270 if read_len != data.len() {
271 return Err(Error::ReadError);
272 }
273 Ok(Some(data))
274 }
275 _ => Ok(None), },
277 None => return Ok(None), }
279 }
280
281 pub fn delete(&mut self, key: &str) -> Result<(), Error> {
285 let handle = self.handle();
286 let cstr_key = self.to_cstr(key)?;
287 Error::convert(unsafe { fdb_kv_del(handle, cstr_key.as_ptr()) })
288 }
289
290 pub fn reset(&mut self) -> Result<(), Error> {
297 Error::convert(unsafe { fdb_kv_set_default(self.handle()) })
298 }
299
300 pub fn get_reader<'a>(&'_ mut self, key: &str) -> Result<KVReader<'_, S>, Error> {
304 let handle = self.handle();
305 let cstr_key = self.to_cstr(key)?;
306 let mut kv_obj = unsafe { core::mem::zeroed::<fdb_kv>() };
307 if unsafe { fdb_kv_get_obj(handle, cstr_key.as_ptr(), &mut kv_obj) }
308 == core::ptr::null_mut()
309 {
310 return Err(Error::ReadError);
311 };
312
313 Ok(KVReader::new(self, kv_obj.into()))
314 }
315
316 pub fn iter(&mut self) -> KVDBIterator<'_, S> {
317 KVDBIterator::new(self)
318 }
319}
320
321impl<S: NorFlash> RawHandle for KVDB<S> {
322 type Handle = *mut fdb_kvdb;
323 fn handle(&self) -> Self::Handle {
324 &self.inner as *const _ as *mut _
325 }
326}
327
328impl<S: NorFlash> Drop for KVDB<S> {
329 fn drop(&mut self) {
330 if self.initialized {
331 unsafe {
332 fdb_kvdb_deinit(self.handle());
333 }
334 }
335 }
336}
337
338pub fn fdb_blob_make_by(v: &mut [u8], kv: &KVEntry, offset: usize) -> fdb_blob {
339 fdb_blob {
340 buf: v.as_mut_ptr() as *mut _,
341 size: v.len(),
342 saved: fdb_blob__bindgen_ty_1 {
343 meta_addr: kv.inner.addr.start,
344 addr: kv.inner.addr.value + offset as u32,
345 len: kv.inner.value_len as usize - offset,
346 },
347 }
348}
349
350pub fn fdb_blob_make_read(v: &mut [u8]) -> fdb_blob {
351 fdb_blob {
352 buf: v.as_mut_ptr() as *mut _,
353 size: v.len(),
354 saved: unsafe { core::mem::zeroed() },
355 }
356}
357pub fn fdb_blob_make_write(v: &[u8]) -> fdb_blob {
358 fdb_blob {
359 buf: v.as_ptr() as *const _ as *mut _,
360 size: v.len(),
361 saved: unsafe { core::mem::zeroed() },
362 }
363}