#![warn(unsafe_op_in_unsafe_fn)]
#![allow(non_camel_case_types)]
#![allow(unused_unsafe)]
use ffizz_passby::Boxed;
use ffizz_string::{fz_string_t as kvstore_string_t, FzString};
use std::collections::HashMap;
ffizz_header::snippet! {
#[ffizz(name="header", order=0)]
}
pub struct Store {
map: HashMap<String, String>,
}
impl Store {
fn new() -> Store {
Store {
map: HashMap::new(),
}
}
fn get(&self, key: &str) -> Option<&str> {
self.map.get(key).map(|v| &**v)
}
fn set(&mut self, key: impl Into<String>, value: impl Into<String>) {
self.map.insert(key.into(), value.into());
}
fn del(&mut self, key: &str) {
self.map.remove(key);
}
}
#[ffizz_header::item]
#[ffizz(order = 10)]
#[allow(non_camel_case_types)]
type kvstore_t = Store;
type BoxedStore = Boxed<Store>;
#[ffizz_header::item]
#[ffizz(order = 20)]
#[no_mangle]
pub unsafe extern "C" fn kvstore_new() -> *mut kvstore_t {
let store = Store::new();
unsafe { BoxedStore::return_val(store) }
}
#[ffizz_header::item]
#[ffizz(order = 21)]
#[no_mangle]
pub unsafe extern "C" fn kvstore_free(store: *mut kvstore_t) {
let store = unsafe { BoxedStore::take_nonnull(store) };
drop(store); }
#[ffizz_header::item]
#[ffizz(order = 30)]
#[no_mangle]
pub unsafe extern "C" fn kvstore_get(
store: *mut kvstore_t,
key: *mut kvstore_string_t,
) -> kvstore_string_t {
unsafe {
BoxedStore::with_ref_nonnull(store, |store| {
match unsafe {
FzString::with_ref_mut(key, |key| {
if let Ok(Some(key)) = key.as_str() {
store.get(key)
} else {
None }
})
} {
Some(val) => unsafe { FzString::return_val(FzString::String(val.to_string())) },
None => unsafe { FzString::return_val(FzString::Null) },
}
})
}
}
#[ffizz_header::item]
#[ffizz(order = 30)]
#[no_mangle]
pub unsafe extern "C" fn kvstore_set(
store: *mut kvstore_t,
key: *mut kvstore_string_t,
val: *mut kvstore_string_t,
) -> bool {
unsafe {
BoxedStore::with_ref_mut_nonnull(store, |store| {
let (key, val) = unsafe { (FzString::take_ptr(key), FzString::take_ptr(val)) };
if let Ok(Some(key)) = key.into_string() {
if let Ok(Some(val)) = val.into_string() {
store.set(key, val);
return true;
}
}
false
})
}
}
#[ffizz_header::item]
#[ffizz(order = 30)]
#[no_mangle]
pub unsafe extern "C" fn kvstore_del(store: *mut kvstore_t, key: *mut kvstore_string_t) -> bool {
unsafe {
FzString::with_ref_mut(key, move |key| {
unsafe {
BoxedStore::with_ref_mut_nonnull(store, move |store| {
if let Ok(Some(key)) = key.as_str() {
store.del(key);
true
} else {
false
}
})
}
})
}
}
ffizz_header::snippet! {
#[ffizz(name="kvstore_string_t", order=100)]
}
#[ffizz_header::item]
#[ffizz(order = 110)]
pub use ffizz_string::fz_string_clone as kvstore_string_clone;
#[ffizz_header::item]
#[ffizz(order = 110)]
pub use ffizz_string::fz_string_content as kvstore_string_content;
#[ffizz_header::item]
#[ffizz(order = 110)]
pub use ffizz_string::fz_string_free as kvstore_string_free;
#[ffizz_header::item]
#[ffizz(order = 110)]
pub use ffizz_string::fz_string_is_null as kvstore_string_is_null;
fn main() {
let store = unsafe { kvstore_new() };
fn fzstr(s: &str) -> kvstore_string_t {
use std::ffi::CString;
let cstr = CString::new(s).unwrap();
unsafe { kvstore_string_clone(cstr.as_ptr()) }
}
fn rstr(fzs: &mut kvstore_string_t) -> &str {
use std::ffi::CStr;
let content =
unsafe { CStr::from_ptr(kvstore_string_content(fzs as *mut kvstore_string_t)) };
content.to_str().unwrap()
}
let mut key = fzstr("a-key");
let mut val = unsafe { kvstore_get(store, &mut key as *mut kvstore_string_t) };
assert!(unsafe { kvstore_string_is_null(&val as *const kvstore_string_t) });
unsafe { kvstore_string_free(&mut val as *mut kvstore_string_t) };
let mut val = fzstr("a-val");
assert!(unsafe {
kvstore_set(
store,
&mut key as *mut kvstore_string_t,
&mut val as *mut kvstore_string_t,
)
});
let mut key = fzstr("a-key");
let mut val = unsafe { kvstore_get(store, &mut key as *mut kvstore_string_t) };
assert_eq!(rstr(&mut val), "a-val");
unsafe { kvstore_string_free(&mut val as *mut kvstore_string_t) };
assert!(unsafe { kvstore_del(store, &mut key as *mut kvstore_string_t,) });
let mut val = unsafe { kvstore_get(store, &mut key as *mut kvstore_string_t) };
assert!(unsafe { kvstore_string_is_null(&val as *const kvstore_string_t) });
unsafe { kvstore_string_free(&mut key as *mut kvstore_string_t) };
unsafe { kvstore_string_free(&mut val as *mut kvstore_string_t) };
unsafe { kvstore_free(store) };
}