diff --git a/Cargo.lock b/Cargo.lock index 8670b04..6d22eb4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,31 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "slamshuffle" version = "0.1.0" +dependencies = [ + "nom", +] diff --git a/Cargo.toml b/Cargo.toml index 564d871..0547914 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,3 +7,4 @@ license = "MIT" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +nom = "7" diff --git a/src/instruments.rs b/src/instruments.rs new file mode 100644 index 0000000..26051fb --- /dev/null +++ b/src/instruments.rs @@ -0,0 +1,58 @@ +use nom::{ + bytes::complete::tag_no_case, + character::complete::{hex_digit1, line_ending, not_line_ending, space1}, + combinator::{map_parser, map_res, opt}, + error::{Error, ErrorKind}, + multi::fold_many0, + sequence::{preceded, separated_pair, terminated}, + IResult, +}; + +#[derive(Default)] +pub struct InstrumentSet([u8; 32]); + +impl InstrumentSet { + pub fn generate(input: &str) -> Self { + match Self::parse(input) { + Ok((_, set)) => set, + Err(_) => panic!(), + } + } + + fn parse<'i>(input: &'i str) -> IResult<&'i str, Self> { + fold_many0( + terminated( + opt(preceded( + tag_no_case("#WAVE"), + map_parser(not_line_ending, wave_numbers), + )), + line_ending, + ), + Self::default, + |mut set, bytes: Option<(usize, u8)>| match bytes { + Some((slot, sample)) => { + let pos = slot - 0x20; + set.0[pos] = sample; + set + } + None => set, + }, + )(input) + } +} + +fn wave_numbers(input: &str) -> IResult<&str, (usize, u8)> { + separated_pair( + map_res(hex_digit1, |s: &str| { + s.parse::().map_err(|_| nom::error::make_error::<&str, Error<&str>>(s, ErrorKind::HexDigit)).and_then(|n| { + if (0x20..0x30).contains(&n) { + Ok(n) + } else { + Err(nom::error::make_error(s, ErrorKind::MapRes)) + } + }) + }), + space1, + map_res(hex_digit1, |s: &str| s.parse::()), + )(input) +} diff --git a/src/lib.rs b/src/lib.rs index b0011ee..db615be 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1 +1,2 @@ +pub mod instruments; pub mod mfvi;