use std::fmt::Display;
use crate::helper;
use std::ptr::null_mut;
#[derive(Debug, Clone)]
pub enum Error {
NoSuchStore,
AccessDenied,
Other(String),
}
pub struct Store {
handle: u32,
}
impl Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Error::NoSuchStore => write!(f, "no such store"),
Error::AccessDenied => write!(f, "access denied"),
Error::Other(msg) => write!(f, "other error: {}", msg),
}
}
}
impl Store {
pub fn new() -> Result<Self, Error> {
Self::open("default")
}
pub fn open(name: &str) -> Result<Self, Error> {
let mut return_handler = 0;
unsafe {
match super::proxy_kv_store_open(name.as_ptr(), name.len(), &mut return_handler) {
0 => Ok(Store {
handle: return_handler,
}),
1 => Err(Error::NoSuchStore),
2 => Err(Error::AccessDenied),
status => Err(Error::Other(format!("unexpected status: {}", status))),
}
}
}
pub fn get(&self, key: &str) -> Result<Option<Vec<u8>>, Error> {
let mut return_data: *mut u8 = null_mut();
let mut return_size: usize = 0;
unsafe {
match super::proxy_kv_store_get(
self.handle,
key.as_ptr(),
key.len(),
&mut return_data,
&mut return_size,
) {
0 => {
if !return_data.is_null() {
Ok(Some(Vec::from_raw_parts(
return_data,
return_size,
return_size,
)))
} else {
Ok(None)
}
}
status => Err(Error::Other(format!("unexpected status: {}", status))),
}
}
}
pub fn zrange_by_score(&self, key: &str, min: f64, max: f64) -> Result<Vec<(Vec<u8>, f64)>, Error> {
let mut return_data: *mut u8 = null_mut();
let mut return_size: usize = 0;
unsafe {
match super::proxy_kv_store_zrange_by_score(
self.handle,
key.as_ptr(),
key.len(),
min,
max,
&mut return_data,
&mut return_size,
) {
0 => {
if !return_data.is_null() {
let data = Vec::from_raw_parts(return_data, return_size, return_size);
let data: Vec<(Vec<u8>, f64)> = helper::deserialize_list(&data)
.into_iter()
.map(|v| {
let mut value = v.to_vec();
let sz = size_of::<f64>();
if value.len() > sz {
let npos = value.len() - sz;
let score = value.split_off(npos);
let score = f64::from_le_bytes(
<[u8; 8]>::try_from(&score[0..sz]).expect("Failed to convert score bytes to f64: expected 8 bytes"),
);
(value, score)
} else {
(vec![], 0.0)
}
})
.collect();
Ok(data)
} else {
Ok(vec![])
}
}
status => Err(Error::Other(format!("unexpected status: {}", status))),
}
}
}
pub fn scan(&self, pattern: &str) -> Result<Vec<String>, Error> {
let mut return_data: *mut u8 = null_mut();
let mut return_size: usize = 0;
unsafe {
match super::proxy_kv_store_scan(
self.handle,
pattern.as_ptr(),
pattern.len(),
&mut return_data,
&mut return_size,
) {
0 => {
if !return_data.is_null() {
let data = Vec::from_raw_parts(return_data, return_size, return_size);
let data: Vec<String> = helper::deserialize_list(&data)
.into_iter()
.map(|v| String::from_utf8_lossy(v).to_string())
.collect();
Ok(data)
} else {
Ok(vec![])
}
}
status => Err(Error::Other(format!("unexpected status: {}", status))),
}
}
}
pub fn zscan(&self, key: &str, pattern: &str) -> Result<Vec<(Vec<u8>, f64)>, Error> {
let mut return_data: *mut u8 = null_mut();
let mut return_size: usize = 0;
unsafe {
match super::proxy_kv_store_zscan(
self.handle,
key.as_ptr(),
key.len(),
pattern.as_ptr(),
pattern.len(),
&mut return_data,
&mut return_size,
) {
0 => {
if !return_data.is_null() {
let data = Vec::from_raw_parts(return_data, return_size, return_size);
let data: Vec<(Vec<u8>, f64)> = helper::deserialize_list(&data)
.into_iter()
.map(|v| {
let mut value = v.to_vec();
let sz = size_of::<f64>();
if value.len() > sz {
let npos = value.len() - sz;
let score = value.split_off(npos);
let score = f64::from_le_bytes(
<[u8; 8]>::try_from(&score[0..sz]).expect("Failed to convert score bytes to f64: expected 8 bytes"),
);
(value, score)
} else {
(vec![], 0.0)
}
})
.collect();
Ok(data)
} else {
Ok(vec![])
}
}
status => Err(Error::Other(format!("unexpected status: {}", status))),
}
}
}
pub fn bf_exists(&self, key: &str, item: &str) -> Result<bool, Error> {
let mut return_handler: u32 = 0;
unsafe {
match super::proxy_kv_store_bf_exists(
self.handle,
key.as_ptr(),
key.len(),
item.as_ptr(),
item.len(),
&mut return_handler,
) {
0 => Ok(return_handler != 0),
status => Err(Error::Other(format!("unexpected status: {}", status))),
}
}
}
}