read_value()/write_value(): implement serialization via postcard crate

This commit is contained in:
Astro 2020-12-11 19:00:47 +01:00
parent 9153240b9b
commit 8a2bcf13f8
4 changed files with 62 additions and 5 deletions

View File

@ -12,4 +12,6 @@ license = "GPL-3"
edition = "2018" edition = "2018"
[dependencies] [dependencies]
byteorder = { version = "1.0", default-features = false } byteorder = { version = "1", default-features = false }
serde = { version = "1.0", default-features = false }
postcard = "0.5"

View File

@ -1,9 +1,11 @@
use core::{fmt, str}; use core::{fmt, str};
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum Error<B> { pub enum Error<B> {
Read(ReadError), Read(ReadError),
Write(WriteError<B>), Write(WriteError<B>),
Encode(postcard::Error),
Decode(postcard::Error),
} }
impl<B> From<ReadError> for Error<B> { impl<B> From<ReadError> for Error<B> {

View File

@ -2,6 +2,7 @@
use core::{fmt::Write, mem::size_of, str}; use core::{fmt::Write, mem::size_of, str};
use byteorder::{ByteOrder, BigEndian}; use byteorder::{ByteOrder, BigEndian};
use serde::{Deserialize, Serialize};
mod error; mod error;
pub use error::{Error, ReadError, WriteError}; pub use error::{Error, ReadError, WriteError};
@ -14,7 +15,7 @@ mod test;
pub trait StoreBackend { pub trait StoreBackend {
type Data: Sized + AsRef<[u8]> + Clone; type Data: Sized + AsRef<[u8]> + Clone;
/// Memory-mapped /// Memory-mapped
fn data(&self) -> &Self::Data; fn data(&self) -> &Self::Data;
fn len(&self) -> usize { fn len(&self) -> usize {
@ -63,6 +64,15 @@ impl<B: StoreBackend> Store<B> {
.transpose()) .transpose())
} }
/// read from `key`, decode with `postcard`
pub fn read_value<'a, T: Deserialize<'a>>(&'a self, key: &str) -> Result<Option<T>, Error<B::Error>> {
self.read(key)?
.map(
|data| postcard::from_bytes(data)
.map_err(Error::Decode)
).transpose()
}
/// how many bytes are currently used /// how many bytes are currently used
/// ///
/// equally, offset of free space /// equally, offset of free space
@ -157,11 +167,20 @@ impl<B: StoreBackend> Store<B> {
self.write(key, wrapper.contents()) self.write(key, wrapper.contents())
} }
/// encode with `postcard`, write at `key`
pub fn write_value<T: Serialize>(&mut self, key: &str, value: T) -> Result<(), Error<B::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` /// store a 0-byte tombstone value at `key`
pub fn remove(&mut self, key: &str) -> Result<(), Error<B::Error>> { pub fn remove(&mut self, key: &str) -> Result<(), Error<B::Error>> {
self.write(key, &[]) self.write(key, &[])
} }
/// invokes erase on the backend (this is no compaction!)
pub fn erase(&mut self) -> Result<(), WriteError<B::Error>> { pub fn erase(&mut self) -> Result<(), WriteError<B::Error>> {
self.backend.erase() self.backend.erase()
.map_err(WriteError::Backend)?; .map_err(WriteError::Backend)?;

View File

@ -52,14 +52,48 @@ fn empty_read_not_found() {
assert_eq!(store.read("foo").unwrap(), None) assert_eq!(store.read("foo").unwrap(), None)
} }
#[test] #[test]
fn write_read() { fn write_read() {
let mut store = make_store(); let mut store = make_store();
store.write("foo", b"bar").unwrap(); store.write("foo", b"bar").unwrap();
assert_eq!(store.read("foo").unwrap().unwrap(), b"bar"); 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] #[test]
fn write_int_read_str() { fn write_int_read_str() {
let mut store = make_store(); let mut store = make_store();