use std::fmt::Debug;
use std::hash::Hash;
use std::ops::{Add, AddAssign, Sub};
use borrow::Cow;
use endianity::Endianity;
use leb128;
use parser::{Error, Format, Result};
pub trait ReaderOffset
: Debug + Copy + Eq + Ord + Hash + Add<Output = Self> + AddAssign + Sub<Output = Self>
{
fn from_u8(offset: u8) -> Self;
fn from_u16(offset: u16) -> Self;
fn from_i16(offset: i16) -> Self;
fn from_u32(offset: u32) -> Self;
fn from_u64(offset: u64) -> Result<Self>;
fn into_u64(self) -> u64;
fn wrapping_add(self, other: Self) -> Self;
fn checked_sub(self, other: Self) -> Option<Self>;
}
impl ReaderOffset for u64 {
#[inline]
fn from_u8(offset: u8) -> Self {
offset as u64
}
#[inline]
fn from_u16(offset: u16) -> Self {
offset as u64
}
#[inline]
fn from_i16(offset: i16) -> Self {
offset as u64
}
#[inline]
fn from_u32(offset: u32) -> Self {
offset as u64
}
#[inline]
fn from_u64(offset: u64) -> Result<Self> {
Ok(offset)
}
#[inline]
fn into_u64(self) -> u64 {
self
}
#[inline]
fn wrapping_add(self, other: Self) -> Self {
self.wrapping_add(other)
}
#[inline]
fn checked_sub(self, other: Self) -> Option<Self> {
self.checked_sub(other)
}
}
impl ReaderOffset for u32 {
#[inline]
fn from_u8(offset: u8) -> Self {
offset as u32
}
#[inline]
fn from_u16(offset: u16) -> Self {
offset as u32
}
#[inline]
fn from_i16(offset: i16) -> Self {
offset as u32
}
#[inline]
fn from_u32(offset: u32) -> Self {
offset
}
#[inline]
fn from_u64(offset64: u64) -> Result<Self> {
let offset = offset64 as u32;
if offset as u64 == offset64 {
Ok(offset)
} else {
Err(Error::UnsupportedOffset)
}
}
#[inline]
fn into_u64(self) -> u64 {
self as u64
}
#[inline]
fn wrapping_add(self, other: Self) -> Self {
self.wrapping_add(other)
}
#[inline]
fn checked_sub(self, other: Self) -> Option<Self> {
self.checked_sub(other)
}
}
impl ReaderOffset for usize {
#[inline]
fn from_u8(offset: u8) -> Self {
offset as usize
}
#[inline]
fn from_u16(offset: u16) -> Self {
offset as usize
}
#[inline]
fn from_i16(offset: i16) -> Self {
offset as usize
}
#[inline]
fn from_u32(offset: u32) -> Self {
offset as usize
}
#[inline]
fn from_u64(offset64: u64) -> Result<Self> {
let offset = offset64 as usize;
if offset as u64 == offset64 {
Ok(offset)
} else {
Err(Error::UnsupportedOffset)
}
}
#[inline]
fn into_u64(self) -> u64 {
self as u64
}
#[inline]
fn wrapping_add(self, other: Self) -> Self {
self.wrapping_add(other)
}
#[inline]
fn checked_sub(self, other: Self) -> Option<Self> {
self.checked_sub(other)
}
}
pub trait Reader: Debug + Clone {
type Endian: Endianity;
type Offset: ReaderOffset;
fn endian(&self) -> Self::Endian;
fn len(&self) -> Self::Offset;
fn empty(&mut self);
fn truncate(&mut self, len: Self::Offset) -> Result<()>;
fn offset_from(&self, base: &Self) -> Self::Offset;
fn find(&self, byte: u8) -> Result<Self::Offset>;
fn skip(&mut self, len: Self::Offset) -> Result<()>;
fn split(&mut self, len: Self::Offset) -> Result<Self>;
fn to_slice(&self) -> Result<Cow<[u8]>>;
fn to_string(&self) -> Result<Cow<str>>;
fn to_string_lossy(&self) -> Result<Cow<str>>;
fn read_u8_array<A>(&mut self) -> Result<A>
where
A: Sized + Default + AsMut<[u8]>;
#[inline]
fn is_empty(&self) -> bool {
self.len() == Self::Offset::from_u8(0)
}
#[inline]
fn read_u8(&mut self) -> Result<u8> {
let a: [u8; 1] = self.read_u8_array()?;
Ok(a[0])
}
#[inline]
fn read_i8(&mut self) -> Result<i8> {
let a: [u8; 1] = self.read_u8_array()?;
Ok(a[0] as i8)
}
#[inline]
fn read_u16(&mut self) -> Result<u16> {
let a: [u8; 2] = self.read_u8_array()?;
Ok(self.endian().read_u16(&a))
}
#[inline]
fn read_i16(&mut self) -> Result<i16> {
let a: [u8; 2] = self.read_u8_array()?;
Ok(self.endian().read_i16(&a))
}
#[inline]
fn read_u32(&mut self) -> Result<u32> {
let a: [u8; 4] = self.read_u8_array()?;
Ok(self.endian().read_u32(&a))
}
#[inline]
fn read_i32(&mut self) -> Result<i32> {
let a: [u8; 4] = self.read_u8_array()?;
Ok(self.endian().read_i32(&a))
}
#[inline]
fn read_u64(&mut self) -> Result<u64> {
let a: [u8; 8] = self.read_u8_array()?;
Ok(self.endian().read_u64(&a))
}
#[inline]
fn read_i64(&mut self) -> Result<i64> {
let a: [u8; 8] = self.read_u8_array()?;
Ok(self.endian().read_i64(&a))
}
#[inline]
fn read_f32(&mut self) -> Result<f32> {
let a: [u8; 4] = self.read_u8_array()?;
Ok(self.endian().read_f32(&a))
}
#[inline]
fn read_f64(&mut self) -> Result<f64> {
let a: [u8; 8] = self.read_u8_array()?;
Ok(self.endian().read_f64(&a))
}
fn read_null_terminated_slice(&mut self) -> Result<Self> {
let idx = self.find(0)?;
let val = self.split(idx)?;
self.skip(Self::Offset::from_u8(1))?;
Ok(val)
}
fn read_uleb128(&mut self) -> Result<u64> {
leb128::read::unsigned(self)
}
fn read_sleb128(&mut self) -> Result<i64> {
leb128::read::signed(self)
}
fn read_address(&mut self, address_size: u8) -> Result<u64> {
match address_size {
1 => self.read_u8().map(|v| v as u64),
2 => self.read_u16().map(|v| v as u64),
4 => self.read_u32().map(|v| v as u64),
8 => self.read_u64(),
otherwise => Err(Error::UnsupportedAddressSize(otherwise)),
}
}
fn read_word(&mut self, format: Format) -> Result<u64> {
match format {
Format::Dwarf32 => self.read_u32().map(|v| v as u64),
Format::Dwarf64 => self.read_u64(),
}
}
fn read_offset(&mut self, format: Format) -> Result<Self::Offset> {
self.read_word(format).and_then(Self::Offset::from_u64)
}
}