rocksdb_fileformat/
block_handle.rs1use 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}