use crate::bases::*;
use std::{borrow::Cow, sync::Arc};
use super::{ByteSlice, ByteStream};
#[derive(Debug, Clone)]
pub struct ByteRegion {
pub(crate) source: Arc<dyn Source>,
pub(crate) region: Region,
}
impl ByteRegion {
pub fn size(&self) -> Size {
self.region.size()
}
pub fn stream(&self) -> ByteStream {
ByteStream::new_from_parts(Arc::clone(&self.source), self.region, self.region.begin())
}
pub fn cut(&self, offset: Offset, size: Size) -> ByteSlice<'_> {
let region = self.region.cut_rel(offset, size);
ByteSlice {
source: &self.source,
region,
}
}
pub fn as_slice(&self) -> ByteSlice<'_> {
ByteSlice {
source: &self.source,
region: self.region,
}
}
pub fn get_slice(&self, offset: Offset, size: usize) -> Result<Cow<'_, [u8]>> {
let region = self.region.cut_rel_asize(offset, ASize::new(size));
self.source.get_slice(region, BlockCheck::None)
}
}
impl From<ByteSlice<'_>> for ByteRegion {
fn from(byte_slice: ByteSlice<'_>) -> Self {
Self {
source: Arc::clone(byte_slice.source),
region: byte_slice.region,
}
}
}
impl RandomParser for ByteRegion {
type Parser<'s> = SliceParser<'s>;
fn create_parser(&self, offset: Offset) -> Result<Self::Parser<'_>> {
let size = self.region.size() - offset.into();
let size = std::cmp::min(0xFFFF_u64, size.into_u64()) as usize;
let region = self.region.cut_rel_asize(offset, size.into());
Ok(SliceParser::new(
self.source.get_slice(region, BlockCheck::None)?,
self.region.begin() + offset,
))
}
fn global_offset(&self) -> Offset {
self.region.begin()
}
fn read_slice(&self, offset: Offset, size: usize) -> Result<Cow<'_, [u8]>> {
let region = self.region.cut_rel_asize(offset, ASize::from(size));
self.source.get_slice(region, BlockCheck::None)
}
fn read_data(&self, offset: Offset, buf: &mut [u8]) -> IoResult<()> {
self.source.read_exact(self.region.begin() + offset, buf)
}
}
#[cfg(feature = "explorable_serde")]
impl serde::Serialize for ByteRegion {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let size = self.size();
if size.into_u64() < 0xFFFF {
serializer.serialize_bytes(
&self
.get_slice(Offset::zero(), self.size().into_u64() as usize)
.unwrap(),
)
} else {
serializer.serialize_str(&format!(
"ByteRegion of size {size} to big to be serialized"
))
}
}
}
#[cfg(feature = "explorable")]
impl graphex::Display for ByteRegion {
fn print_content(&self, out: &mut graphex::Output) -> graphex::Result {
let size = std::cmp::min(self.size().into_u64(), 0xFFFF) as usize;
let slice = self.get_slice(Offset::zero(), size)?;
writeln!(out, "{:?}", slice)
}
}
#[cfg(feature = "explorable")]
impl graphex::Node for ByteRegion {
fn display(&self) -> &dyn graphex::Display {
self
}
#[cfg(feature = "explorable_serde")]
fn serde(&self) -> Option<&dyn erased_serde::Serialize> {
Some(self)
}
}