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
@@ -101,52 +101,55 @@
         let mut valid_len: u64 = 0;
         let mut total_records: u64 = 0;
 
-        if path.exists() {
-            let file = File::open(&path)?;
-            let total_on_disk = file.metadata()?.len();
-            // Hint the IndexMap capacity from the on-disk size so the replay
-            // loop avoids the geometric grow-rehash sequence. 24 bytes/record
-            // matches the smallest Insert<u64,u64> record (4-byte length +
-            // 20-byte payload); larger records over-reserve harmlessly.
-            let capacity_hint = (total_on_disk / 24) as usize;
-            if capacity_hint > 0 {
-                map.reserve(capacity_hint);
-            }
-            let mut reader = BufReader::new(file);
-            let mut len_buf = [0u8; LEN_BYTES];
-            let mut payload: Vec<u8> = Vec::new();
-            loop {
-                match reader.read_exact(&mut len_buf) {
-                    Ok(()) => {}
-                    Err(e) if e.kind() == ErrorKind::UnexpectedEof => break,
-                    Err(e) => return Err(e),
-                }
-                let len = u32::from_le_bytes(len_buf) as usize;
-                payload.resize(len, 0);
-                if reader.read_exact(&mut payload).is_err() {
-                    break;
+        match File::open(&path) {
+            Ok(file) => {
+                let total_on_disk = file.metadata()?.len();
+                // Hint the IndexMap capacity from the on-disk size so the replay
+                // loop avoids the geometric grow-rehash sequence. 24 bytes/record
+                // matches the smallest Insert<u64,u64> record (4-byte length +
+                // 20-byte payload); larger records over-reserve harmlessly.
+                let capacity_hint = (total_on_disk / 24) as usize;
+                if capacity_hint > 0 {
+                    map.reserve(capacity_hint);
                 }
-                let rec: LogOwned<K, V> = match bincode::deserialize(&payload) {
-                    Ok(r) => r,
-                    Err(_) => break,
-                };
-                match rec {
-                    LogOwned::Insert(k, v) => {
-                        map.insert(k, v);
+                let mut reader = BufReader::new(file);
+                let mut len_buf = [0u8; LEN_BYTES];
+                let mut payload: Vec<u8> = Vec::new();
+                loop {
+                    match reader.read_exact(&mut len_buf) {
+                        Ok(()) => {}
+                        Err(e) if e.kind() == ErrorKind::UnexpectedEof => break,
+                        Err(e) => return Err(e),
+                    }
+                    let len = u32::from_le_bytes(len_buf) as usize;
+                    payload.resize(len, 0);
+                    if reader.read_exact(&mut payload).is_err() {
+                        break;
                     }
-                    LogOwned::Remove(k) => {
-                        map.shift_remove(&k);
+                    let rec: LogOwned<K, V> = match bincode::deserialize(&payload) {
+                        Ok(r) => r,
+                        Err(_) => break,
+                    };
+                    match rec {
+                        LogOwned::Insert(k, v) => {
+                            map.insert(k, v);
+                        }
+                        LogOwned::Remove(k) => {
+                            map.shift_remove(&k);
+                        }
                     }
+                    valid_len += (LEN_BYTES + len) as u64;
+                    total_records += 1;
                 }
-                valid_len += (LEN_BYTES + len) as u64;
-                total_records += 1;
-            }
 
-            if valid_len != total_on_disk {
-                let f = OpenOptions::new().write(true).open(&path)?;
-                f.set_len(valid_len)?;
-                f.sync_all()?;
+                if valid_len != total_on_disk {
+                    let f = OpenOptions::new().write(true).open(&path)?;
+                    f.set_len(valid_len)?;
+                    f.sync_all()?;
+                }
             }
+            Err(e) if e.kind() == ErrorKind::NotFound => {}
+            Err(e) => return Err(e),
         }
 
         let file = OpenOptions::new().create(true).append(true).open(&path)?;