diff options
-rw-r--r-- | src/main.rs | 43 |
1 files changed, 24 insertions, 19 deletions
diff --git a/src/main.rs b/src/main.rs index 414f1c0..5a3bf36 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,7 +26,6 @@ use nom::{ number::complete::*, sequence::tuple, Finish, - InputTake, IResult, }; use std::{ @@ -263,10 +262,14 @@ fn fourcc<'a>(data: &'a [u8]) -> IResult<&'a [u8], &'a str> { Ok((rest, std::str::from_utf8(tag).unwrap())) } -fn root_chunk<'a>(data: &'a [u8]) -> IResult<&'a [u8], ()> { - let (rest, (key, val)) = tuple((cmstring, cmstring))(data)?; - println!(" {}: {}", key, val); - Ok((rest, ())) +/** + * Root chunks allways have the same layout, two length prefixed strings. + * + * These seem to be a mapping between a field name, and the data type the field contains. + * The actual data follows in the ARCH chunk following this ROOT chunk. + */ +fn root_chunk<'a>(data: &'a [u8]) -> IResult<&'a [u8], (&str, &str)> { + tuple((cmstring, cmstring))(data) } @@ -304,20 +307,6 @@ fn arch_chunk<'a>(data: &'a [u8]) -> IResult<&'a [u8], ()> { Ok((rest, ())) } -fn chunk<'a>(data: &'a [u8]) -> IResult<&'a [u8], ()> { - let (rest, (tag, payload)) = tuple((fourcc, length_data(be_u32)))(data)?; - - println!(" {}: {}", tag, payload.len()); - - match tag { - "ROOT" => root_chunk(payload)?, - "ARCH" => arch_chunk(payload)?, - &_ => (payload, ()) - }; - - Ok((rest, ())) -} - struct RiffChunk<'a> { fourcc: &'a str, payload: &'a [u8], @@ -383,6 +372,22 @@ where for chunk in chunks { println!("{}: {}", chunk.fourcc, chunk.payload.len()); + + match chunk.fourcc { + "ROOT" => { + let (r, (k, v)) = root_chunk(chunk.payload).finish().map_err(|e| format!("{:?}", e))?; + assert_eq!(r.len(), 0); + println!(" {}: {}", k, v); + }, + "ARCH" => { + arch_chunk(chunk.payload).finish().map_err(|e| format!("{:?}", e))?; + }, + _ => { + eprintln!("[-] Warning: ignoring unknown chunk \"{}\" of length {} bytes.", + chunk.fourcc, + chunk.payload.len()); + } + }; } Ok(proj) |