diff --git a/Cargo.toml b/Cargo.toml index 7ed41da..cf8322c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,4 +12,6 @@ license = "GPL-3" edition = "2018" [dependencies] -byteorder = { version = "1.0", default-features = false } +byteorder = { version = "1", default-features = false } +serde = { version = "1.0", default-features = false } +postcard = "0.5" diff --git a/src/error.rs b/src/error.rs index 3e82129..c213fa4 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,9 +1,11 @@ use core::{fmt, str}; -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum Error { Read(ReadError), Write(WriteError), + Encode(postcard::Error), + Decode(postcard::Error), } impl From for Error { diff --git a/src/lib.rs b/src/lib.rs index 87b7d82..623b81c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,7 @@ use core::{fmt::Write, mem::size_of, str}; use byteorder::{ByteOrder, BigEndian}; +use serde::{Deserialize, Serialize}; mod error; pub use error::{Error, ReadError, WriteError}; @@ -14,7 +15,7 @@ mod test; pub trait StoreBackend { type Data: Sized + AsRef<[u8]> + Clone; - + /// Memory-mapped fn data(&self) -> &Self::Data; fn len(&self) -> usize { @@ -63,6 +64,15 @@ impl Store { .transpose()) } + /// read from `key`, decode with `postcard` + pub fn read_value<'a, T: Deserialize<'a>>(&'a self, key: &str) -> Result, Error> { + self.read(key)? + .map( + |data| postcard::from_bytes(data) + .map_err(Error::Decode) + ).transpose() + } + /// how many bytes are currently used /// /// equally, offset of free space @@ -157,11 +167,20 @@ impl Store { self.write(key, wrapper.contents()) } + /// encode with `postcard`, write at `key` + pub fn write_value(&mut self, key: &str, value: T) -> Result<(), Error> { + let mut buf = [0; 64]; + let data = postcard::to_slice(&value, &mut buf) + .map_err(Error::Encode)?; + self.write(key, data) + } + /// store a 0-byte tombstone value at `key` pub fn remove(&mut self, key: &str) -> Result<(), Error> { self.write(key, &[]) } + /// invokes erase on the backend (this is no compaction!) pub fn erase(&mut self) -> Result<(), WriteError> { self.backend.erase() .map_err(WriteError::Backend)?; diff --git a/src/test.rs b/src/test.rs index 0d382fe..e8bb0ca 100644 --- a/src/test.rs +++ b/src/test.rs @@ -52,14 +52,48 @@ fn empty_read_not_found() { assert_eq!(store.read("foo").unwrap(), None) } - #[test] fn write_read() { let mut store = make_store(); store.write("foo", b"bar").unwrap(); assert_eq!(store.read("foo").unwrap().unwrap(), b"bar"); } - + +#[test] +fn write_read_value_str() { + let mut store = make_store(); + store.write_value("foo", "bar").unwrap(); + assert_eq!(store.read_value("foo"), Ok(Some("bar"))); +} + +#[test] +fn write_read_value_u32() { + let mut store = make_store(); + store.write_value("foo", 42005u32).unwrap(); + assert_eq!(store.read_value("foo"), Ok(Some(42005u32))); +} + +#[test] +fn write_read_value_i64() { + let mut store = make_store(); + store.write_value("foo", -99999999i64).unwrap(); + assert_eq!(store.read_value("foo"), Ok(Some(-99999999i64))); +} + +#[test] +fn write_read_value_f32() { + let mut store = make_store(); + store.write_value("foo", 3.75e17f32).unwrap(); + assert_eq!(store.read_value("foo"), Ok(Some(3.75e17f32))); +} + +#[test] +fn write_read_value_f64() { + let mut store = make_store(); + store.write_value("foo", -1.999e-13f64).unwrap(); + assert_eq!(store.read_value("foo"), Ok(Some(-1.999e-13f64))); +} + #[test] fn write_int_read_str() { let mut store = make_store();