Handle hex or decimal digits in #WAVE macro.
Now with tests!
This commit is contained in:
parent
99eb9f048f
commit
3018db7dd1
|
@ -1,14 +1,16 @@
|
|||
use nom::{
|
||||
branch::alt,
|
||||
bytes::complete::tag_no_case,
|
||||
character::complete::{hex_digit1, line_ending, not_line_ending, space1},
|
||||
combinator::{map_parser, map_res, opt},
|
||||
character::complete::{digit1, hex_digit1, line_ending, not_line_ending, space1},
|
||||
combinator::{map_parser, map_res, opt, success, value},
|
||||
error::{Error, ErrorKind},
|
||||
multi::fold_many0,
|
||||
sequence::{preceded, separated_pair, terminated},
|
||||
multi::fold_many1,
|
||||
sequence::{preceded, separated_pair, terminated, tuple},
|
||||
IResult,
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
#[cfg_attr(test, derive(Debug, PartialEq))]
|
||||
pub struct InstrumentSet([u8; 32]);
|
||||
|
||||
impl InstrumentSet {
|
||||
|
@ -20,7 +22,7 @@ impl InstrumentSet {
|
|||
}
|
||||
|
||||
fn parse<'i>(input: &'i str) -> IResult<&'i str, Self> {
|
||||
fold_many0(
|
||||
fold_many1(
|
||||
terminated(
|
||||
opt(preceded(
|
||||
tag_no_case("#WAVE "),
|
||||
|
@ -31,7 +33,7 @@ impl InstrumentSet {
|
|||
Self::default,
|
||||
|mut set, bytes: Option<(usize, u8)>| match bytes {
|
||||
Some((slot, sample)) => {
|
||||
let pos = slot - 0x20;
|
||||
let pos = (slot - 0x20) * 2;
|
||||
set.0[pos] = sample;
|
||||
set
|
||||
}
|
||||
|
@ -41,10 +43,19 @@ impl InstrumentSet {
|
|||
}
|
||||
}
|
||||
|
||||
fn hexordecimal(input: &str) -> IResult<&str, (u32, &str)> {
|
||||
alt((
|
||||
tuple((value(16, tag_no_case("0x")), hex_digit1)),
|
||||
tuple((success(10), digit1)),
|
||||
))(input)
|
||||
}
|
||||
|
||||
fn wave_numbers(input: &str) -> IResult<&str, (usize, u8)> {
|
||||
separated_pair(
|
||||
map_res(hex_digit1, |s: &str| {
|
||||
s.parse::<usize>().map_err(|_| nom::error::make_error::<&str, Error<&str>>(s, ErrorKind::HexDigit)).and_then(|n| {
|
||||
map_res(hexordecimal, |(radix, s)| {
|
||||
usize::from_str_radix(s, radix)
|
||||
.map_err(|_| nom::error::make_error::<&str, Error<&str>>(s, ErrorKind::HexDigit))
|
||||
.and_then(|n| {
|
||||
if (0x20..0x30).contains(&n) {
|
||||
Ok(n)
|
||||
} else {
|
||||
|
@ -53,6 +64,34 @@ fn wave_numbers(input: &str) -> IResult<&str, (usize, u8)> {
|
|||
})
|
||||
}),
|
||||
space1,
|
||||
map_res(hex_digit1, |s: &str| s.parse::<u8>()),
|
||||
map_res(hexordecimal, |(radix, s)| {
|
||||
u8::from_str_radix(s, radix)
|
||||
}),
|
||||
)(input)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::InstrumentSet;
|
||||
|
||||
#[test]
|
||||
fn parse_waves() {
|
||||
let input = "
|
||||
#WAVE 0x20 0xA5 flute
|
||||
#WAVE 0x21 0x95 clari
|
||||
#WAVE 0x22 0x65 strings
|
||||
#WAVE 0x23 0x63 ostrings
|
||||
#WAVE 0x24 0x34 guitar
|
||||
#WAVE 0x25 0x53 fbass
|
||||
";
|
||||
|
||||
assert_eq!(
|
||||
InstrumentSet::generate(input),
|
||||
InstrumentSet([
|
||||
0xa5, 0x00, 0x95, 0x00, 0x65, 0x00, 0x63, 0x00, 0x34, 0x00, 0x53, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue