use std::io::{Read, Write, Error, ErrorKind};
use capwriter::{Save, Load};
use sigalign_core::reference::extensions::{
Serialize,
EstimateSize,
LabelStorage,
LabelRefStorage,
};
use crate::core::{EndianType, ReadBytesExt, WriteBytesExt};
use super::InMemoryStorage;
impl Serialize for InMemoryStorage {
fn save_to<W>(&self, mut writer: W) -> Result<(), Error> where
W: Write
{
writer.write_u64::<EndianType>(self.target_count as u64)?;
self.concatenated_sequence.save_to(&mut writer)?;
self.sequence_index.save_to(&mut writer)?;
self.concatenated_label.as_bytes().save_to(&mut writer)?;
self.label_index.save_to(&mut writer)?;
Ok(())
}
fn load_from<R>(mut reader: R) -> Result<Self, Error> where
R: Read,
Self: Sized,
{
let target_count = reader.read_u64::<EndianType>()? as usize;
let concatenated_sequence = Vec::load_from(&mut reader)?;
let sequence_index = Vec::load_from(&mut reader)?;
let concatenated_label = match String::from_utf8(Vec::<u8>::load_from(&mut reader)?) {
Ok(v) => v,
Err(_) => return Err(ErrorKind::InvalidData.into()),
};
let label_index = Vec::load_from(&mut reader)?;
Ok(Self {
target_count,
concatenated_sequence,
sequence_index,
concatenated_label,
label_index,
})
}
}
impl EstimateSize for InMemoryStorage {
fn serialized_size(&self) -> usize {
std::mem::size_of::<u64>()
+ self.concatenated_sequence.to_be_saved_size()
+ self.sequence_index.to_be_saved_size()
+ self.concatenated_label.as_bytes().to_be_saved_size()
+ self.label_index.to_be_saved_size()
}
}
impl LabelStorage for InMemoryStorage {
fn label_of_target_unchecked(&self, target_index: u32) -> String {
self.label_ref_of_target_unchecked(target_index).to_string()
}
}
impl LabelRefStorage for InMemoryStorage {
fn label_ref_of_target_unchecked(&self, target_index: u32) -> &str {
unsafe {
std::str::from_utf8_unchecked(
&self.concatenated_label.as_bytes()[
self.label_index[target_index as usize]
..self.label_index[target_index as usize +1]
]
)
}
}
}
impl InMemoryStorage {
pub fn get_label_safely(&self, target_index: u32) -> Option<String> {
if target_index as usize >= self.target_count {
return None
}
Some(self.label_of_target_unchecked(target_index))
}
pub fn get_label_ref_safely(&self, target_index: u32) -> Option<&str> {
if target_index as usize >= self.target_count {
return None
}
Some(self.label_ref_of_target_unchecked(target_index))
}
}