skimmer 0.0.3

Simple streams reader
Documentation
use crate::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)
    }
}