use crate::error::Result;
use crate::storage::core::{SharedStorage, Storage};
use std::sync::Arc;
#[derive(Debug)]
pub struct StorageView<S: Storage> {
parent: SharedStorage<S>,
offset: usize,
len: usize,
}
impl<S: Storage> StorageView<S> {
pub fn new(parent: SharedStorage<S>, offset: usize, len: usize) -> Result<Self> {
if offset + len > parent.get().len() {
return Err(crate::error::TorshError::IndexOutOfBounds {
index: offset + len,
size: parent.get().len(),
});
}
Ok(StorageView {
parent,
offset,
len,
})
}
pub fn parent(&self) -> &SharedStorage<S> {
&self.parent
}
pub fn offset(&self) -> usize {
self.offset
}
pub fn view_len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn end_offset(&self) -> usize {
self.offset + self.len
}
pub fn overlaps(&self, other: &StorageView<S>) -> bool {
if Arc::ptr_eq(self.parent.inner_arc(), other.parent.inner_arc()) {
let self_end = self.offset + self.len;
let other_end = other.offset + other.len;
!(self_end <= other.offset || other_end <= self.offset)
} else {
false
}
}
pub fn contains(&self, other: &StorageView<S>) -> bool {
if Arc::ptr_eq(self.parent.inner_arc(), other.parent.inner_arc()) {
self.offset <= other.offset && other.end_offset() <= self.end_offset()
} else {
false
}
}
pub fn is_adjacent(&self, other: &StorageView<S>) -> bool {
if Arc::ptr_eq(self.parent.inner_arc(), other.parent.inner_arc()) {
self.end_offset() == other.offset || other.end_offset() == self.offset
} else {
false
}
}
pub fn slice(&self, start: usize, len: usize) -> Result<StorageView<S>> {
if start + len > self.len {
return Err(crate::error::TorshError::IndexOutOfBounds {
index: start + len,
size: self.len,
});
}
StorageView::new(self.parent.clone(), self.offset + start, len)
}
pub fn split_at(&self, at: usize) -> Result<(StorageView<S>, StorageView<S>)> {
if at > self.len {
return Err(crate::error::TorshError::IndexOutOfBounds {
index: at,
size: self.len,
});
}
let left = StorageView::new(self.parent.clone(), self.offset, at)?;
let right = StorageView::new(self.parent.clone(), self.offset + at, self.len - at)?;
Ok((left, right))
}
pub fn split_at_positions(&self, positions: &[usize]) -> Result<Vec<StorageView<S>>> {
if positions.is_empty() {
return Ok(vec![self.clone()]);
}
for (i, &pos) in positions.iter().enumerate() {
if pos > self.len {
return Err(crate::error::TorshError::IndexOutOfBounds {
index: pos,
size: self.len,
});
}
if i > 0 && pos <= positions[i - 1] {
return Err(crate::error::TorshError::InvalidArgument(
"Split positions must be sorted and unique".to_string(),
));
}
}
let mut views = Vec::new();
let mut last_pos = 0;
for &pos in positions {
if pos > last_pos {
views.push(StorageView::new(
self.parent.clone(),
self.offset + last_pos,
pos - last_pos,
)?);
}
last_pos = pos;
}
if last_pos < self.len {
views.push(StorageView::new(
self.parent.clone(),
self.offset + last_pos,
self.len - last_pos,
)?);
}
Ok(views)
}
pub fn merge(&self, other: &StorageView<S>) -> Result<StorageView<S>> {
if !Arc::ptr_eq(self.parent.inner_arc(), other.parent.inner_arc()) {
return Err(crate::error::TorshError::InvalidArgument(
"Cannot merge views from different parent storage".to_string(),
));
}
let (start_offset, total_len) = if self.end_offset() == other.offset {
(self.offset, self.len + other.len)
} else if other.end_offset() == self.offset {
(other.offset, other.len + self.len)
} else {
return Err(crate::error::TorshError::InvalidArgument(
"Views are not adjacent and cannot be merged".to_string(),
));
};
StorageView::new(self.parent.clone(), start_offset, total_len)
}
pub fn can_extend(&self, additional_len: usize) -> bool {
self.offset + self.len + additional_len <= self.parent.get().len()
}
pub fn extend(&self, additional_len: usize) -> Result<StorageView<S>> {
if !self.can_extend(additional_len) {
return Err(crate::error::TorshError::IndexOutOfBounds {
index: self.offset + self.len + additional_len,
size: self.parent.get().len(),
});
}
StorageView::new(self.parent.clone(), self.offset, self.len + additional_len)
}
pub fn statistics(&self) -> ViewStatistics {
ViewStatistics {
offset: self.offset,
length: self.len,
parent_length: self.parent.get().len(),
parent_ref_count: self.parent.strong_count(),
coverage_ratio: self.len as f64 / self.parent.get().len() as f64,
}
}
pub fn to_owned_storage(&self) -> Result<S>
where
S: Clone,
{
self.parent.get().clone_storage()
}
}
impl<S: Storage> Clone for StorageView<S> {
fn clone(&self) -> Self {
StorageView {
parent: self.parent.clone(),
offset: self.offset,
len: self.len,
}
}
}
#[derive(Debug, Clone)]
pub struct ViewStatistics {
pub offset: usize,
pub length: usize,
pub parent_length: usize,
pub parent_ref_count: usize,
pub coverage_ratio: f64,
}
impl std::fmt::Display for ViewStatistics {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"ViewStats(offset={}, len={}, parent_len={}, refs={}, coverage={:.2}%)",
self.offset,
self.length,
self.parent_length,
self.parent_ref_count,
self.coverage_ratio * 100.0
)
}
}
#[derive(Debug)]
pub struct ViewBuilder<S: Storage> {
parent: SharedStorage<S>,
operations: Vec<ViewOperation>,
}
#[derive(Debug, Clone)]
enum ViewOperation {
Slice { start: usize, len: usize },
SplitAt { position: usize },
Extend { additional_len: usize },
}
impl<S: Storage> ViewBuilder<S> {
pub fn new(parent: SharedStorage<S>) -> Self {
Self {
parent,
operations: Vec::new(),
}
}
pub fn slice(mut self, start: usize, len: usize) -> Self {
self.operations.push(ViewOperation::Slice { start, len });
self
}
pub fn split_at(mut self, position: usize) -> Self {
self.operations.push(ViewOperation::SplitAt { position });
self
}
pub fn extend(mut self, additional_len: usize) -> Self {
self.operations
.push(ViewOperation::Extend { additional_len });
self
}
pub fn build(self) -> Result<StorageView<S>> {
let parent_len = self.parent.get().len();
let mut current_view = StorageView::new(self.parent, 0, parent_len)?;
for operation in self.operations {
current_view = match operation {
ViewOperation::Slice { start, len } => current_view.slice(start, len)?,
ViewOperation::SplitAt { position } => {
let (left, _right) = current_view.split_at(position)?;
left
}
ViewOperation::Extend { additional_len } => current_view.extend(additional_len)?,
};
}
Ok(current_view)
}
pub fn build_multiple(self) -> Result<Vec<StorageView<S>>> {
Ok(vec![self.build()?])
}
}
pub mod utils {
use super::*;
pub fn find_overlapping_views<S: Storage>(views: &[StorageView<S>]) -> Vec<(usize, usize)> {
let mut overlaps = Vec::new();
for (i, view1) in views.iter().enumerate() {
for (j, view2) in views.iter().enumerate().skip(i + 1) {
if view1.overlaps(view2) {
overlaps.push((i, j));
}
}
}
overlaps
}
pub fn merge_adjacent_views<S: Storage>(
views: Vec<StorageView<S>>,
) -> Result<Vec<StorageView<S>>> {
if views.is_empty() {
return Ok(views);
}
let mut result = Vec::new();
let mut views_iter = views.into_iter();
let mut current = views_iter
.next()
.expect("views is non-empty after is_empty check");
for view in views_iter {
match current.merge(&view) {
Ok(merged) => current = merged,
Err(_) => {
result.push(current);
current = view;
}
}
}
result.push(current);
Ok(result)
}
pub fn calculate_coverage<S: Storage>(views: &[StorageView<S>]) -> f64 {
if views.is_empty() {
return 0.0;
}
let total_view_elements: usize = views.iter().map(|v| v.view_len()).sum();
let parent_elements = views[0].parent().get().len();
if parent_elements == 0 {
return 0.0;
}
total_view_elements as f64 / parent_elements as f64
}
pub fn views_cover_parent<S: Storage>(views: &[StorageView<S>]) -> bool {
if views.is_empty() {
return false;
}
let mut coverage = vec![false; views[0].parent().get().len()];
for view in views {
for i in view.offset()..view.end_offset() {
if i < coverage.len() {
coverage[i] = true;
}
}
}
coverage.iter().all(|&covered| covered)
}
}