rocksdb_fileformat/
block_handle.rs

1use crate::error::{Error, Result};
2use byteorder::{ReadBytesExt, WriteBytesExt};
3use std::io::{Cursor, Read, Write};
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub struct BlockHandle {
7    pub offset: u64,
8    pub size: u64,
9}
10
11impl BlockHandle {
12    pub fn new(offset: u64, size: u64) -> Self {
13        Self { offset, size }
14    }
15
16    pub fn null() -> Self {
17        Self { offset: 0, size: 0 }
18    }
19
20    pub fn is_null(&self) -> bool {
21        self.offset == 0 && self.size == 0
22    }
23
24    pub fn decode_from<R: Read>(reader: &mut R) -> Result<Self> {
25        let offset = read_varint64(reader)?;
26        let size = read_varint64(reader)?;
27        Ok(Self { offset, size })
28    }
29
30    pub fn encode_to<W: Write>(&self, writer: &mut W) -> Result<()> {
31        write_varint64(writer, self.offset)?;
32        write_varint64(writer, self.size)?;
33        Ok(())
34    }
35
36    pub fn encoded_length(&self) -> usize {
37        varint64_length(self.offset) + varint64_length(self.size)
38    }
39
40    pub fn decode_from_bytes(data: &[u8]) -> Result<(Self, usize)> {
41        let mut cursor = Cursor::new(data);
42        let handle = Self::decode_from(&mut cursor)?;
43        let consumed = cursor.position() as usize;
44        Ok((handle, consumed))
45    }
46
47    pub fn encode_to_bytes(&self) -> Result<Vec<u8>> {
48        let mut buf = Vec::with_capacity(self.encoded_length());
49        self.encode_to(&mut buf)?;
50        Ok(buf)
51    }
52}
53
54fn read_varint64<R: Read>(reader: &mut R) -> Result<u64> {
55    let mut result = 0u64;
56    let mut shift = 0;
57
58    for _ in 0..10 {
59        let byte = reader.read_u8()?;
60
61        if (byte & 0x80) == 0 {
62            result |= (byte as u64) << shift;
63            return Ok(result);
64        }
65
66        result |= ((byte & 0x7f) as u64) << shift;
67        shift += 7;
68    }
69
70    Err(Error::InvalidVarint)
71}
72
73fn write_varint64<W: Write>(writer: &mut W, mut value: u64) -> Result<()> {
74    while value >= 0x80 {
75        writer.write_u8((value as u8) | 0x80)?;
76        value >>= 7;
77    }
78    writer.write_u8(value as u8)?;
79    Ok(())
80}
81
82fn varint64_length(mut value: u64) -> usize {
83    let mut length = 1;
84    while value >= 0x80 {
85        value >>= 7;
86        length += 1;
87    }
88    length
89}
90
91#[cfg(test)]
92mod tests {
93    use super::*;
94
95    #[test]
96    fn test_varint64_encoding() -> Result<()> {
97        let test_cases = vec![0, 127, 128, 16383, 16384, 2097151, 2097152];
98
99        for value in test_cases {
100            let mut buf = Vec::new();
101            write_varint64(&mut buf, value)?;
102            let mut cursor = Cursor::new(&buf);
103            let decoded = read_varint64(&mut cursor)?;
104            assert_eq!(value, decoded);
105        }
106        Ok(())
107    }
108
109    #[test]
110    fn test_block_handle_encoding() -> Result<()> {
111        let handle = BlockHandle::new(12345, 67890);
112        let encoded = handle.encode_to_bytes()?;
113        let (decoded, consumed) = BlockHandle::decode_from_bytes(&encoded)?;
114
115        assert_eq!(handle, decoded);
116        assert_eq!(consumed, encoded.len());
117        Ok(())
118    }
119
120    #[test]
121    fn test_block_handle_encoded_length() -> Result<()> {
122        let handle = BlockHandle::new(12345, 67890);
123        let encoded = handle.encode_to_bytes()?;
124        assert_eq!(handle.encoded_length(), encoded.len());
125        Ok(())
126    }
127}