use alloc::{vec::Vec, string::String, collections::btree_map::BTreeMap}; use cslice::{CSlice, AsCSlice}; use core::mem::transmute; struct Entry { data: Vec, slice: CSlice<'static, i32>, borrowed: bool } impl core::fmt::Debug for Entry { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("Entry") .field("data", &self.data) .field("borrowed", &self.borrowed) .finish() } } pub struct Cache { entries: BTreeMap, empty: CSlice<'static, i32>, } impl core::fmt::Debug for Cache { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("Cache") .field("entries", &self.entries) .finish() } } impl Cache { pub fn new() -> Cache { let empty_vec = vec![]; let empty = unsafe { transmute::, CSlice<'static, i32>>(empty_vec.as_c_slice()) }; Cache { entries: BTreeMap::new(), empty } } pub fn get(&mut self, key: &str) -> *const CSlice<'static, i32> { match self.entries.get_mut(key) { None => &self.empty, Some(ref mut entry) => { entry.borrowed = true; &entry.slice } } } pub fn put(&mut self, key: &str, data: &[i32]) -> Result<(), ()> { match self.entries.get_mut(key) { None => (), Some(ref mut entry) => { if entry.borrowed { return Err(()) } entry.data = Vec::from(data); unsafe { entry.slice = transmute::, CSlice<'static, i32>>( entry.data.as_c_slice()); } return Ok(()) } } let data = Vec::from(data); let slice = unsafe { transmute::, CSlice<'static, i32>>(data.as_c_slice()) }; self.entries.insert(String::from(key), Entry { data, slice, borrowed: false }); Ok(()) } pub unsafe fn unborrow(&mut self) { for (_key, entry) in self.entries.iter_mut() { entry.borrowed = false; } } }