#![allow(unsafe_op_in_unsafe_fn)]
use crate::error::{Error, check};
use crate::ffi;
use crate::merkle::MerkleEntry;
use crate::types::NodeId;
#[derive(Clone, Debug)]
pub struct LogIndexEntry {
pub node_id: NodeId,
pub pubkey: [u8; 32],
pub log_index: u64,
pub revoked: bool,
}
impl LogIndexEntry {
pub(crate) fn to_ffi(&self) -> ffi::nwep_log_index_entry {
ffi::nwep_log_index_entry {
nodeid: ffi::nwep_nodeid {
data: self.node_id.0,
},
pubkey: self.pubkey,
log_index: self.log_index,
revoked: self.revoked as i32,
}
}
pub(crate) fn from_ffi(e: &ffi::nwep_log_index_entry) -> Self {
LogIndexEntry {
node_id: NodeId(e.nodeid.data),
pubkey: e.pubkey,
log_index: e.log_index,
revoked: e.revoked != 0,
}
}
}
pub trait LogIndexStorage: Send + 'static {
fn get(&self, node_id: &NodeId) -> Result<LogIndexEntry, Error>;
fn put(&mut self, entry: &LogIndexEntry) -> Result<(), Error>;
}
struct StorageCallbacks {
storage: Box<dyn LogIndexStorage>,
}
unsafe extern "C" fn index_get_cb(
user_data: *mut std::ffi::c_void,
nodeid: *const ffi::nwep_nodeid,
entry: *mut ffi::nwep_log_index_entry,
) -> std::ffi::c_int {
let cb = &*(user_data as *mut StorageCallbacks);
let nid = NodeId((*nodeid).data);
match cb.storage.get(&nid) {
Ok(e) => {
*entry = e.to_ffi();
0
}
Err(e) => e.code,
}
}
unsafe extern "C" fn index_put_cb(
user_data: *mut std::ffi::c_void,
entry: *const ffi::nwep_log_index_entry,
) -> std::ffi::c_int {
let cb = &mut *(user_data as *mut StorageCallbacks);
let e = LogIndexEntry::from_ffi(&*entry);
match cb.storage.put(&e) {
Ok(()) => 0,
Err(e) => e.code,
}
}
pub struct LogIndex {
ptr: *mut ffi::nwep_log_index,
_storage: Box<StorageCallbacks>,
}
unsafe impl Send for LogIndex {}
impl LogIndex {
pub fn new(storage: impl LogIndexStorage) -> Result<Self, Error> {
let mut cb = Box::new(StorageCallbacks {
storage: Box::new(storage),
});
let ffi_storage = ffi::nwep_log_index_storage {
get: Some(index_get_cb),
put: Some(index_put_cb),
user_data: cb.as_mut() as *mut _ as *mut std::ffi::c_void,
};
let mut ptr: *mut ffi::nwep_log_index = std::ptr::null_mut();
check(unsafe { ffi::nwep_log_index_new(&mut ptr, &ffi_storage) })?;
Ok(LogIndex { ptr, _storage: cb })
}
pub fn lookup(&mut self, node_id: &NodeId) -> Result<LogIndexEntry, Error> {
let ffi_nid = ffi::nwep_nodeid { data: node_id.0 };
let mut entry = unsafe { std::mem::zeroed::<ffi::nwep_log_index_entry>() };
check(unsafe { ffi::nwep_log_index_lookup(self.ptr, &ffi_nid, &mut entry) })?;
Ok(LogIndexEntry::from_ffi(&entry))
}
pub fn update(&mut self, entry: &MerkleEntry, log_idx: u64) -> Result<(), Error> {
let ffi_entry = entry.to_ffi();
check(unsafe { ffi::nwep_log_index_update(self.ptr, &ffi_entry, log_idx) })
}
}
impl Drop for LogIndex {
fn drop(&mut self) {
if !self.ptr.is_null() {
unsafe { ffi::nwep_log_index_free(self.ptr) }
}
}
}