From 1b1fca8138485920590d04b04ba699e78a418934 Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Wed, 25 Nov 2020 14:14:45 +0100 Subject: Refactor parsing of ARCH chunks and add docs. --- src/main.rs | 54 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/src/main.rs b/src/main.rs index 52a8d3f..7546df8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,6 +16,7 @@ */ use nom::{ + branch::alt, bytes::complete::*, multi::{count, length_data, many0}, number::complete::*, @@ -101,7 +102,6 @@ fn bytevec<'a>(data: &'a[u8]) -> IResult<&'a [u8], &'a [u8]> { /// Version information about the app that created the file. #[derive(Debug)] struct PAppVersion<'a> { - num1: u32, appname: &'a str, appversion: &'a str, appdate: &'a str, @@ -113,11 +113,10 @@ struct PAppVersion<'a> { } fn p_appversion<'a>(data: &'a [u8]) -> IResult<&'a [u8], PAppVersion<'a>> { - let (r, (num1, appname, appversion, appdate, num2, apparch, num3, appencoding, applocale)) = - tuple((be_u32, cmstring, cmstring, cmstring, be_u32, cmstring, be_u32, cmstring, cmstring))(&data)?; + let (r, (appname, appversion, appdate, num2, apparch, num3, appencoding, applocale)) = + tuple((cmstring, cmstring, cmstring, be_u32, cmstring, be_u32, cmstring, cmstring))(&data)?; Ok((r, PAppVersion { - num1, appname, appversion, appdate, @@ -271,20 +270,35 @@ fn root_chunk<'a>(data: &'a [u8]) -> IResult<&'a [u8], ()> { Ok((rest, ())) } -fn arch_chunk<'a>(data: &'a [u8]) -> IResult<&'a [u8], ()> { - let (rest, (nt, t, x)) = tuple((nodetype, cmstring, be_u16))(data)?; - println!(" {:?}: {}, {}", nt, t, x); - match nt { - NodeType::Container => { - arch_chunk(rest)?; - }, - NodeType::Leaf => { - let (_, nodeval) = node_value(t, rest)?; - println!(" {:?}", nodeval); - } - }; +/** + * A container node does not contain any data of it's own, but contains + * one or more sub elements. These can be either other containers, or + * object/leaf nodes. + */ +fn container_node<'a>(data: &'a [u8]) -> IResult<&'a [u8], ()> { + let (r, (_, name, num)) = tuple((tag(b"\xff\xff\xff\xfe"), cmstring, be_u16))(data)?; + println!(" Container: {}, {}", name, num); + Ok((r, ())) +} + +/** + * An object node contains serialized structured data. + * + * It has a size, as well as a payload containing the actual serialized data. + */ +fn object_node<'a>(data: &'a [u8]) -> IResult<&'a [u8], ()> { + let (r, (_, name, num, payload)) = tuple((tag(b"\xff\xff\xff\xff"), cmstring, be_u16, length_data(be_u32)))(data)?; + println!(" Object: {}, {}, {}", name, num, payload.len()); + Ok((r, ())) +} +/** + * ARCH chunks contains one or more structured data elements that can be + * either container nodes or object/leaf nodes.. + */ +fn arch_chunk<'a>(data: &'a [u8]) -> IResult<&'a [u8], ()> { + let (rest, _nodes) = many0(alt((container_node, object_node)))(data)?; Ok((rest, ())) } @@ -302,6 +316,14 @@ fn chunk<'a>(data: &'a [u8]) -> IResult<&'a [u8], ()> { Ok((rest, ())) } +/** + * Parse the Cubase project file header. + * + * A Cubase project file is almost a standard RIFF file, with the exception of an + * extra fourcc (NUND) following the global RIFF header. The extra (NUND) fourcc + * is _not_ followed by the length of the chunk, but rather immediately followed by + * the next chunk. + */ fn file_hdr<'a>(data: &'a [u8]) -> IResult<&'a [u8], ()> { let (rest, (_, len, _)) = tuple((tag("RIFF"), be_u32, tag("NUND")))(data)?; println!("RIFF: {}, NUND", len); -- cgit v1.2.3