]> git.mikk.net Git - mtbl-rs/commitdiff
metadata: read from file-like object instaed of buf
authorChris Mikkelson <cmikk@fsi.io>
Mon, 5 Aug 2024 06:01:41 +0000 (00:01 -0600)
committerChris Mikkelson <cmikk@fsi.io>
Mon, 5 Aug 2024 06:03:51 +0000 (00:03 -0600)
src/metadata.rs

index 20485a8ddb135416de2cd75560ef454bc793bb7a..df08ce9375f296864836878e83db820c7da501a0 100644 (file)
@@ -14,6 +14,8 @@ struct mtbl_metadata {
 */
 use crate::compression::Compression;
 use crate::Result;
+use integer_encoding::{FixedIntReader, FixedIntWriter};
+use std::io::SeekFrom;
 use std::mem::size_of;
 
 const MTBL_MAGIC: u32 = 0x4D54424C;
@@ -31,53 +33,40 @@ pub(crate) struct Metadata {
     pub(crate) bytes_values: usize,
 }
 
-fn try_read64(b: &mut &[u8]) -> Result<u64> {
-    if b.len() < size_of::<u64>() {
-        Err("buffer too short".into())
-    } else {
-        let (n, rest) = b.split_at(size_of::<u64>());
-        *b = rest;
-        Ok(u64::from_be_bytes(n.try_into()?))
-    }
-}
-
-fn write64(n: u64, mut out: impl std::io::Write) -> std::io::Result<()> {
-    out.write_all(n.to_be_bytes().as_slice())
-}
-
 impl Metadata {
-    pub(crate) fn from_bytes(mut b: &[u8]) -> Result<Self> {
-        if b.len() < size_of::<u32>() {
-            return Err("metadata block too short".into());
-        } else if u32::from_be_bytes(b[b.len() - size_of::<u32>()..].try_into()?) != MTBL_MAGIC {
+    pub(crate) fn read_from(mut inp: impl std::io::Read + std::io::Seek) -> Result<Self> {
+        inp.seek(SeekFrom::Start(512 - size_of::<u32>() as u64))?;
+        if inp.read_fixedint::<u32>()? != MTBL_MAGIC {
             return Err("bad magic".into());
         }
+        inp.seek(SeekFrom::Current(-512))?;
+
         Ok(Self {
-            index_block_offset: try_read64(&mut b)? as usize,
-            data_block_size: try_read64(&mut b)? as usize,
-            compression_algorithm: try_read64(&mut b)?.try_into()?,
-            count_entries: try_read64(&mut b)?,
-            count_data_blocks: try_read64(&mut b)?,
-            bytes_data_blocks: try_read64(&mut b)? as usize,
-            bytes_index_block: try_read64(&mut b)? as usize,
-            bytes_keys: try_read64(&mut b)? as usize,
-            bytes_values: try_read64(&mut b)? as usize,
+            index_block_offset: inp.read_fixedint::<u64>()? as usize,
+            data_block_size: inp.read_fixedint::<u64>()? as usize,
+            compression_algorithm: inp.read_fixedint::<u64>()?.try_into()?,
+            count_entries: inp.read_fixedint()?,
+            count_data_blocks: inp.read_fixedint()?,
+            bytes_data_blocks: inp.read_fixedint::<u64>()? as usize,
+            bytes_index_block: inp.read_fixedint::<u64>()? as usize,
+            bytes_keys: inp.read_fixedint::<u64>()? as usize,
+            bytes_values: inp.read_fixedint::<u64>()? as usize,
         })
     }
 
     pub(crate) fn write_to(&self, mut out: impl std::io::Write) -> Result<()> {
-        write64(self.index_block_offset as u64, &mut out)?;
-        write64(self.data_block_size as u64, &mut out)?;
-        write64(self.compression_algorithm.into(), &mut out)?;
-        write64(self.count_entries, &mut out)?;
-        write64(self.count_data_blocks, &mut out)?;
-        write64(self.bytes_data_blocks as u64, &mut out)?;
-        write64(self.bytes_index_block as u64, &mut out)?;
-        write64(self.bytes_keys as u64, &mut out)?;
-        write64(self.bytes_values as u64, &mut out)?;
+        out.write_fixedint::<u64>(self.index_block_offset as u64)?;
+        out.write_fixedint::<u64>(self.data_block_size as u64)?;
+        out.write_fixedint::<u64>(self.compression_algorithm.into())?;
+        out.write_fixedint(self.count_entries)?;
+        out.write_fixedint(self.count_data_blocks)?;
+        out.write_fixedint::<u64>(self.bytes_data_blocks as u64)?;
+        out.write_fixedint::<u64>(self.bytes_index_block as u64)?;
+        out.write_fixedint::<u64>(self.bytes_keys as u64)?;
+        out.write_fixedint::<u64>(self.bytes_values as u64)?;
         let bytes_written = 9 * 8;
         out.write_all(vec![0; 512 - bytes_written - size_of::<u32>()].as_slice())?;
-        out.write_all(MTBL_MAGIC.to_be_bytes().as_slice())?;
+        out.write_fixedint(MTBL_MAGIC)?;
         Ok(())
     }
 
@@ -101,6 +90,7 @@ impl Metadata {
 #[cfg(test)]
 mod test {
     use super::Metadata;
+    use std::io::Cursor;
 
     #[test]
     fn test_metadata_default() {
@@ -111,7 +101,7 @@ mod test {
         let mut v = Vec::<u8>::new();
         m.write_to(&mut v).expect("write_to");
         assert_eq!(v.len(), 512);
-        let m2 = Metadata::from_bytes(v.as_slice()).unwrap();
+        let m2 = Metadata::read_from(Cursor::new(v)).unwrap();
         assert_eq!(m2.count_entries, 1);
         assert_eq!(m2.bytes_keys, 1);
         assert_eq!(m2.bytes_values, 2);