use marker::Marker;
use std::fmt::Debug;
pub trait Datum : Clone + Debug {
fn len (&self) -> usize;
fn as_slice (&self) -> &[u8];
}
pub struct Data<Datum> {
data: Vec<Datum>
}
impl<D> Data<D>
where
D: Datum
{
pub fn with_capacity (size: usize) -> Data<D> { Data { data: Vec::with_capacity (size) } }
pub fn clear (&mut self) { self.data.clear () }
pub fn amount (&self) -> usize { self.data.len () }
pub fn push (&mut self, datum: D) { self.data.push (datum) }
pub fn marker_len (&self, marker: &Marker) -> usize {
if marker.pos1.0 == marker.pos2.0 { marker.pos2.1 - marker.pos1.1 } else {
let mut tot_len = 0;
tot_len += self.data[marker.pos1.0].len () - marker.pos1.1;
tot_len += marker.pos2.1;
for i in marker.pos1.0 + 1 .. marker.pos2.0 { tot_len += self.data[i].len (); }
tot_len
}
}
pub fn resize (&self, marker: Marker, newlen: usize) -> Marker {
if marker.pos1.0 == marker.pos2.0 {
Marker::new (
(marker.pos1.0, marker.pos1.1),
(marker.pos2.0, marker.pos1.1 + newlen)
)
} else {
let ref datum = self.data[marker.pos1.0];
if datum.len () - marker.pos1.1 >= newlen {
Marker::new (
(marker.pos1.0, marker.pos1.1),
(marker.pos1.0, marker.pos1.1 + newlen)
)
} else {
let pos1 = marker.pos1;
let mut pos2 = marker.pos1;
let mut tot_len = newlen - (datum.len () - marker.pos1.1);
loop {
pos2.0 += 1;
let ref datum = self.data[pos2.0];
if datum.len () >= tot_len {
pos2.1 = tot_len;
break;
} else {
tot_len -= datum.len ();
}
}
Marker::new ( pos1, pos2 )
}
}
}
pub fn chunk<'a, 'b> (&'a self, marker: &'b Marker) -> Chunk<'a> {
if marker.pos1.0 == marker.pos2.0 {
self._chunk_slice (marker.pos1.0, marker.pos1.1, marker.pos2.1)
} else {
self._chunk_vec (marker)
}
}
fn _chunk_slice<'a> (&'a self, datum_idx: usize, start: usize, end: usize) -> Chunk<'a> {
Chunk::Slice (&self.data[datum_idx].as_slice ()[start .. end])
}
fn _chunk_vec<'a, 'b> (&'a self, marker: &'b Marker) -> Chunk<'a> {
let mut vec: Vec<u8>;
let mut len = 0;
len += self.data[marker.pos1.0].len () - marker.pos1.1;
len += marker.pos2.1;
if marker.pos2.0 - marker.pos1.0 > 1 {
for i in marker.pos1.0 + 1 .. marker.pos2.0 {
len += self.data[i].len ();
}
}
vec = Vec::with_capacity (len);
vec.extend (&self.data[marker.pos1.0].as_slice ()[marker.pos1.1 .. ]);
if marker.pos2.0 - marker.pos1.0 > 1 {
for i in marker.pos1.0 + 1 .. marker.pos2.0 {
vec.extend (self.data[i].as_slice ());
}
}
vec.extend (&self.data[marker.pos2.0].as_slice ()[ .. marker.pos2.1]);
Chunk::Vec (vec)
}
}
pub enum Chunk<'a> {
Slice (&'a [u8]),
Vec (Vec<u8>)
}
impl<'a> Chunk<'a> {
pub fn as_slice (&self) -> &[u8] { self.into () }
}
impl<'a, 'b> Into<&'b [u8]> for &'b Chunk<'a> {
fn into (self) -> &'b [u8] {
match *self {
Chunk::Slice (slice) => slice,
Chunk::Vec (ref v) => v.as_slice ()
}
}
}
impl<'a> From<Vec<u8>> for Chunk<'a> {
fn from (v: Vec<u8>) -> Chunk<'a> { Chunk::Vec (v) }
}