use std::fmt;
use crate::errors::CondowError;
use bytes::Bytes;
mod bytes_stream;
mod chunk_stream;
mod ordered_chunk_stream;
pub use bytes_stream::{BytesStream, BytesStreamItem};
pub use chunk_stream::*;
pub use ordered_chunk_stream::*;
pub type ChunkStreamItem = Result<Chunk, CondowError>;
#[derive(Debug, Clone)]
pub struct Chunk {
pub part_index: u64,
pub chunk_index: usize,
pub blob_offset: u64,
pub range_offset: u64,
pub bytes: Bytes,
pub bytes_left: u64,
}
impl Chunk {
pub fn is_last(&self) -> bool {
self.bytes_left == 0
}
pub fn len(&self) -> usize {
self.bytes.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct BytesHint(u64, Option<u64>);
impl BytesHint {
pub fn new(lower_bound: u64, upper_bound: Option<u64>) -> Self {
BytesHint(lower_bound, upper_bound)
}
pub fn new_exact(bytes: u64) -> Self {
Self(bytes, Some(bytes))
}
pub fn new_at_max(bytes: u64) -> Self {
Self(0, Some(bytes))
}
pub fn new_no_hint() -> Self {
Self(0, None)
}
pub fn lower_bound(&self) -> u64 {
self.0
}
pub fn upper_bound(&self) -> Option<u64> {
self.1
}
pub fn is_exact(&self) -> bool {
if let Some(upper) = self.1 {
upper == self.0
} else {
false
}
}
pub fn exact(&self) -> Option<u64> {
if self.is_exact() {
self.1
} else {
None
}
}
#[inline]
pub fn reduce_by(&mut self, by: u64) {
if by == 0 {
return;
}
match self {
BytesHint(0, None) => {}
BytesHint(min, None) => {
if *min >= by {
*min -= by;
} else {
*self = BytesHint::new_no_hint()
}
}
BytesHint(0, Some(max)) => {
if *max >= by {
*max -= by;
} else {
*self = BytesHint::new_no_hint()
}
}
BytesHint(min, Some(max)) => {
if *min >= by {
*min -= by;
} else {
*min = 0;
}
if *max >= by {
*max -= by;
} else {
self.1 = None
}
}
}
}
pub fn combine(self, other: BytesHint) -> BytesHint {
let (me_lower, me_upper) = self.into_inner();
let (other_lower, other_upper) = other.into_inner();
let lower_bound = me_lower + other_lower;
let upper_bound = match (me_upper, other_upper) {
(Some(a), Some(b)) => Some(a + b),
(Some(_), None) => None,
(None, Some(_)) => None,
(None, None) => None,
};
BytesHint::new(lower_bound, upper_bound)
}
pub fn into_inner(self) -> (u64, Option<u64>) {
(self.lower_bound(), self.upper_bound())
}
}
impl fmt::Display for BytesHint {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let (lower, upper) = self.into_inner();
match upper {
Some(upper) => write!(f, "[{}..{}]", lower, upper),
None => write!(f, "[{}..?[", lower),
}
}
}