use crate::DbError;
use crate::utilities::serialize::Serialize;
#[derive(Debug, Clone, Copy, Default)]
pub struct StorageRecord {
pub index: u64,
pub pos: u64,
pub size: u64,
}
impl StorageRecord {
pub fn value_start(&self) -> u64 {
self.pos + self.index.serialized_size() + self.size.serialized_size()
}
pub fn end(&self) -> u64 {
self.value_start() + self.size
}
}
#[derive(Debug, Clone)]
pub struct StorageRecords {
records: Vec<StorageRecord>,
}
impl StorageRecords {
pub fn new() -> Self {
Self {
records: vec![StorageRecord::default()],
}
}
pub fn new_record(&mut self, pos: u64, size: u64) -> StorageRecord {
let record;
if self.records[0].index != 0 {
let index = self.records[0].index;
self.records[0].index = self.records[index as usize].index;
record = StorageRecord { index, pos, size };
self.records[index as usize] = record;
} else {
record = StorageRecord {
index: self.records.len() as u64,
pos,
size,
};
self.records.push(record);
}
record
}
pub fn records(&self) -> Vec<StorageRecord> {
let mut res = Vec::with_capacity(self.records.len());
for record in &self.records {
if self.is_valid(record) {
res.push(*record);
}
}
res.sort_by(|left, right| left.pos.cmp(&right.pos));
res
}
pub fn set_pos(&mut self, index: u64, pos: u64) {
if let Some(i) = self.records.get_mut(index as usize) {
i.pos = pos;
}
}
pub fn set_records(&mut self, records: Vec<StorageRecord>) {
self.records = records;
for index in 1..self.records.len() {
if !self.is_valid(&self.records[index]) {
self.remove_index(index as u64);
}
}
}
pub fn set_size(&mut self, index: u64, size: u64) {
if let Some(i) = self.records.get_mut(index as usize) {
i.size = size;
}
}
pub fn record(&self, index: u64) -> Result<StorageRecord, DbError> {
if let Some(record) = self.records.get(index as usize)
&& self.is_valid(record)
{
return Ok(*record);
}
Err(DbError::from(format!(
"Storage error: index ({index}) not found"
)))
}
pub fn remove_index(&mut self, index: u64) {
let next_free = self.records[0].index;
if let Some(record) = self.records.get_mut(index as usize) {
record.index = next_free;
record.pos = u64::MAX;
self.records[0].index = index;
}
}
fn is_valid(&self, record: &StorageRecord) -> bool {
record.index != 0 && self.records[record.index as usize].index == record.index
}
}