commit bfeb073143205de4bb54fe7c4b541aa998f3da95 Author: Bradlee Speice Date: Tue Apr 16 14:53:53 2019 -0400 Initial draft for the Kaitai API diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..61daf13 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.idea/ + +/target +**/*.rs.bk +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..b357c80 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "kaitai_runtime" +version = "0.1.0" +authors = ["Bradlee Speice "] +edition = "2018" + +[dependencies] diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..b9ba1e8 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,262 @@ +use std::io; +use std::io::Read; +use std::io::Seek; + +#[derive(Debug)] +pub enum KaitaiError<'a> { + InvalidContents { actual: &'a [u8] }, + InvalidKey, + IoError(io::Error), +} + +impl<'a> From for KaitaiError<'a> { + fn from(e: io::Error) -> Self { + KaitaiError::IoError(e) + } +} + +type Result<'a, T> = std::result::Result>; + +pub trait KaitaiStruct<'a> +{ + type Parent: KaitaiStruct<'a>; + type Root: KaitaiStruct<'a>; + + fn new(stream: &mut S) -> Result + where + Self: Sized; + + /* + fn read>( + &mut self, + + ) + */ +} + +pub trait KaitaiStream { + fn is_eof(&self) -> io::Result; + fn seek(&mut self, position: u64) -> io::Result<()>; + fn pos(&self) -> io::Result; + fn size(&self) -> io::Result; + + fn read_s1(&mut self) -> io::Result; + fn read_s2be(&mut self) -> io::Result; + fn read_s4be(&mut self) -> io::Result; + fn read_s8be(&mut self) -> io::Result; + fn read_s2le(&mut self) -> io::Result; + fn read_s4le(&mut self) -> io::Result; + fn read_s8le(&mut self) -> io::Result; + + fn read_u1(&mut self) -> io::Result; + fn read_u2be(&mut self) -> io::Result; + fn read_u4be(&mut self) -> io::Result; + fn read_u8be(&mut self) -> io::Result; + fn read_u2le(&mut self) -> io::Result; + fn read_u4le(&mut self) -> io::Result; + fn read_u8le(&mut self) -> io::Result; + + fn read_f4be(&mut self) -> io::Result; + fn read_f8be(&mut self) -> io::Result; + fn read_f4le(&mut self) -> io::Result; + fn read_f8le(&mut self) -> io::Result; + + fn align_to_byte(&mut self) -> io::Result<()>; + fn read_bits_int(&mut self, n: u32) -> io::Result; + + fn read_bytes(&mut self, dst: &mut [u8], len: usize) -> io::Result<&[u8]>; + fn read_bytes_full(&mut self) -> io::Result<&[u8]>; + fn read_bytes_term( + &mut self, + term: char, + include: bool, + consume: bool, + eos_error: bool, + ) -> io::Result<&[u8]>; + + /// Verify a magic sequence occurs in the file. Because the size is known at compile-time + /// (and is generally very small), we ask that our caller pass in a buffer for us. + fn ensure_fixed_contents(&mut self, expected: &[u8], buf: &mut [u8]) -> Result<&[u8]> { + let actual = self.read_bytes(buf, expected.len())?; + if actual == expected { + Ok(actual) + } else { + // Return what the actual contents were; our caller provided us + // what was expected so we don't need to return it, and it makes + // the lifetimes way easier + Err(KaitaiError::InvalidContents { actual }) + } + } + + /// Return a byte array that is sized to exclude all trailing instances of the + /// padding character. Because this operation is immutable on the underlying byte slice, + /// we don't allocate a second buffer. + fn bytes_strip_right(bytes: &[u8], pad: u8) -> &[u8] { + let mut new_len = bytes.len(); + while new_len > 0 && bytes[new_len - 1] == pad { + new_len -= 1; + } + &bytes[..new_len] + } + + /// Return a byte array that contains all bytes up until the + /// termination byte. Can optionally include the termination byte as well. + /// Because this operation is immutable on the underlying byte slice, + /// we don't allocate a second buffer. + fn bytes_terminate(bytes: &[u8], term: u8, include_term: bool) -> &[u8] { + let mut new_len = 0; + while bytes[new_len] != term && new_len < bytes.len() { + new_len += 1; + } + + if include_term && new_len < bytes.len() { + new_len += 1; + } + + &bytes[..new_len] + } +} + +struct BytesReader<'a> { + bytes: &'a[u8], + pos: usize, + bits: u8, + bits_left: u8, +} +impl<'a> BytesReader<'a> { + fn new(bytes: &'a[u8]) -> Self { + BytesReader { + bytes, + pos: 0, + bits: 0, + bits_left: 0 + } + } +} +impl<'a> From<&'a[u8]> for BytesReader<'a> { + fn from(b: &'a[u8]) -> Self { + BytesReader::new(b) + } +} +impl<'a> KaitaiStream for BytesReader<'a> { + fn is_eof(&self) -> io::Result { + unimplemented!() + } + + fn seek(&mut self, position: u64) -> io::Result<()> { + unimplemented!() + } + + fn pos(&self) -> io::Result { + unimplemented!() + } + + fn size(&self) -> io::Result { + unimplemented!() + } + + fn read_s1(&mut self) -> io::Result { + unimplemented!() + } + + fn read_s2be(&mut self) -> io::Result { + unimplemented!() + } + + fn read_s4be(&mut self) -> io::Result { + unimplemented!() + } + + fn read_s8be(&mut self) -> io::Result { + unimplemented!() + } + + fn read_s2le(&mut self) -> io::Result { + unimplemented!() + } + + fn read_s4le(&mut self) -> io::Result { + unimplemented!() + } + + fn read_s8le(&mut self) -> io::Result { + unimplemented!() + } + + fn read_u1(&mut self) -> io::Result { + unimplemented!() + } + + fn read_u2be(&mut self) -> io::Result { + unimplemented!() + } + + fn read_u4be(&mut self) -> io::Result { + unimplemented!() + } + + fn read_u8be(&mut self) -> io::Result { + unimplemented!() + } + + fn read_u2le(&mut self) -> io::Result { + unimplemented!() + } + + fn read_u4le(&mut self) -> io::Result { + unimplemented!() + } + + fn read_u8le(&mut self) -> io::Result { + unimplemented!() + } + + fn read_f4be(&mut self) -> io::Result { + unimplemented!() + } + + fn read_f8be(&mut self) -> io::Result { + unimplemented!() + } + + fn read_f4le(&mut self) -> io::Result { + unimplemented!() + } + + fn read_f8le(&mut self) -> io::Result { + unimplemented!() + } + + fn align_to_byte(&mut self) -> io::Result<()> { + unimplemented!() + } + + fn read_bits_int(&mut self, n: u32) -> io::Result { + unimplemented!() + } + + fn read_bytes(&mut self, buf: &mut [u8], len: usize) -> io::Result<&[u8]> { + unimplemented!() + } + + fn read_bytes_full(&mut self) -> io::Result<&[u8]> { + unimplemented!() + } + + fn read_bytes_term(&mut self, term: char, include: bool, consume: bool, eos_error: bool) -> io::Result<&[u8]> { + unimplemented!() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn basic_strip_right() { + let b = [1, 2, 3, 4, 5, 5, 5, 5]; + let c = BytesReader::bytes_strip_right(&b, 5); + + assert_eq!([1, 2, 3, 4], c); + } +} \ No newline at end of file