use crate::binary_coding::{decode, decode_sequence, encode, encode_sequence}; use crate::error::{DecodeErrorKind, Error}; use crate::store::{Column, Result}; use std::mem::size_of; use std::path::PathBuf; #[derive(Debug, Clone)] pub struct StoreHeader { pub table_folder: PathBuf, // This one is not encoded into the file pub number_of_columns: usize, pub deleted_count: usize, pub total_count: usize, pub primary_column: Column, pub indexed_columns: Vec, } #[derive(Debug, Clone)] pub struct StoreHeaderFixedPart { pub table_folder: PathBuf, // This one is not encoded into the file pub number_of_columns: usize, pub deleted_count: usize, pub total_count: usize, pub primary_column: Column, } impl StoreHeader { pub const NUMBER_OF_COLUMNS_SIZE: usize = size_of::(); pub const DELETED_COUNT_SIZE: usize = size_of::(); pub const TOTAL_COUNT_SIZE: usize = size_of::(); pub const PRIMARY_COLUMN_SIZE: usize = size_of::(); pub const FIXED_SIZE: usize = Self::NUMBER_OF_COLUMNS_SIZE + Self::DELETED_COUNT_SIZE + Self::TOTAL_COUNT_SIZE + Self::PRIMARY_COLUMN_SIZE; pub const NUMBER_OF_COLUMNS_OFFSET: usize = 0; pub const DELETED_COUNT_OFFSET: usize = Self::NUMBER_OF_COLUMNS_OFFSET + Self::NUMBER_OF_COLUMNS_SIZE; pub const TOTAL_COUNT_OFFSET: usize = Self::DELETED_COUNT_OFFSET + Self::DELETED_COUNT_SIZE; pub const PRIMARY_COLUMN_OFFSET: usize = Self::TOTAL_COUNT_OFFSET + Self::TOTAL_COUNT_SIZE; #[allow(dead_code)] pub const INDEXED_COLUMNS_OFFSET: usize = Self::PRIMARY_COLUMN_OFFSET + Self::PRIMARY_COLUMN_SIZE; fn indexed_columns_size(number_of_columns: usize) -> usize { size_of::() * number_of_columns } pub fn size(number_of_columns: usize) -> usize { Self::FIXED_SIZE + Self::indexed_columns_size(number_of_columns) } pub fn encode(&self) -> Result> { let mut result = encode(&self.number_of_columns)?; result.append(&mut encode(&self.deleted_count)?); result.append(&mut encode(&self.total_count)?); result.append(&mut encode(&self.primary_column)?); result.append(&mut encode_sequence(&self.indexed_columns)?); Ok(result) } pub fn buffer_for_fixed_decoding() -> [u8; Self::FIXED_SIZE] { [0; Self::FIXED_SIZE] } pub fn buffer_for_rest_decoding(header: &StoreHeaderFixedPart) -> Vec { vec![0; Self::indexed_columns_size(header.number_of_columns)] } pub async fn decode_fixed( table_folder: &PathBuf, result: &[u8], ) -> Result { let (number_of_columns, _) = decode::( &result[Self::NUMBER_OF_COLUMNS_OFFSET ..Self::NUMBER_OF_COLUMNS_OFFSET + Self::NUMBER_OF_COLUMNS_SIZE], ) .map_err(|e| Error::DecodeError(DecodeErrorKind::StoreHeaderNumberOfColumns, e))?; let (deleted_count, _) = decode::( &result [Self::DELETED_COUNT_OFFSET..Self::DELETED_COUNT_OFFSET + Self::DELETED_COUNT_SIZE], ) .map_err(|e| Error::DecodeError(DecodeErrorKind::StoreHeaderDeletedCount, e))?; let (total_count, _) = decode::( &result[Self::TOTAL_COUNT_OFFSET..Self::TOTAL_COUNT_OFFSET + Self::TOTAL_COUNT_SIZE], ) .map_err(|e| Error::DecodeError(DecodeErrorKind::StoreHeaderTotalCount, e))?; let (primary_column, _) = decode::( &result[Self::PRIMARY_COLUMN_OFFSET ..Self::PRIMARY_COLUMN_OFFSET + Self::PRIMARY_COLUMN_SIZE], ) .map_err(|e| Error::DecodeError(DecodeErrorKind::StoreHeaderPrimaryColumn, e))?; let header = StoreHeaderFixedPart { table_folder: table_folder.clone(), number_of_columns, deleted_count, total_count, primary_column, }; Ok(header) } pub async fn decode_rest(header: StoreHeaderFixedPart, result: &[u8]) -> Result { let indexed_columns: Vec = decode_sequence::(header.number_of_columns, result) .map_err(|e| Error::DecodeError(DecodeErrorKind::StoreHeaderIndexedColumns, e))?; Ok(StoreHeader { table_folder: header.table_folder, number_of_columns: header.number_of_columns, deleted_count: header.deleted_count, total_count: header.total_count, primary_column: header.primary_column, indexed_columns, }) } // returns new count pub fn increment_total_count(&mut self) -> usize { self.total_count += 1; self.total_count } // returns new count pub fn increment_deleted_count(&mut self) -> usize { self.deleted_count += 1; self.deleted_count } pub fn is_column_indexed(&self, column: Column) -> bool { self.indexed_columns[column as usize] } pub fn make_column_indexed(&mut self, column: Column) { self.indexed_columns[column as usize] = true } }