use std::cmp;
#[derive(Clone, Debug)]
pub struct Map {
length: usize,
entries: Vec<Entry>,
header: Vec<u8>,
data: Vec<u8>,
}
#[derive(Clone, Debug)]
struct Entry {
offset: usize,
length: usize,
field: &'static str,
}
impl Map {
pub(crate) fn new(header: Vec<u8>) -> Self {
Map {
length: 0,
entries: Vec::new(),
header: header,
data: Vec::new(),
}
}
pub(crate) fn add(&mut self, field: &'static str, length: usize) {
self.entries.push(Entry {
offset: self.length, length: length, field: field
});
self.length += length;
}
pub(crate) fn finalize(&mut self, data: Vec<u8>) {
self.data = data;
}
pub fn iter<'a>(&'a self) -> Iter<'a> {
Iter::new(self)
}
}
#[derive(Clone, Debug)]
pub struct Field<'a> {
pub name: &'static str,
pub offset: usize,
pub length: usize,
pub data: &'a [u8],
}
impl<'a> Field<'a> {
fn new(map: &'a Map, i: usize) -> Field<'a> {
if i == 0 {
Field {
offset: 0,
length: map.header.len(),
name: "frame",
data: map.header.as_slice()
}
} else {
let len = map.data.len();
let e = &map.entries[i - 1];
let start = cmp::min(len, e.offset);
let end = cmp::min(len, e.offset + e.length);
Field {
offset: map.header.len() + e.offset,
length: e.length,
name: e.field,
data: &map.data[start..end],
}
}
}
}
pub struct Iter<'a> {
map: &'a Map,
i: usize,
}
impl<'a> Iter<'a> {
fn new(map: &'a Map) -> Iter<'a> {
Iter {
map: map,
i: 0,
}
}
}
impl<'a> Iterator for Iter<'a> {
type Item = Field<'a>;
fn next(&mut self) -> Option<Self::Item> {
if self.i < self.map.entries.len() + 1 {
self.i += 1;
Some(Field::new(self.map, self.i - 1))
} else {
None
}
}
}