1#![cfg_attr(not(feature = "std"), no_std)]
2#![allow(non_upper_case_globals)]
3#![allow(non_camel_case_types)]
4#![allow(non_snake_case)]
5#![allow(clippy::all)]
6
7#![doc = include_str!("../README.md")]
8
9#[cfg(feature = "alloc")]
10extern crate alloc;
11
12pub mod error;
13pub mod kvdb;
14pub mod tsdb;
16pub mod utils;
17
18use core::ffi::c_void;
19
20use embedded_storage::nor_flash::NorFlash;
21
22#[cfg(feature = "std")]
23pub mod storage;
24#[cfg(feature = "std")]
25pub use storage::StdStorage;
26
27pub use error::*;
28
29pub use kvdb::*;
30pub use tsdb::*;
31pub use utils::*;
32
33include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
34
35pub struct SyncWrapper<T>(pub T);
38unsafe impl<T> Sync for SyncWrapper<T> {}
39
40#[macro_export]
61macro_rules! define_default_kvs {
62 ($name:ident, $($key:expr => $value:expr),* $(,)?) => {
63 static KVS_ARRAY: &[$crate::SyncWrapper<$crate::fdb_default_kv_node>] = &[
64 $(
65 $crate::SyncWrapper($crate::fdb_default_kv_node {
66 key: concat!($key, "\0").as_ptr() as *mut _,
67 value: $value.as_ptr() as *mut _,
68 value_len: $value.len(),
69 }),
70 )*
71 ];
72
73 #[allow(non_upper_case_globals)]
74 pub static $name: $crate::SyncWrapper<$crate::fdb_default_kv> = $crate::SyncWrapper($crate::fdb_default_kv {
75 kvs: KVS_ARRAY.as_ptr() as *mut $crate::fdb_default_kv_node,
76 num: KVS_ARRAY.len(),
77 });
78 };
79}
80
81pub trait RawHandle {
82 type Handle;
83
84 fn handle(&self) -> Self::Handle;
87}
88
89#[no_mangle]
91#[cfg(feature = "log")]
92pub extern "C" fn rust_log(message: *const core::ffi::c_char) {
93 let c_str = unsafe { core::ffi::CStr::from_ptr(message) };
94 if let Ok(message_str) = c_str.to_str() {
95 log::log!(log::Level::Info, "{message_str}");
97 }
98}
99
100#[doc(hidden)]
101#[repr(C)]
102pub struct FlashVTable {
103 pub read:
104 unsafe extern "C" fn(storage: *mut c_void, addr: u32, buf: *mut u8, size: usize) -> i32,
105 pub write:
106 unsafe extern "C" fn(storage: *mut c_void, addr: u32, buf: *const u8, size: usize) -> i32,
107 pub erase: unsafe extern "C" fn(storage: *mut c_void, addr: u32, size: usize) -> i32,
108}
109
110#[doc(hidden)]
112#[repr(C)]
113pub struct FlashDispatch {
114 pub vtable: FlashVTable,
115 pub instance: *mut c_void,
116}
117
118impl FlashDispatch {
119 pub fn new<T: NorFlash>() -> Self {
120 return Self {
121 vtable: FlashVTable {
122 read: vtable_read::<T>,
123 write: vtable_write::<T>,
124 erase: vtable_erase::<T>,
125 },
126 instance: core::ptr::null_mut(),
127 };
128 }
129}
130
131unsafe extern "C" fn vtable_read<F: NorFlash>(
133 storage: *mut c_void,
134 addr: u32,
135 buf: *mut u8,
136 size: usize,
137) -> i32 {
138 let flash = &mut *(storage as *mut F);
139 let slice = core::slice::from_raw_parts_mut(buf, size);
140 match flash.read(addr, slice) {
141 Ok(_) => 0,
142 Err(_) => -1,
143 }
144}
145
146unsafe extern "C" fn vtable_write<F: NorFlash>(
147 storage: *mut c_void,
148 addr: u32,
149 buf: *const u8,
150 size: usize,
151) -> i32 {
152 let flash = &mut *(storage as *mut F);
153 let slice = core::slice::from_raw_parts(buf, size);
154 match flash.write(addr, slice) {
155 Ok(_) => 0,
156 Err(_) => -1,
157 }
158}
159
160unsafe extern "C" fn vtable_erase<F: NorFlash>(
161 storage: *mut c_void,
162 addr: u32,
163 size: usize,
164) -> i32 {
165 let flash = &mut *(storage as *mut F);
166 match flash.erase(addr, addr + size as u32) {
167 Ok(_) => 0,
168 Err(_) => -1,
169 }
170}
171
172#[no_mangle]
173pub unsafe extern "C" fn fdb_custom_read(
174 db: fdb_db_t,
175 addr: u32,
176 buf: *mut c_void,
177 size: usize,
178) -> fdb_err_t {
179 let dispatch = &*((*db).user_data as *const FlashDispatch);
180 let result = (dispatch.vtable.read)(dispatch.instance, addr, buf as *mut u8, size);
181 if result == 0 {
182 crate::fdb_err_t_FDB_NO_ERR
183 } else {
184 crate::fdb_err_t_FDB_READ_ERR
185 }
186}
187
188#[no_mangle]
189pub unsafe extern "C" fn fdb_custom_write(
190 db: fdb_db_t,
191 addr: u32,
192 buf: *const c_void,
193 size: usize,
194 _sync: bool,
195) -> fdb_err_t {
196 let dispatch = &*((*db).user_data as *const FlashDispatch);
197 let result = (dispatch.vtable.write)(dispatch.instance, addr, buf as *const u8, size);
198 if result == 0 {
199 crate::fdb_err_t_FDB_NO_ERR
200 } else {
201 crate::fdb_err_t_FDB_WRITE_ERR
202 }
203}
204
205#[no_mangle]
206pub unsafe extern "C" fn fdb_custom_erase(db: fdb_db_t, addr: u32, size: usize) -> fdb_err_t {
207 let dispatch = &*((*db).user_data as *const FlashDispatch);
208 let result = (dispatch.vtable.erase)(dispatch.instance, addr, size);
209 if result == 0 {
210 crate::fdb_err_t_FDB_NO_ERR
211 } else {
212 crate::fdb_err_t_FDB_ERASE_ERR
213 }
214}