use std::fmt::Debug;
use std::iter;
use std::marker::PhantomData;
use byteorder::{ByteOrder, LittleEndian};
use table;
use table::Table;
pub trait VectorItem {
fn indirect_lookup() -> bool;
fn inline_size() -> usize;
}
#[derive(Debug)]
pub struct Iterator<'a, T> {
buffer: &'a [u8],
index: usize,
len: usize,
i: usize,
_marker: PhantomData<[T]>
}
pub trait LittleEndianReader<'a> {
fn read(buffer: &'a [u8], index: usize) -> Self;
fn size() -> usize;
}
impl<'a> LittleEndianReader<'a>for u8 {
fn read(buffer: &[u8], index: usize) -> u8 { buffer[index] }
fn size() -> usize { 1 }
}
impl<'a> LittleEndianReader<'a>for i8 {
fn read(buffer: &[u8], index: usize) -> i8 { buffer[index] as i8 }
fn size() -> usize { 1 }
}
impl<'a> LittleEndianReader<'a>for bool {
fn read(buffer: &[u8], index: usize) -> bool { buffer[index] == 0 }
fn size() -> usize { 1 }
}
impl<'a> LittleEndianReader<'a>for u16 {
fn read(buffer: &[u8], index: usize) -> u16 { LittleEndian::read_u16(&buffer[index..]) }
fn size() -> usize { 2 }
}
impl<'a> LittleEndianReader<'a>for i16 {
fn read(buffer: &[u8], index: usize) -> i16 { LittleEndian::read_i16(&buffer[index..]) }
fn size() -> usize { 2 }
}
impl<'a> LittleEndianReader<'a>for u32 {
fn read(buffer: &[u8], index: usize) -> u32 { LittleEndian::read_u32(&buffer[index..]) }
fn size() -> usize { 4 }
}
impl<'a> LittleEndianReader<'a>for i32 {
fn read(buffer: &[u8], index: usize) -> i32 { LittleEndian::read_i32(&buffer[index..]) }
fn size() -> usize { 4 }
}
impl<'a> LittleEndianReader<'a>for u64 {
fn read(buffer: &[u8], index: usize) -> u64 { LittleEndian::read_u64(&buffer[index..]) }
fn size() -> usize { 8 }
}
impl<'a> LittleEndianReader<'a>for i64 {
fn read(buffer: &[u8], index: usize) -> i64 { LittleEndian::read_i64(&buffer[index..]) }
fn size() -> usize { 8 }
}
impl<'a> LittleEndianReader<'a>for f32 {
fn read(buffer: &[u8], index: usize) -> f32 { LittleEndian::read_f32(&buffer[index..]) }
fn size() -> usize { 4 }
}
impl<'a> LittleEndianReader<'a>for f64 {
fn read(buffer: &[u8], index: usize) -> f64 { LittleEndian::read_f64(&buffer[index..]) }
fn size() -> usize { 8 }
}
impl<'a> LittleEndianReader<'a>for &'a str {
fn read(buffer: &[u8], index:usize) -> &str {
use std::str;
let offset = LittleEndian::read_u32(&buffer[index..]) as usize + index;
let start = offset as usize + 4;
let length = table::read_uoffset(buffer, offset as usize) as usize;
let s = &buffer[start..start+length];
unsafe { str::from_utf8_unchecked(s) }
}
fn size() -> usize { 4 }
}
impl<'a, T: From<Table<'a>> + VectorItem> LittleEndianReader<'a>for T {
fn read(buffer: &'a [u8], index: usize) -> T {
let table = if T::indirect_lookup() {
Table::from_offset(buffer, index as usize)
} else {
Table::with_pos(&buffer, index as usize)
};
table.into()
}
fn size() -> usize { T::inline_size() }
}
impl<'a, T: LittleEndianReader<'a>> iter::Iterator for Iterator<'a, T> {
type Item = T;
fn next(&mut self) -> Option<T> {
if self.i < self.len {
self.i += 1;
let slice = &self.buffer[self.index..];
if slice.len() >= T::size() {
let res = T::read(self.buffer, self.index);
self.index += T::size();
return Some(res)
}
}
None
}
}
impl<'a, T: LittleEndianReader<'a> + Debug> ExactSizeIterator for Iterator<'a, T> {
fn len(&self) -> usize {
self.len
}
}
impl<'a, T> Default for Iterator<'a, T> {
fn default() -> Iterator<'a, T> {
Iterator {
buffer: &[],
index: 0,
len: 0,
i: 0,
_marker: PhantomData
}
}
}
impl<'a, T> Iterator<'a, T> {
pub fn new(buffer: &[u8], index: usize, len: usize) -> Iterator<T> {
Iterator {
buffer: buffer,
index: index,
len: len,
i: 0,
_marker: PhantomData
}
}
}