indexmap_store 0.1.0

Mutable, persistent key-value store backed by an IndexMap with an append-only log.
Documentation
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -19,25 +19,15 @@
 //! The store owns the file; concurrent writers are not supported.
 
 use indexmap::IndexMap;
-use serde::{Deserialize, Serialize, de::DeserializeOwned};
+use serde::{Serialize, de::DeserializeOwned};
 use std::fs::{self, File, OpenOptions};
 use std::hash::Hash;
 use std::io::{self, BufWriter, ErrorKind, Read, Write};
 use std::path::{Path, PathBuf};
 
 const LEN_BYTES: usize = 4;
-
-#[derive(Serialize)]
-enum LogRef<'a, K, V> {
-    Insert(&'a K, &'a V),
-    Remove(&'a K),
-}
-
-#[derive(Deserialize)]
-enum LogOwned<K, V> {
-    Insert(K, V),
-    Remove(K),
-}
+const TAG_INSERT: u8 = 0;
+const TAG_REMOVE: u8 = 1;
 
 /// Configuration for an [`IndexMapStore`].
 #[derive(Clone, Debug)]
@@ -126,20 +116,27 @@
                 ) as usize;
                 let payload_start = offset + LEN_BYTES;
                 let payload_end = payload_start + len;
-                if payload_end > buf.len() {
+                if payload_end > buf.len() || len == 0 {
                     break;
                 }
-                let rec: LogOwned<K, V> = match bincode::deserialize(&buf[payload_start..payload_end]) {
-                    Ok(r) => r,
-                    Err(_) => break,
-                };
-                match rec {
-                    LogOwned::Insert(k, v) => {
+                let tag = buf[payload_start];
+                let body = &buf[payload_start + 1..payload_end];
+                match tag {
+                    TAG_INSERT => {
+                        let (k, v): (K, V) = match bincode::deserialize(body) {
+                            Ok(r) => r,
+                            Err(_) => break,
+                        };
                         map.insert(k, v);
                     }
-                    LogOwned::Remove(k) => {
+                    TAG_REMOVE => {
+                        let k: K = match bincode::deserialize(body) {
+                            Ok(r) => r,
+                            Err(_) => break,
+                        };
                         map.shift_remove(&k);
                     }
+                    _ => break,
                 }
                 valid_len += (LEN_BYTES + len) as u64;
                 total_records += 1;
@@ -220,7 +217,8 @@
     pub fn insert(&mut self, k: K, v: V) -> io::Result<Option<V>> {
         self.scratch.clear();
         self.scratch.extend_from_slice(&[0u8; LEN_BYTES]);
-        bincode::serialize_into(&mut self.scratch, &LogRef::Insert::<K, V>(&k, &v))
+        self.scratch.push(TAG_INSERT);
+        bincode::serialize_into(&mut self.scratch, &(&k, &v))
             .map_err(serialize_err)?;
         self.flush_scratch()?;
         let prev = self.map.insert(k, v);
@@ -240,7 +238,8 @@
         }
         self.scratch.clear();
         self.scratch.extend_from_slice(&[0u8; LEN_BYTES]);
-        bincode::serialize_into(&mut self.scratch, &LogRef::Remove::<K, V>(k))
+        self.scratch.push(TAG_REMOVE);
+        bincode::serialize_into(&mut self.scratch, k)
             .map_err(serialize_err)?;
         self.flush_scratch()?;
         let prev = self.map.shift_remove(k);
@@ -268,7 +267,8 @@
 
         self.scratch.clear();
         self.scratch.extend_from_slice(&[0u8; LEN_BYTES]);
-        bincode::serialize_into(&mut self.scratch, &LogRef::Insert::<K, V>(k, v_ref))
+        self.scratch.push(TAG_INSERT);
+        bincode::serialize_into(&mut self.scratch, &(k, v_ref))
             .map_err(serialize_err)?;
 
         self.flush_scratch()?;
@@ -299,7 +299,8 @@
             let mut buf = Vec::with_capacity(256);
             for (k, v) in &self.map {
                 buf.clear();
-                bincode::serialize_into(&mut buf, &LogRef::Insert::<K, V>(k, v))
+                buf.push(TAG_INSERT);
+                bincode::serialize_into(&mut buf, &(k, v))
                     .map_err(serialize_err)?;
                 writer.write_all(&(buf.len() as u32).to_le_bytes())?;
                 writer.write_all(&buf)?;