From 1f78541f07e81e75ddc38a0f0afeeea709ea1b18 Mon Sep 17 00:00:00 2001 From: Phil <phil@grmr.de> Date: Fri, 10 Nov 2017 19:37:13 +0100 Subject: [PATCH] Add tests, reorganize and add length awareness --- README.md | 2 -- src/lib.rs | 4 +-- src/parser.rs | 56 ++++++++++++++++------------------ src/tests.rs | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 34 deletions(-) create mode 100644 src/tests.rs diff --git a/README.md b/README.md index 14f7a3f..1d00e55 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,6 @@ it and implement a decoder it. ## ToDo -- [ ] make sure we do not parse more than we are supposed to do (limit ourselves by `size`) -- [ ] port the table driven tests from go - [ ] write example cli that pretty prints the fixture's contents - [ ] create documentation/tutorial/walkthrough and give it to `nom` community - [ ] describt binary format (result of re) diff --git a/src/lib.rs b/src/lib.rs index 1e6d860..4e753dc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,11 +2,12 @@ extern crate nom; pub mod parser; +mod tests; + use std::fmt; #[derive(Debug)] pub struct Pattern { - size: u64, version: String, tempo: f32, lines: Vec<Line>, @@ -41,7 +42,6 @@ impl fmt::Display for Line { "{}{}", if i%4 == 0 { "|" } else {""}, match *x { 0 => "-", 1 => "x", _ => "?" } - ).as_str(); } diff --git a/src/parser.rs b/src/parser.rs index 9ee8556..ea613c8 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -17,18 +17,16 @@ named!(parse_line<&[u8], Line>, ) ); -named!(parse_pattern<&[u8], Pattern>, +/* + * _Assumption_: All provided data is to be interpreted + */ +named!(parse_pattern_inner<&[u8], Pattern>, do_parse!( - tag!(b"SPLICE") >> - size: be_u64 >> version: take_str!(32) >> tempo: le_f32 >> - // TODO: make sure we do not parse more than we are supposed to do - // limit ourselves by `size` lines: many0!(parse_line) >> ( Pattern{ - size: size, version: version.trim_matches('\u{0}').to_string(), tempo: tempo, lines: lines, @@ -37,30 +35,28 @@ named!(parse_pattern<&[u8], Pattern>, ) ); +named!(parse_pattern<&[u8], Pattern>, + do_parse!( + // make sure magic bytes are present + tag!(b"SPLICE") >> + // read the length field and give that many bytes to `parse_pattern_inner` + data: map!(length_data!(be_u64), parse_pattern_inner) >> + ( + match data { + // ignore all unused bytes at the end + IResult::Done(_,pattern) => pattern, + // XXX: what type of input could trigger this? + // TODO: make it not panic and handle it gracefully + // TODO: add extra testcase, that triggers this path + _ => panic!("this should never be reached") + } + ) + ) +); + +/* + * Wrapper around inner macros. + */ pub fn parse(i: &[u8]) -> IResult<&[u8], Pattern> { parse_pattern(i) } - -/* - - - - - - - */ - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_works() {} - - #[test] - fn test_fixtures() { - // TODO: implement(port) table based test - let b = include_bytes!("../fixtures/pattern_1.splice"); - - match parse_pattern(b) { - IResult::Done(_, p) => { - println!("{}", p); - panic!("yes.") - }, - _ => panic!("nope.") - } - } -} diff --git a/src/tests.rs b/src/tests.rs new file mode 100644 index 0000000..50b3057 --- /dev/null +++ b/src/tests.rs @@ -0,0 +1,83 @@ +#[test] +fn gochallenge_tests() { + use parser::parse; + use nom::IResult; + + use std::io::prelude::*; + use std::fs::File; + + let table: Vec<(&str, &str)> = vec![ + ( + "fixtures/pattern_1.splice", + "Saved with HW Version: 0.808-alpha +Tempo: 120 +(0) kick |x---|x---|x---|x---| +(1) snare |----|x---|----|x---| +(2) clap |----|x-x-|----|----| +(3) hh-open |--x-|--x-|x-x-|--x-| +(4) hh-close |x---|x---|----|x--x| +(5) cowbell |----|----|--x-|----| +" + ), + ( + "fixtures/pattern_2.splice", + "Saved with HW Version: 0.808-alpha +Tempo: 98.4 +(0) kick |x---|----|x---|----| +(1) snare |----|x---|----|x---| +(3) hh-open |--x-|--x-|x-x-|--x-| +(5) cowbell |----|----|x---|----| +" + ), + ( + "fixtures/pattern_3.splice", + "Saved with HW Version: 0.808-alpha +Tempo: 118 +(40) kick |x---|----|x---|----| +(1) clap |----|x---|----|x---| +(3) hh-open |--x-|--x-|x-x-|--x-| +(5) low-tom |----|---x|----|----| +(12) mid-tom |----|----|x---|----| +(9) hi-tom |----|----|-x--|----| +", + ), + ( + "fixtures/pattern_4.splice", + "Saved with HW Version: 0.909 +Tempo: 240 +(0) SubKick |----|----|----|----| +(1) Kick |x---|----|x---|----| +(99) Maracas |x-x-|x-x-|x-x-|x-x-| +(255) Low Conga |----|x---|----|x---| +", + ), + ( + "fixtures/pattern_5.splice", + "Saved with HW Version: 0.708-alpha +Tempo: 999 +(1) Kick |x---|----|x---|----| +(2) HiHat |x-x-|x-x-|x-x-|x-x-| +", + ), + ]; + + for r in table.iter() { + println!("expected of {}:\n{}", r.0, r.1); + + let mut buf: Vec<u8> = vec![]; + let mut file = File::open(r.0).expect("file exists"); + let _ = file.read_to_end(&mut buf).expect("file can be read"); + + match parse(&buf[..]) { + IResult::Done(_, pattern) => { + println!("Parsing is done."); + assert_eq!(r.1, format!("{}", pattern)); + } + e => { + panic!("something went wrong. {:?}", e); + } + } + + println!("--------------"); + } +} -- GitLab