diff --git a/Cargo.toml b/Cargo.toml index 433e343..5c9009e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ clap = { version = "4.5", features = ["derive"] } derived-deref = "2.1.0" fasteval = "0.2.4" nom = "7.1.3" -serde = "1.0.209" +serde = { version = "1.0.209", features = ["derive"] } serde_yml = "0.0.12" splines = "4.3.1" strum = { version = "0.26", features = ["derive"] } @@ -19,6 +19,8 @@ strum_macros = "0.26" tinyaudio = { version = "0.1", optional = true } bng_macros = { path = "bng_macros" } const_format = "0.2.33" +thiserror = "1.0.64" +derive-new = "0.7.0" [features] default = ["play", "save"] diff --git a/src/bng.rs b/src/bng.rs index 6c2693a..df8b4cd 100644 --- a/src/bng.rs +++ b/src/bng.rs @@ -1,2 +1,26 @@ +use derive_new::new; +use derived_deref::Deref; +use fasteval::Instruction; +use instrument::Instrument; +use serde::Serialize; + mod instrument; mod score; + +#[derive(new, Debug, PartialEq)] +pub struct InstructionWrapper(Instruction); + +impl Serialize for InstructionWrapper { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let expr_str = String::new(); + serializer.serialize_str(&format!("{:#?}", self.0)) + } +} + +#[derive(Serialize)] +struct BngFile { + instruments: Vec, +} diff --git a/src/bng/instrument.rs b/src/bng/instrument.rs index b8db277..a060371 100644 --- a/src/bng/instrument.rs +++ b/src/bng/instrument.rs @@ -1,5 +1,7 @@ use derived_deref::Deref; -use fasteval::Instruction; +use serde::Serialize; -#[derive(Deref)] +use super::InstructionWrapper as Instruction; + +#[derive(Serialize, Deref)] pub struct Instrument(Instruction); diff --git a/src/bng/score.rs b/src/bng/score.rs index 57a47d1..1f1ec70 100644 --- a/src/bng/score.rs +++ b/src/bng/score.rs @@ -2,12 +2,13 @@ use std::num::{NonZeroU16, NonZeroU8}; use anyhow::Context; use bng_macros::{QuickModifierParser, SlopeModifierParser}; -use fasteval::Instruction; use strum::EnumDiscriminants; mod lex; mod utils; +use super::InstructionWrapper as Instruction; + #[cfg_attr(debug_assertions, derive(Debug, PartialEq))] pub(super) enum Atom { Note(u8), diff --git a/src/bng/score/lex/lexer.rs b/src/bng/score/lex/lexer.rs index 5846f75..19df019 100644 --- a/src/bng/score/lex/lexer.rs +++ b/src/bng/score/lex/lexer.rs @@ -4,7 +4,7 @@ use std::{ }; use clap::builder::TypedValueParser; -use fasteval::{Compiler, Instruction}; +use fasteval::Compiler; use nom::{ branch::alt, bytes::complete::{take_till, take_till1}, @@ -15,7 +15,10 @@ use nom::{ Err, IResult, Parser, }; -use crate::bng::score::{Atom, FlatAtom, Modifier, QuickModifier, SlopeModifier}; +use super::{ + super::super::InstructionWrapper as Instruction, + {Atom, FlatAtom, Modifier, QuickModifier, SlopeModifier}, +}; #[cfg(test)] mod tests; @@ -65,7 +68,7 @@ fn flat_atom_parser(notes: &str) -> impl Parser<&str, FlatAtom, nom::error::Erro map_res(take_till1(|c| c == ','), |s| { let parser = fasteval::Parser::new(); let mut slab = fasteval::Slab::new(); - Result::>::Ok( + Result::>::Ok(Instruction::new( parser .parse(s, &mut slab.ps) .map_err(|_| { @@ -73,7 +76,7 @@ fn flat_atom_parser(notes: &str) -> impl Parser<&str, FlatAtom, nom::error::Erro })? .from(&slab.ps) .compile(&slab.ps, &mut slab.cs), - ) + )) }), ), ), diff --git a/src/bng/score/lex/lexer/tests.rs b/src/bng/score/lex/lexer/tests.rs index f37a4fa..9c91afb 100644 --- a/src/bng/score/lex/lexer/tests.rs +++ b/src/bng/score/lex/lexer/tests.rs @@ -14,11 +14,11 @@ mod flat_atom { use fasteval::Compiler; use nom::Parser; - use super::*; - use crate::bng::score::{ - lex::{lexer::flat_atom_parser, UP}, - Atom, FlatAtom, Modifier, QuickModifier, SlopeModifier, + use super::super::{ + super::super::super::InstructionWrapper as Instruction, super::UP, flat_atom_parser, Atom, + FlatAtom, Modifier, QuickModifier, SlopeModifier, }; + use super::*; pub(super) const SAMPLE_STR: &str = concatcp!( Atom::TUPLE.0, @@ -139,11 +139,13 @@ mod flat_atom { FlatAtom::SlopeStarts(SlopeModifier::Note, { let parser = fasteval::Parser::new(); let mut slab = fasteval::Slab::new(); - parser - .parse(FASTEVAL_INSTRUCTION, &mut slab.ps) - .unwrap() - .from(&slab.ps) - .compile(&slab.ps, &mut slab.cs) + Instruction::new( + parser + .parse(FASTEVAL_INSTRUCTION, &mut slab.ps) + .unwrap() + .from(&slab.ps) + .compile(&slab.ps, &mut slab.cs), + ) }) )), flat_atom_parser("abcdefg").parse(concatcp!( diff --git a/src/bng/score/utils.rs b/src/bng/score/utils.rs index 347d51f..2177b12 100644 --- a/src/bng/score/utils.rs +++ b/src/bng/score/utils.rs @@ -1,22 +1,32 @@ use super::*; +use strum::Display; +use thiserror::Error; #[cfg(test)] mod tests; -// TODO: replace panics with custom error type -fn inflate(mut flat_atoms: Vec) -> Vec { - #[derive(EnumDiscriminants)] - #[cfg_attr(debug_assertions, derive(Debug))] - enum CurrentStack { - Loop(NonZeroU8), - Tuple, - Slope(SlopeModifier, Instruction), - } +#[derive(Debug, EnumDiscriminants)] +#[strum_discriminants(derive(Display))] +enum Wrapper { + Loop(NonZeroU8), + Tuple, + Slope(SlopeModifier, Instruction), +} + +#[derive(Debug, Error)] +#[cfg_attr(test, derive(PartialEq))] +enum InflateError { + #[error("misplaced {0} end symbol")] + MismatchedEnd(WrapperDiscriminants), +} + +fn inflate(mut flat_atoms: Vec) -> Result, InflateError> { + type Error = InflateError; let mut result = Vec::with_capacity(flat_atoms.len()); let mut loop_stack: Vec> = Vec::new(); let mut tuple_stack: Vec> = Vec::new(); let mut slope_stack: Vec> = Vec::new(); - let mut stack_history: Vec = Vec::new(); + let mut stack_history: Vec = Vec::new(); for mut atom in flat_atoms.into_iter() { #[cfg(test)] { @@ -26,159 +36,172 @@ fn inflate(mut flat_atoms: Vec) -> Vec { dbg!(&slope_stack); dbg!(&stack_history); } - if let Some(stack) = stack_history.last() { - match CurrentStackDiscriminants::from(stack) { - CurrentStackDiscriminants::Loop => match atom { - FlatAtom::Note(n) => loop_stack.last_mut().unwrap().push(Atom::Note(n)), - FlatAtom::Rest => loop_stack.last_mut().unwrap().push(Atom::Rest), - FlatAtom::StartHere => loop_stack.last_mut().unwrap().push(Atom::StartHere), - FlatAtom::Modifier(m) => loop_stack.last_mut().unwrap().push(Atom::Modifier(m)), - FlatAtom::QuickModifier(q) => { - loop_stack.last_mut().unwrap().push(Atom::QuickModifier(q)) - } - FlatAtom::LoopStarts(n) => { - loop_stack.push(Vec::new()); - stack_history.push(CurrentStack::Loop(n)); - } - FlatAtom::LoopEnds => { - let popped = loop_stack.pop().unwrap(); - if stack_history.len() > 1 { - match CurrentStackDiscriminants::from( - stack_history.get(stack_history.len() - 2).unwrap(), - ) { - CurrentStackDiscriminants::Loop => &mut loop_stack, - CurrentStackDiscriminants::Tuple => &mut tuple_stack, - CurrentStackDiscriminants::Slope => &mut slope_stack, - } - .last_mut() - .unwrap() - .push(Atom::Loop( - match stack_history.pop().unwrap() { - CurrentStack::Loop(n) => n, - _ => unreachable!("this one is proven to be a loop"), - }, - popped, - )) - } else { - result.push(Atom::Loop( - match stack_history.pop().unwrap() { - CurrentStack::Loop(n) => n, - _ => unreachable!("this one is proven to be a loop"), - }, - popped, - )) + match stack_history.last().map(WrapperDiscriminants::from) { + Some(WrapperDiscriminants::Loop) => match atom { + FlatAtom::Note(n) => { + unsafe { loop_stack.last_mut().unwrap_unchecked() }.push(Atom::Note(n)) + } + FlatAtom::Rest => { + unsafe { loop_stack.last_mut().unwrap_unchecked() }.push(Atom::Rest) + } + FlatAtom::StartHere => { + unsafe { loop_stack.last_mut().unwrap_unchecked() }.push(Atom::StartHere) + } + FlatAtom::Modifier(m) => { + unsafe { loop_stack.last_mut().unwrap_unchecked() }.push(Atom::Modifier(m)) + } + FlatAtom::QuickModifier(q) => { + unsafe { loop_stack.last_mut().unwrap_unchecked() }.push(Atom::QuickModifier(q)) + } + FlatAtom::LoopStarts(n) => { + loop_stack.push(Vec::new()); + stack_history.push(Wrapper::Loop(n)); + } + FlatAtom::LoopEnds => { + let popped = unsafe { loop_stack.pop().unwrap_unchecked() }; + if stack_history.len() > 1 { + match WrapperDiscriminants::from( + stack_history.get(stack_history.len() - 2).unwrap(), + ) { + WrapperDiscriminants::Loop => &mut loop_stack, + WrapperDiscriminants::Tuple => &mut tuple_stack, + WrapperDiscriminants::Slope => &mut slope_stack, } + .last_mut() + .unwrap() + .push(Atom::Loop( + match stack_history.pop().unwrap() { + Wrapper::Loop(n) => n, + _ => unreachable!("this one is proven to be a loop"), + }, + popped, + )) + } else { + result.push(Atom::Loop( + match stack_history.pop().unwrap() { + Wrapper::Loop(n) => n, + _ => unreachable!("this one is proven to be a loop"), + }, + popped, + )) } - FlatAtom::TupleStarts => { - tuple_stack.push(Vec::new()); - stack_history.push(CurrentStack::Tuple); - } - FlatAtom::TupleEnds => panic!("unmatched end tuple in a loop"), - FlatAtom::SlopeStarts(s, i) => { - slope_stack.push(Vec::new()); - stack_history.push(CurrentStack::Slope(s, i)); - } - FlatAtom::SlopeEnds => panic!("unmatched end slope in a loop"), - FlatAtom::Comment => loop_stack.last_mut().unwrap().push(Atom::Comment), - }, - CurrentStackDiscriminants::Tuple => match atom { - FlatAtom::Note(n) => tuple_stack.last_mut().unwrap().push(Atom::Note(n)), - FlatAtom::Rest => tuple_stack.last_mut().unwrap().push(Atom::Rest), - FlatAtom::StartHere => tuple_stack.last_mut().unwrap().push(Atom::StartHere), - FlatAtom::Modifier(m) => { - tuple_stack.last_mut().unwrap().push(Atom::Modifier(m)) - } - FlatAtom::QuickModifier(q) => { - tuple_stack.last_mut().unwrap().push(Atom::QuickModifier(q)) - } - FlatAtom::LoopStarts(n) => { - loop_stack.push(Vec::new()); - stack_history.push(CurrentStack::Loop(n)); - } - FlatAtom::LoopEnds => panic!("unmatched end loop in a tuple"), - FlatAtom::TupleStarts => { - tuple_stack.push(Vec::new()); - stack_history.push(CurrentStack::Tuple); - } - FlatAtom::TupleEnds => { - let popped = tuple_stack.pop().unwrap(); - if stack_history.len() > 1 { - match CurrentStackDiscriminants::from( - stack_history.get(stack_history.len() - 2).unwrap(), - ) { - CurrentStackDiscriminants::Loop => &mut loop_stack, - CurrentStackDiscriminants::Tuple => &mut tuple_stack, - CurrentStackDiscriminants::Slope => &mut slope_stack, - } - .last_mut() - .unwrap() - .push({ - stack_history.pop(); - Atom::Tuple(popped) - }) - } else { - result.push(Atom::Tuple(popped)) + } + FlatAtom::TupleStarts => { + tuple_stack.push(Vec::new()); + stack_history.push(Wrapper::Tuple); + } + FlatAtom::TupleEnds => { + return Err(Error::MismatchedEnd(WrapperDiscriminants::Tuple)); + } + FlatAtom::SlopeStarts(s, i) => { + slope_stack.push(Vec::new()); + stack_history.push(Wrapper::Slope(s, i)); + } + FlatAtom::SlopeEnds => { + return Err(Error::MismatchedEnd(WrapperDiscriminants::Slope)); + } + FlatAtom::Comment => loop_stack.last_mut().unwrap().push(Atom::Comment), + }, + Some(WrapperDiscriminants::Tuple) => match atom { + FlatAtom::Note(n) => tuple_stack.last_mut().unwrap().push(Atom::Note(n)), + FlatAtom::Rest => tuple_stack.last_mut().unwrap().push(Atom::Rest), + FlatAtom::StartHere => tuple_stack.last_mut().unwrap().push(Atom::StartHere), + FlatAtom::Modifier(m) => tuple_stack.last_mut().unwrap().push(Atom::Modifier(m)), + FlatAtom::QuickModifier(q) => { + tuple_stack.last_mut().unwrap().push(Atom::QuickModifier(q)) + } + FlatAtom::LoopStarts(n) => { + loop_stack.push(Vec::new()); + stack_history.push(Wrapper::Loop(n)); + } + FlatAtom::LoopEnds => { + return Err(Error::MismatchedEnd(WrapperDiscriminants::Loop)); + } + FlatAtom::TupleStarts => { + tuple_stack.push(Vec::new()); + stack_history.push(Wrapper::Tuple); + } + FlatAtom::TupleEnds => { + let popped = tuple_stack.pop().unwrap(); + if stack_history.len() > 1 { + match WrapperDiscriminants::from( + stack_history.get(stack_history.len() - 2).unwrap(), + ) { + WrapperDiscriminants::Loop => &mut loop_stack, + WrapperDiscriminants::Tuple => &mut tuple_stack, + WrapperDiscriminants::Slope => &mut slope_stack, } + .last_mut() + .unwrap() + .push({ + stack_history.pop(); + Atom::Tuple(popped) + }) + } else { + result.push(Atom::Tuple(popped)) } - FlatAtom::SlopeStarts(s, i) => { - slope_stack.push(Vec::new()); - stack_history.push(CurrentStack::Slope(s, i)); - } - FlatAtom::SlopeEnds => panic!("unmatched end slope in a tuple"), - FlatAtom::Comment => tuple_stack.last_mut().unwrap().push(Atom::Comment), - }, - CurrentStackDiscriminants::Slope => match atom { - FlatAtom::Note(n) => slope_stack.last_mut().unwrap().push(Atom::Note(n)), - FlatAtom::Rest => slope_stack.last_mut().unwrap().push(Atom::Rest), - FlatAtom::StartHere => slope_stack.last_mut().unwrap().push(Atom::StartHere), - FlatAtom::Modifier(m) => { - slope_stack.last_mut().unwrap().push(Atom::Modifier(m)) - } - FlatAtom::QuickModifier(q) => { - slope_stack.last_mut().unwrap().push(Atom::QuickModifier(q)) - } - FlatAtom::LoopStarts(n) => { - loop_stack.push(Vec::new()); - stack_history.push(CurrentStack::Loop(n)); - } - FlatAtom::LoopEnds => panic!("unmatched end loop"), - FlatAtom::TupleStarts => { - tuple_stack.push(Vec::new()); - stack_history.push(CurrentStack::Tuple); - } - FlatAtom::TupleEnds => panic!("unmatched end tuple"), - FlatAtom::SlopeStarts(s, i) => { - slope_stack.push(Vec::new()); - stack_history.push(CurrentStack::Slope(s, i)); - } - FlatAtom::SlopeEnds => { - let popped = slope_stack.pop().unwrap(); - if stack_history.len() > 1 { - match CurrentStackDiscriminants::from( - stack_history.get(stack_history.len() - 2).unwrap(), - ) { - CurrentStackDiscriminants::Loop => &mut loop_stack, - CurrentStackDiscriminants::Tuple => &mut tuple_stack, - CurrentStackDiscriminants::Slope => &mut slope_stack, - } - .last_mut() - .unwrap() - .push(match stack_history.pop().unwrap() { - CurrentStack::Slope(m, i) => Atom::Slope(m, i, popped), - _ => unreachable!("this one is proven to be a slope"), - }) - } else { - result.push(match stack_history.pop().unwrap() { - CurrentStack::Slope(m, i) => Atom::Slope(m, i, popped), - _ => unreachable!("this one is proven to be a slope"), - }) + } + FlatAtom::SlopeStarts(s, i) => { + slope_stack.push(Vec::new()); + stack_history.push(Wrapper::Slope(s, i)); + } + FlatAtom::SlopeEnds => { + return Err(Error::MismatchedEnd(WrapperDiscriminants::Slope)); + } + FlatAtom::Comment => tuple_stack.last_mut().unwrap().push(Atom::Comment), + }, + Some(WrapperDiscriminants::Slope) => match atom { + FlatAtom::Note(n) => slope_stack.last_mut().unwrap().push(Atom::Note(n)), + FlatAtom::Rest => slope_stack.last_mut().unwrap().push(Atom::Rest), + FlatAtom::StartHere => slope_stack.last_mut().unwrap().push(Atom::StartHere), + FlatAtom::Modifier(m) => slope_stack.last_mut().unwrap().push(Atom::Modifier(m)), + FlatAtom::QuickModifier(q) => { + slope_stack.last_mut().unwrap().push(Atom::QuickModifier(q)) + } + FlatAtom::LoopStarts(n) => { + loop_stack.push(Vec::new()); + stack_history.push(Wrapper::Loop(n)); + } + FlatAtom::LoopEnds => { + return Err(Error::MismatchedEnd(WrapperDiscriminants::Loop)); + } + FlatAtom::TupleStarts => { + tuple_stack.push(Vec::new()); + stack_history.push(Wrapper::Tuple); + } + FlatAtom::TupleEnds => { + return Err(Error::MismatchedEnd(WrapperDiscriminants::Tuple)); + } + FlatAtom::SlopeStarts(s, i) => { + slope_stack.push(Vec::new()); + stack_history.push(Wrapper::Slope(s, i)); + } + FlatAtom::SlopeEnds => { + let popped = slope_stack.pop().unwrap(); + if stack_history.len() > 1 { + match WrapperDiscriminants::from( + stack_history.get(stack_history.len() - 2).unwrap(), + ) { + WrapperDiscriminants::Loop => &mut loop_stack, + WrapperDiscriminants::Tuple => &mut tuple_stack, + WrapperDiscriminants::Slope => &mut slope_stack, } + .last_mut() + .unwrap() + .push(match stack_history.pop().unwrap() { + Wrapper::Slope(m, i) => Atom::Slope(m, i, popped), + _ => unreachable!("this one is proven to be a slope"), + }) + } else { + result.push(match stack_history.pop().unwrap() { + Wrapper::Slope(m, i) => Atom::Slope(m, i, popped), + _ => unreachable!("this one is proven to be a slope"), + }) } - FlatAtom::Comment => slope_stack.last_mut().unwrap().push(Atom::Comment), - }, - } - } else { - match atom { + } + FlatAtom::Comment => slope_stack.last_mut().unwrap().push(Atom::Comment), + }, + None => match atom { FlatAtom::Note(n) => result.push(Atom::Note(n)), FlatAtom::Rest => result.push(Atom::Rest), FlatAtom::StartHere => result.push(Atom::StartHere), @@ -186,22 +209,28 @@ fn inflate(mut flat_atoms: Vec) -> Vec { FlatAtom::QuickModifier(q) => result.push(Atom::QuickModifier(q)), FlatAtom::LoopStarts(n) => { loop_stack.push(Vec::new()); - stack_history.push(CurrentStack::Loop(n)); + stack_history.push(Wrapper::Loop(n)); + } + FlatAtom::LoopEnds => { + return Err(Error::MismatchedEnd(WrapperDiscriminants::Loop)); } - FlatAtom::LoopEnds => panic!("unmatched end loop"), FlatAtom::TupleStarts => { tuple_stack.push(Vec::new()); - stack_history.push(CurrentStack::Tuple); + stack_history.push(Wrapper::Tuple); + } + FlatAtom::TupleEnds => { + return Err(Error::MismatchedEnd(WrapperDiscriminants::Tuple)); } - FlatAtom::TupleEnds => panic!("unmatched end tuple"), FlatAtom::SlopeStarts(s, i) => { slope_stack.push(Vec::new()); - stack_history.push(CurrentStack::Slope(s, i)); + stack_history.push(Wrapper::Slope(s, i)); + } + FlatAtom::SlopeEnds => { + return Err(Error::MismatchedEnd(WrapperDiscriminants::Slope)); } - FlatAtom::SlopeEnds => panic!("unmatched end slope"), FlatAtom::Comment => result.push(Atom::Comment), - } + }, } } - result + Ok(result) } diff --git a/src/bng/score/utils/tests.rs b/src/bng/score/utils/tests.rs index 99d7c69..0bb7dad 100644 --- a/src/bng/score/utils/tests.rs +++ b/src/bng/score/utils/tests.rs @@ -10,24 +10,26 @@ mod inflate { fn instruction() -> Instruction { let parser = fasteval::Parser::new(); let mut slab = fasteval::Slab::new(); - parser - .parse(FASTEVAL_INSTRUCTION, &mut slab.ps) - .unwrap() - .from(&slab.ps) - .compile(&slab.ps, &mut slab.cs) + Instruction::new( + parser + .parse(FASTEVAL_INSTRUCTION, &mut slab.ps) + .unwrap() + .from(&slab.ps) + .compile(&slab.ps, &mut slab.cs), + ) } #[test] fn inflate_flat() { assert_eq!( - vec![ + Ok(vec![ Atom::Note(2), Atom::Rest, Atom::StartHere, Atom::Modifier(Modifier::Volume(2)), Atom::QuickModifier(QuickModifier::Volume(UP)), Atom::Comment - ], + ]), inflate(vec![ FlatAtom::Note(2), FlatAtom::Rest, @@ -42,10 +44,10 @@ mod inflate { #[test] fn inflate_loop_l1() { assert_eq!( - vec![Atom::Loop( + Ok(vec![Atom::Loop( unsafe { NonZeroU8::new_unchecked(3) }, vec![Atom::Note(2), Atom::Note(3)] - )], + )]), inflate(vec![ FlatAtom::LoopStarts(unsafe { NonZeroU8::new_unchecked(3) }), FlatAtom::Note(2), @@ -58,7 +60,7 @@ mod inflate { #[test] fn inflate_tuple_l1() { assert_eq!( - vec![Atom::Tuple(vec![Atom::Note(2), Atom::Note(3)])], + Ok(vec![Atom::Tuple(vec![Atom::Note(2), Atom::Note(3)])]), inflate(vec![ FlatAtom::TupleStarts, FlatAtom::Note(2), @@ -71,11 +73,11 @@ mod inflate { #[test] fn inflate_slope_l1() { assert_eq!( - vec![Atom::Slope( + Ok(vec![Atom::Slope( SlopeModifier::Note, instruction(), vec![Atom::Note(2), Atom::Note(3)] - )], + )]), inflate(vec![ FlatAtom::SlopeStarts(SlopeModifier::Note, instruction()), FlatAtom::Note(2), @@ -88,13 +90,13 @@ mod inflate { #[test] fn inflate_loop_l2() { assert_eq!( - vec![Atom::Loop( + Ok(vec![Atom::Loop( unsafe { NonZeroU8::new_unchecked(2) }, vec![Atom::Loop( unsafe { NonZeroU8::new_unchecked(3) }, vec![Atom::Note(2), Atom::Note(3)] )] - )], + )]), inflate(vec![ FlatAtom::LoopStarts(unsafe { NonZeroU8::new_unchecked(2) }), FlatAtom::LoopStarts(unsafe { NonZeroU8::new_unchecked(3) }), @@ -109,10 +111,10 @@ mod inflate { #[test] fn inflate_tuple_l2() { assert_eq!( - vec![Atom::Tuple(vec![Atom::Tuple(vec![ + Ok(vec![Atom::Tuple(vec![Atom::Tuple(vec![ Atom::Note(2), Atom::Note(3) - ])])], + ])])]), inflate(vec![ FlatAtom::TupleStarts, FlatAtom::TupleStarts, @@ -127,7 +129,7 @@ mod inflate { #[test] fn inflate_slope_l2() { assert_eq!( - vec![Atom::Slope( + Ok(vec![Atom::Slope( SlopeModifier::Note, instruction(), vec![Atom::Slope( @@ -135,7 +137,7 @@ mod inflate { instruction(), vec![Atom::Note(2), Atom::Note(3)] )] - )], + )]), inflate(vec![ FlatAtom::SlopeStarts(SlopeModifier::Note, instruction()), FlatAtom::SlopeStarts(SlopeModifier::Length, instruction()), @@ -150,7 +152,7 @@ mod inflate { #[test] fn mixed() { assert_eq!( - vec![Atom::Slope( + Ok(vec![Atom::Slope( SlopeModifier::Note, instruction(), vec![Atom::Slope( @@ -166,7 +168,7 @@ mod inflate { ) ] )] - )], + )]), inflate(vec![ FlatAtom::SlopeStarts(SlopeModifier::Note, instruction()), FlatAtom::SlopeStarts(SlopeModifier::Length, instruction()), @@ -187,24 +189,26 @@ mod inflate { } #[test] - #[should_panic] - fn mixed_panic() { - inflate(vec![ - FlatAtom::SlopeStarts(SlopeModifier::Note, instruction()), - FlatAtom::SlopeStarts(SlopeModifier::Length, instruction()), - FlatAtom::Note(2), - FlatAtom::TupleStarts, - FlatAtom::Rest, - FlatAtom::SlopeEnds, // mismatched slope end while in a tuple - FlatAtom::Note(6), - FlatAtom::TupleEnds, - FlatAtom::Note(3), - FlatAtom::LoopStarts(unsafe { NonZeroU8::new_unchecked(9) }), - FlatAtom::QuickModifier(QuickModifier::Pizz(ON)), - FlatAtom::Note(0), - FlatAtom::LoopEnds, - FlatAtom::SlopeEnds, - FlatAtom::SlopeEnds, - ]); + fn mixed_mismatched_end() { + assert_eq!( + Err(InflateError::MismatchedEnd(WrapperDiscriminants::Slope)), + inflate(vec![ + FlatAtom::SlopeStarts(SlopeModifier::Note, instruction()), + FlatAtom::SlopeStarts(SlopeModifier::Length, instruction()), + FlatAtom::Note(2), + FlatAtom::TupleStarts, + FlatAtom::Rest, + FlatAtom::SlopeEnds, // mismatched slope end while in a tuple + FlatAtom::Note(6), + FlatAtom::TupleEnds, + FlatAtom::Note(3), + FlatAtom::LoopStarts(unsafe { NonZeroU8::new_unchecked(9) }), + FlatAtom::QuickModifier(QuickModifier::Pizz(ON)), + FlatAtom::Note(0), + FlatAtom::LoopEnds, + FlatAtom::SlopeEnds, + FlatAtom::SlopeEnds, + ]) + ) } } diff --git a/src/main.rs b/src/main.rs index 1746585..5cb1207 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +/// TODO: remove clap, use only a file or standard in use clap::Parser; mod bng;