use crate::{Cursor, Offset};
use super::Storage;
use std::io;
pub(crate) struct Segment<T> {
pub(crate) data: Vec<T>,
total_size: u64,
pub(crate) absolute_offset: u64,
}
pub(crate) enum SegmentPosition {
Next(u64),
Done(u64),
}
impl<T> Segment<T>
where
T: Storage + Clone,
{
pub(crate) fn with_offset(absolute_offset: u64) -> Self {
Self {
data: Vec::with_capacity(1024),
absolute_offset,
total_size: 0,
}
}
pub(crate) fn new() -> Self {
Self {
data: Vec::with_capacity(1024),
absolute_offset: 0,
total_size: 0,
}
}
#[inline]
pub(crate) fn next_offset(&self) -> u64 {
self.absolute_offset + self.len()
}
#[inline]
pub(crate) fn push(&mut self, inner_type: T) {
self.total_size += inner_type.size() as u64;
self.data.push(inner_type);
}
#[inline]
pub(crate) fn readv(
&self,
cursor: Cursor,
len: u64,
out: &mut Vec<(T, Offset)>,
) -> io::Result<SegmentPosition> {
let idx = cursor.1 - self.absolute_offset;
let mut ret: Option<u64>;
if idx >= self.len() {
ret = None;
} else {
let mut limit = idx + len;
ret = Some(limit);
if limit >= self.len() {
ret = None;
limit = self.len();
}
let offsets = std::iter::repeat(cursor.0).zip(cursor.1..cursor.1 + limit);
let o = self.data[idx as usize..limit as usize]
.iter()
.cloned()
.zip(offsets);
out.extend(o);
}
match ret {
Some(relative_offset) => Ok(SegmentPosition::Next(
self.absolute_offset + relative_offset,
)),
None => Ok(SegmentPosition::Done(self.next_offset())),
}
}
#[inline]
pub(crate) fn len(&self) -> u64 {
self.data.len() as u64
}
#[inline]
pub(crate) fn size(&self) -> u64 {
self.total_size
}
#[inline]
pub fn last(&self) -> Option<T> {
self.data.last().cloned()
}
}
#[cfg(test)]
mod tests {
use super::*;
use bytes::Bytes;
#[test]
fn segment_works_for_bytes() {
let mut mem_segment: Segment<Bytes> = Segment::new();
let test_byte = Bytes::from_static(b"test1");
mem_segment.push(test_byte.clone());
assert_eq!(mem_segment.len(), 1);
assert_eq!(mem_segment.last().unwrap(), test_byte);
}
#[test]
fn readv_works_for_bytes() {
let mut segment: Segment<Bytes> = Segment::new();
segment.push(Bytes::from_static(b"test1"));
segment.push(Bytes::from_static(b"test2"));
segment.push(Bytes::from_static(b"test3"));
segment.push(Bytes::from_static(b"test4"));
segment.push(Bytes::from_static(b"test5"));
segment.push(Bytes::from_static(b"test6"));
segment.push(Bytes::from_static(b"test7"));
segment.push(Bytes::from_static(b"test8"));
segment.push(Bytes::from_static(b"test9"));
assert_eq!(segment.len(), 9);
let mut out: Vec<(Bytes, Offset)> = Vec::new();
let _ = segment.readv((0, 0), 2, &mut out).unwrap();
assert_eq!(
out,
vec![
(Bytes::from_static(b"test1"), (0, 0)),
(Bytes::from_static(b"test2"), (0, 1))
]
);
}
#[test]
fn readv_works_for_vec_of_u8() {
let mut segment: Segment<Vec<u8>> = Segment::new();
segment.push(vec![1u8]);
segment.push(vec![2u8]);
segment.push(vec![3u8]);
segment.push(vec![4u8]);
segment.push(vec![5u8]);
segment.push(vec![6u8]);
segment.push(vec![7u8]);
segment.push(vec![8u8]);
segment.push(vec![9u8]);
assert_eq!(segment.len(), 9);
let mut out: Vec<(Vec<u8>, Offset)> = Vec::new();
let _ = segment.readv((0, 0), 2, &mut out).unwrap();
assert_eq!(out, vec![(vec![1u8], (0, 0)), (vec![2u8], (0, 1))]);
}
}