Now have a structure that actually works

This commit is contained in:
Bradlee Speice 2019-04-26 16:08:55 -04:00
parent 0835e4bc26
commit 01d42890f6
2 changed files with 126 additions and 173 deletions

View File

@ -1,5 +1,4 @@
use std::io; use std::cell::RefCell;
use std::marker::PhantomData;
#[derive(Debug, PartialEq, Eq, Clone, Copy)] #[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Needed { pub enum Needed {
@ -9,101 +8,85 @@ pub enum Needed {
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
pub enum KError<'a> { pub enum KError<'a> {
Incomplete(Needed), Incomplete(Needed),
MissingRoot,
UnexpectedContents { actual: &'a [u8] }, UnexpectedContents { actual: &'a [u8] },
UnknownVariant(u64), UnknownVariant(u64),
} }
pub type KResult<'a, T> = Result<T, KError<'a>>; pub type KResult<'a, T> = Result<T, KError<'a>>;
// TODO: Do we need extra lifetimes for parents/roots?
// Likely not necessary since everyone effectively lives
// as long as the stream, but worth looking into
pub trait KStruct<'a> { pub trait KStruct<'a> {
type Parent: KStruct<'a>; type Parent: KStruct<'a>;
type Root: KStruct<'a>; type Root: KStruct<'a>;
/// Create a new instance of this struct; if we are the root node,
/// then both `_parent` and `_root` will be `None`.
fn new(_parent: Option<&'a Self::Parent>, _root: Option<&'a Self::Root>) -> Self
where
Self: Sized;
/// Parse this struct (and any children) from the supplied stream /// Parse this struct (and any children) from the supplied stream
fn read<'s: 'a, S: KStream>(&mut self, stream: &'s mut S) -> KResult<'s, ()>; fn read<'s: 'a, S: KStream>(
&mut self,
/// Get the root of this parse structure _io: &'s S,
fn root(&self) -> &'a Self::Root; _root: Option<&Self::Root>,
_parent: Option<&Self::Parent>,
) -> KResult<'s, ()>;
} }
/// Dummy struct used to indicate an absence of value; needed for /// Dummy struct used to indicate an absence of value; needed for
/// root structs to satisfy the associate type bounds in the /// root structs to satisfy the associated type bounds in the
/// `KStruct` trait. /// `KStruct` trait.
#[derive(Debug, Default, Copy, Clone, PartialEq)] #[derive(Debug, Default, Copy, Clone, PartialEq)]
pub struct KStructUnit<'a> { pub struct KStructUnit;
phantom: PhantomData<&'a ()>, impl<'a> KStruct<'a> for KStructUnit {
} type Parent = KStructUnit;
impl<'a> KStruct<'a> for KStructUnit<'a> { type Root = KStructUnit;
type Parent = KStructUnit<'a>;
type Root = KStructUnit<'a>;
fn new(_parent: Option<&'a Self::Parent>, _root: Option<&'a Self::Root>) -> Self fn read<'s: 'a, S: KStream>(
where &mut self,
Self: Sized, _io: &'s S,
{ _root: Option<&Self::Root>,
KStructUnit { _parent: Option<&Self::Parent>,
phantom: PhantomData, ) -> KResult<'s, ()> {
}
}
fn read<'s: 'a, S: KStream>(&mut self, _stream: &'s mut S) -> KResult<'s, ()> {
Ok(()) Ok(())
} }
fn root(&self) -> &'a Self::Root {
panic!("Attempted to get root of unit structure.")
}
} }
pub trait KStream { pub trait KStream {
fn is_eof(&self) -> io::Result<bool>; fn is_eof(&self) -> KResult<bool>;
fn seek(&mut self, position: u64) -> io::Result<()>; fn seek(&self, position: u64) -> KResult<()>;
fn pos(&self) -> io::Result<u64>; fn pos(&self) -> KResult<u64>;
fn size(&self) -> io::Result<u64>; fn size(&self) -> KResult<u64>;
fn read_s1(&mut self) -> io::Result<i8>; fn read_s1(&self) -> KResult<i8>;
fn read_s2be(&mut self) -> io::Result<i16>; fn read_s2be(&self) -> KResult<i16>;
fn read_s4be(&mut self) -> io::Result<i32>; fn read_s4be(&self) -> KResult<i32>;
fn read_s8be(&mut self) -> io::Result<i64>; fn read_s8be(&self) -> KResult<i64>;
fn read_s2le(&mut self) -> io::Result<i16>; fn read_s2le(&self) -> KResult<i16>;
fn read_s4le(&mut self) -> io::Result<i32>; fn read_s4le(&self) -> KResult<i32>;
fn read_s8le(&mut self) -> io::Result<i64>; fn read_s8le(&self) -> KResult<i64>;
fn read_u1(&mut self) -> io::Result<u8>; fn read_u1(&self) -> KResult<u8>;
fn read_u2be(&mut self) -> io::Result<u16>; fn read_u2be(&self) -> KResult<u16>;
fn read_u4be(&mut self) -> io::Result<u32>; fn read_u4be(&self) -> KResult<u32>;
fn read_u8be(&mut self) -> io::Result<u64>; fn read_u8be(&self) -> KResult<u64>;
fn read_u2le(&mut self) -> io::Result<u16>; fn read_u2le(&self) -> KResult<u16>;
fn read_u4le(&mut self) -> io::Result<u32>; fn read_u4le(&self) -> KResult<u32>;
fn read_u8le(&mut self) -> io::Result<u64>; fn read_u8le(&self) -> KResult<u64>;
fn read_f4be(&mut self) -> io::Result<f32>; fn read_f4be(&self) -> KResult<f32>;
fn read_f8be(&mut self) -> io::Result<f64>; fn read_f8be(&self) -> KResult<f64>;
fn read_f4le(&mut self) -> io::Result<f32>; fn read_f4le(&self) -> KResult<f32>;
fn read_f8le(&mut self) -> io::Result<f64>; fn read_f8le(&self) -> KResult<f64>;
fn align_to_byte(&mut self) -> io::Result<()>; fn align_to_byte(&self) -> KResult<()>;
fn read_bits_int(&mut self, n: u32) -> io::Result<u64>; fn read_bits_int(&self, n: u32) -> KResult<u64>;
fn read_bytes(&mut self, len: usize) -> KResult<&[u8]>; fn read_bytes(&self, len: usize) -> KResult<&[u8]>;
fn read_bytes_full(&mut self) -> KResult<&[u8]>; fn read_bytes_full(&self) -> KResult<&[u8]>;
fn read_bytes_term( fn read_bytes_term(
&mut self, &self,
term: char, term: char,
include: bool, include: bool,
consume: bool, consume: bool,
eos_error: bool, eos_error: bool,
) -> KResult<&[u8]>; ) -> KResult<&[u8]>;
fn ensure_fixed_contents(&mut self, expected: &[u8]) -> KResult<&[u8]> { fn ensure_fixed_contents(&self, expected: &[u8]) -> KResult<&[u8]> {
let actual = self.read_bytes(expected.len())?; let actual = self.read_bytes(expected.len())?;
if actual == expected { if actual == expected {
Ok(actual) Ok(actual)
@ -141,154 +124,141 @@ pub trait KStream {
} }
} }
#[allow(dead_code)] #[derive(Default)]
pub struct BytesReader<'a> { struct BytesReaderState {
bytes: &'a [u8],
pos: usize, pos: usize,
bits: u8, bits: u8,
bits_left: u8, bits_left: u8,
} }
impl<'a> BytesReader<'a> { pub struct BytesReader<'a> {
fn new(bytes: &'a [u8]) -> Self { state: RefCell<BytesReaderState>,
BytesReader { bytes: &'a [u8],
bytes,
pos: 0,
bits: 0,
bits_left: 0,
}
}
fn remaining(&self) -> usize {
self.bytes.len().checked_sub(self.pos).unwrap_or(0)
}
} }
impl<'a> From<&'a [u8]> for BytesReader<'a> { impl<'a> BytesReader<'a> {
fn from(b: &'a [u8]) -> Self { pub fn new(bytes: &'a [u8]) -> Self {
BytesReader::new(b) BytesReader {
state: RefCell::new(BytesReaderState::default()),
bytes,
}
} }
} }
impl<'a> KStream for BytesReader<'a> { impl<'a> KStream for BytesReader<'a> {
fn is_eof(&self) -> io::Result<bool> { fn is_eof(&self) -> KResult<bool> {
unimplemented!() unimplemented!()
} }
fn seek(&mut self, _position: u64) -> io::Result<()> { fn seek(&self, position: u64) -> KResult<()> {
unimplemented!() unimplemented!()
} }
fn pos(&self) -> io::Result<u64> { fn pos(&self) -> KResult<u64> {
unimplemented!() unimplemented!()
} }
fn size(&self) -> io::Result<u64> { fn size(&self) -> KResult<u64> {
unimplemented!() unimplemented!()
} }
fn read_s1(&mut self) -> io::Result<i8> { fn read_s1(&self) -> KResult<i8> {
unimplemented!() unimplemented!()
} }
fn read_s2be(&mut self) -> io::Result<i16> { fn read_s2be(&self) -> KResult<i16> {
unimplemented!() unimplemented!()
} }
fn read_s4be(&mut self) -> io::Result<i32> { fn read_s4be(&self) -> KResult<i32> {
unimplemented!() unimplemented!()
} }
fn read_s8be(&mut self) -> io::Result<i64> { fn read_s8be(&self) -> KResult<i64> {
unimplemented!() unimplemented!()
} }
fn read_s2le(&mut self) -> io::Result<i16> { fn read_s2le(&self) -> KResult<i16> {
unimplemented!() unimplemented!()
} }
fn read_s4le(&mut self) -> io::Result<i32> { fn read_s4le(&self) -> KResult<i32> {
unimplemented!() unimplemented!()
} }
fn read_s8le(&mut self) -> io::Result<i64> { fn read_s8le(&self) -> KResult<i64> {
unimplemented!() unimplemented!()
} }
fn read_u1(&mut self) -> io::Result<u8> { fn read_u1(&self) -> KResult<u8> {
unimplemented!() unimplemented!()
} }
fn read_u2be(&mut self) -> io::Result<u16> { fn read_u2be(&self) -> KResult<u16> {
unimplemented!() unimplemented!()
} }
fn read_u4be(&mut self) -> io::Result<u32> { fn read_u4be(&self) -> KResult<u32> {
unimplemented!() unimplemented!()
} }
fn read_u8be(&mut self) -> io::Result<u64> { fn read_u8be(&self) -> KResult<u64> {
unimplemented!() unimplemented!()
} }
fn read_u2le(&mut self) -> io::Result<u16> { fn read_u2le(&self) -> KResult<u16> {
unimplemented!() unimplemented!()
} }
fn read_u4le(&mut self) -> io::Result<u32> { fn read_u4le(&self) -> KResult<u32> {
unimplemented!() unimplemented!()
} }
fn read_u8le(&mut self) -> io::Result<u64> { fn read_u8le(&self) -> KResult<u64> {
unimplemented!() unimplemented!()
} }
fn read_f4be(&mut self) -> io::Result<f32> { fn read_f4be(&self) -> KResult<f32> {
unimplemented!() unimplemented!()
} }
fn read_f8be(&mut self) -> io::Result<f64> { fn read_f8be(&self) -> KResult<f64> {
unimplemented!() unimplemented!()
} }
fn read_f4le(&mut self) -> io::Result<f32> { fn read_f4le(&self) -> KResult<f32> {
unimplemented!() unimplemented!()
} }
fn read_f8le(&mut self) -> io::Result<f64> { fn read_f8le(&self) -> KResult<f64> {
unimplemented!() unimplemented!()
} }
fn align_to_byte(&mut self) -> io::Result<()> { fn align_to_byte(&self) -> KResult<()> {
unimplemented!() unimplemented!()
} }
fn read_bits_int(&mut self, _n: u32) -> io::Result<u64> { fn read_bits_int(&self, n: u32) -> KResult<u64> {
unimplemented!() unimplemented!()
} }
fn read_bytes(&mut self, len: usize) -> KResult<&[u8]> { fn read_bytes(&self, len: usize) -> KResult<&[u8]> {
if len > self.remaining() { let cur_pos = self.state.borrow().pos;
return Err(KError::Incomplete(Needed::Size(len - self.remaining()))); if len + cur_pos > self.bytes.len() {
return Err(KError::Incomplete(Needed::Size(len + cur_pos - self.bytes.len())));
} }
let slice = &self.bytes[self.pos..self.pos + len];
self.pos += len;
Ok(slice) self.state.borrow_mut().pos += len;
Ok(&self.bytes[cur_pos..cur_pos+len])
} }
fn read_bytes_full(&mut self) -> KResult<&[u8]> { fn read_bytes_full(&self) -> KResult<&[u8]> {
if self.remaining() > 0 { unimplemented!()
self.pos = self.bytes.len();
Ok(&self.bytes[self.pos..])
} else {
Err(KError::Incomplete(Needed::Unknown))
}
} }
fn read_bytes_term( fn read_bytes_term(
&mut self, &self,
_term: char, term: char,
_include: bool, include: bool,
_consume: bool, consume: bool,
_eos_error: bool, eos_error: bool,
) -> KResult<&[u8]> { ) -> KResult<&[u8]> {
unimplemented!() unimplemented!()
} }
@ -309,7 +279,7 @@ mod tests {
#[test] #[test]
fn basic_read_bytes() { fn basic_read_bytes() {
let b = vec![1, 2, 3, 4, 5, 6, 7, 8]; let b = vec![1, 2, 3, 4, 5, 6, 7, 8];
let mut reader = BytesReader::from(b.as_slice()); let mut reader = BytesReader::new(&b[..]);
assert_eq!(reader.read_bytes(4).unwrap(), &[1, 2, 3, 4]); assert_eq!(reader.read_bytes(4).unwrap(), &[1, 2, 3, 4]);
assert_eq!(reader.read_bytes(3).unwrap(), &[5, 6, 7]); assert_eq!(reader.read_bytes(3).unwrap(), &[5, 6, 7]);

View File

@ -1,87 +1,70 @@
//! Example using hand-coded structs to validate that the borrow checker //! Example using hand-coded structs to validate that the borrow checker
//! will allow our code to actually run //! will allow our code to actually run
/* use kaitai::{BytesReader, KError, KResult, KStream, KStruct, KStructUnit};
use kaitai::{BytesReader, KError, KStream, KStructUnit, KStruct};
#[derive(Debug, PartialEq, Clone, Default)] #[derive(Debug, PartialEq, Clone, Default)]
struct TestRootStruct<'a> { struct TestRootStruct<'a> {
pub bytes: &'a [u8], pub bytes: &'a [u8],
pub child: Option<&'a TestChildStruct<'a>>, pub child: Option<TestChildStruct<'a>>,
parent: Option<&'a KStructUnit<'a>>,
root: Option<&'a TestRootStruct<'a>>,
} }
#[derive(Debug, PartialEq, Clone, Default)] #[derive(Debug, PartialEq, Clone, Default)]
struct TestChildStruct<'a> { struct TestChildStruct<'a> {
pub bytes: &'a [u8], pub bytes: &'a [u8],
parent: Option<&'a TestRootStruct<'a>>, pub root_bytes: &'a [u8],
root: Option<&'a TestRootStruct<'a>>,
} }
impl<'a> KStruct<'a> for TestRootStruct<'a> { impl<'a> KStruct<'a> for TestRootStruct<'a> {
type Parent = KStructUnit<'a>; type Parent = KStructUnit;
type Root = TestRootStruct<'a>; type Root = TestRootStruct<'a>;
fn new(_parent: Option<&'a Self::Parent>, _root: Option<&'a Self::Root>) -> Self fn read<'s: 'a, S: KStream>(
where &mut self,
Self: Sized { _io: &'s S,
TestRootStruct { _root: Option<&Self::Root>,
parent: _parent, _parent: Option<&Self::Parent>,
root: _root, ) -> KResult<'s, ()> {
..Default::default() self.bytes = _io.read_bytes(1)?;
}
}
fn read<'s: 'a, S: KStream>(&mut self, stream: &'s mut S) -> Result<(), KError<'s>> { // TODO: `new` method in KStruct?
self.bytes = stream.read_bytes(1)?; let mut child = TestChildStruct::default();
// Implementation note: because callers of `read` can't call us as
let mut child = TestChildStruct::new(Some(self), Some(self.root())); // `struct.read(_io, Some(struct), None)`, we have to use the `or`
child.read(stream)?; // call below to give an immutable copy of ourselves to the child
self.child = Some(&child); child.read(_io, _root.or(Some(self)), Some(self))?;
self.child = Some(child);
Ok(()) Ok(())
} }
fn root(&self) -> &'a Self::Root {
self.root.or(Some(self)).unwrap()
}
} }
impl<'a> KStruct<'a> for TestChildStruct<'a> { impl<'a> KStruct<'a> for TestChildStruct<'a> {
type Parent = TestRootStruct<'a>; type Parent = TestRootStruct<'a>;
type Root = TestRootStruct<'a>; type Root = TestRootStruct<'a>;
fn new(_parent: Option<&'a Self::Parent>, _root: Option<&'a Self::Root>) -> Self where fn read<'s: 'a, S: KStream>(
Self: Sized { &mut self,
TestChildStruct { _io: &'s S,
parent: _parent, _root: Option<&Self::Root>,
root: _root, _parent: Option<&Self::Parent>,
..Default::default() ) -> KResult<'s, ()> {
} self.bytes = _io.read_bytes(1).unwrap();
} _root.map(|r| self.root_bytes = r.bytes).ok_or(KError::MissingRoot)?;
fn read<'s: 'a, S: KStream>(&mut self, stream: &'s mut S) -> Result<(), KError<'s>> {
self.bytes = stream.read_bytes(1)?;
Ok(()) Ok(())
} }
fn root(&self) -> &'a Self::Root {
self.root.unwrap()
}
} }
#[test] #[test]
fn basic_parse() { fn basic_parse() {
let bytes = [1, 2]; let bytes = vec![1, 2];
let mut reader = BytesReader::from(&bytes[..]); let mut reader = BytesReader::new(&bytes);
let mut root = TestRootStruct::new(None, None); let mut root = TestRootStruct::default();
let res = root.read(&mut reader); let res = root.read(&mut reader, None, None);
assert!(res.is_ok()); assert!(res.is_ok());
assert_eq!([1], root.bytes); assert_eq!([1], root.bytes);
assert!(root.child.is_some()); assert!(root.child.is_some());
assert_eq!([2], root.child.unwrap().bytes); assert_eq!([2], root.child.unwrap().bytes);
} }
*/