| 
									
										
										
										
											2022-12-23 14:29:32 -05:00
										 |  |  | use bytes::BufMut;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | use super::{Block, SIZEOF_U16};
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-23 22:32:30 -05:00
										 |  |  | /// Builds a block.
 | 
					
						
							| 
									
										
										
										
											2022-12-23 14:29:32 -05:00
										 |  |  | pub struct BlockBuilder {
 | 
					
						
							| 
									
										
										
										
											2022-12-23 22:32:30 -05:00
										 |  |  |     /// Offsets of each key-value entries.
 | 
					
						
							| 
									
										
										
										
											2022-12-23 14:29:32 -05:00
										 |  |  |     offsets: Vec<u16>,
 | 
					
						
							| 
									
										
										
										
											2022-12-23 22:32:30 -05:00
										 |  |  |     /// All key-value pairs in the block.
 | 
					
						
							| 
									
										
										
										
											2022-12-23 14:29:32 -05:00
										 |  |  |     data: Vec<u8>,
 | 
					
						
							| 
									
										
										
										
											2022-12-23 22:32:30 -05:00
										 |  |  |     /// The expected block size.
 | 
					
						
							| 
									
										
										
										
											2022-12-23 21:14:11 -05:00
										 |  |  |     block_size: usize,
 | 
					
						
							| 
									
										
										
										
											2022-12-23 14:29:32 -05:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | impl BlockBuilder {
 | 
					
						
							| 
									
										
										
										
											2022-12-23 22:32:30 -05:00
										 |  |  |     /// Creates a new block builder.
 | 
					
						
							| 
									
										
										
										
											2022-12-23 21:14:11 -05:00
										 |  |  |     pub fn new(block_size: usize) -> Self {
 | 
					
						
							| 
									
										
										
										
											2022-12-23 14:29:32 -05:00
										 |  |  |         Self {
 | 
					
						
							|  |  |  |             offsets: Vec::new(),
 | 
					
						
							|  |  |  |             data: Vec::new(),
 | 
					
						
							| 
									
										
										
										
											2022-12-23 21:14:11 -05:00
										 |  |  |             block_size,
 | 
					
						
							| 
									
										
										
										
											2022-12-23 14:29:32 -05:00
										 |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fn estimated_size(&self) -> usize {
 | 
					
						
							|  |  |  |         self.offsets.len() * SIZEOF_U16 + self.data.len() + SIZEOF_U16
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-23 22:32:30 -05:00
										 |  |  |     /// Adds a key-value pair to the block. Returns false when the block is full.
 | 
					
						
							| 
									
										
										
										
											2022-12-23 14:29:32 -05:00
										 |  |  |     #[must_use]
 | 
					
						
							|  |  |  |     pub fn add(&mut self, key: &[u8], value: &[u8]) -> bool {
 | 
					
						
							|  |  |  |         assert!(!key.is_empty(), "key must not be empty");
 | 
					
						
							| 
									
										
										
										
											2022-12-23 21:14:11 -05:00
										 |  |  |         if self.estimated_size() + key.len() + value.len() + SIZEOF_U16 * 3 > self.block_size
 | 
					
						
							| 
									
										
										
										
											2022-12-23 14:29:32 -05:00
										 |  |  |             && !self.is_empty()
 | 
					
						
							|  |  |  |         {
 | 
					
						
							|  |  |  |             return false;
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |         self.offsets.push(self.data.len() as u16);
 | 
					
						
							|  |  |  |         self.data.put_u16(key.len() as u16);
 | 
					
						
							|  |  |  |         self.data.put(key);
 | 
					
						
							|  |  |  |         self.data.put_u16(value.len() as u16);
 | 
					
						
							|  |  |  |         self.data.put(value);
 | 
					
						
							|  |  |  |         true
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-23 22:32:30 -05:00
										 |  |  |     /// Check if there is no key-value pair in the block.
 | 
					
						
							| 
									
										
										
										
											2022-12-23 14:29:32 -05:00
										 |  |  |     pub fn is_empty(&self) -> bool {
 | 
					
						
							|  |  |  |         self.offsets.is_empty()
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-23 22:32:30 -05:00
										 |  |  |     /// Finalize the block.
 | 
					
						
							| 
									
										
										
										
											2022-12-23 14:29:32 -05:00
										 |  |  |     pub fn build(self) -> Block {
 | 
					
						
							|  |  |  |         if self.is_empty() {
 | 
					
						
							|  |  |  |             panic!("block should not be empty");
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |         Block {
 | 
					
						
							|  |  |  |             data: self.data,
 | 
					
						
							|  |  |  |             offsets: self.offsets,
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 |