cleaning my room
This commit is contained in:
parent
a06e0a1d02
commit
93067b3010
2 changed files with 129 additions and 107 deletions
109
src/bng/score.rs
109
src/bng/score.rs
|
@ -27,7 +27,9 @@ use thiserror::Error;
|
||||||
use utils::{inflate, InflateError};
|
use utils::{inflate, InflateError};
|
||||||
|
|
||||||
mod lex;
|
mod lex;
|
||||||
|
mod ser;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
pub use ser::*;
|
||||||
|
|
||||||
use super::Expression as Instruction;
|
use super::Expression as Instruction;
|
||||||
|
|
||||||
|
@ -35,113 +37,6 @@ use super::Expression as Instruction;
|
||||||
#[cfg_attr(debug_assertions, derive(Serialize, Debug))]
|
#[cfg_attr(debug_assertions, derive(Serialize, Debug))]
|
||||||
pub struct Atoms(Vec<Atom>);
|
pub struct Atoms(Vec<Atom>);
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
|
||||||
enum AtomsSerializeError {
|
|
||||||
#[error("sheet parsing error: {0}")]
|
|
||||||
Parsing(String),
|
|
||||||
#[error("sheet semantics: {0}")]
|
|
||||||
Inflation(#[from] InflateError),
|
|
||||||
}
|
|
||||||
|
|
||||||
fn nom_err_message(e: nom::Err<nom::error::Error<&str>>) -> String {
|
|
||||||
match e {
|
|
||||||
nom::Err::Incomplete(needed) => format!(
|
|
||||||
"input is incomplete, needed {} byte(s) more",
|
|
||||||
match needed {
|
|
||||||
nom::Needed::Unknown => "?".to_string(),
|
|
||||||
nom::Needed::Size(s) => s.to_string(),
|
|
||||||
}
|
|
||||||
),
|
|
||||||
nom::Err::Error(e) | nom::Err::Failure(e) => format!(
|
|
||||||
"got error code {code:#?} at \"{input}\"",
|
|
||||||
code = e.code,
|
|
||||||
input = e.input
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for Atoms {
|
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
||||||
where
|
|
||||||
D: serde::Deserializer<'de>,
|
|
||||||
{
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
#[serde(field_identifier, rename_all = "lowercase")]
|
|
||||||
enum Field {
|
|
||||||
Notes,
|
|
||||||
Sheet,
|
|
||||||
}
|
|
||||||
#[derive(Deserialize, new)]
|
|
||||||
struct NotesSheet {
|
|
||||||
notes: String,
|
|
||||||
sheet: String,
|
|
||||||
}
|
|
||||||
struct NotesSheetVisitor;
|
|
||||||
impl<'de> Visitor<'de> for NotesSheetVisitor {
|
|
||||||
type Value = NotesSheet;
|
|
||||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
formatter.write_str("a \"notes\" field and a \"sheet\" field")
|
|
||||||
}
|
|
||||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
|
||||||
where
|
|
||||||
A: serde::de::SeqAccess<'de>,
|
|
||||||
{
|
|
||||||
let notes = seq
|
|
||||||
.next_element()?
|
|
||||||
.ok_or_else(|| de::Error::invalid_length(0, &self))?;
|
|
||||||
let sheet = seq
|
|
||||||
.next_element()?
|
|
||||||
.ok_or_else(|| de::Error::invalid_length(1, &self))?;
|
|
||||||
Ok(NotesSheet::new(notes, sheet))
|
|
||||||
}
|
|
||||||
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
|
|
||||||
where
|
|
||||||
A: de::MapAccess<'de>,
|
|
||||||
{
|
|
||||||
let mut notes = None;
|
|
||||||
let mut sheet = None;
|
|
||||||
while let Some(key) = map.next_key()? {
|
|
||||||
match key {
|
|
||||||
Field::Notes => {
|
|
||||||
if notes.is_some() {
|
|
||||||
return Err(de::Error::duplicate_field("notes"));
|
|
||||||
}
|
|
||||||
notes = Some(map.next_value()?);
|
|
||||||
}
|
|
||||||
Field::Sheet => {
|
|
||||||
if sheet.is_some() {
|
|
||||||
return Err(de::Error::duplicate_field("sheet"));
|
|
||||||
}
|
|
||||||
sheet = Some(map.next_value()?);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let notes = notes.ok_or_else(|| de::Error::missing_field("notes"))?;
|
|
||||||
let sheet = sheet.ok_or_else(|| de::Error::missing_field("sheet"))?;
|
|
||||||
Ok(NotesSheet::new(notes, sheet))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const FIELDS: &[&str] = &["notes", "sheet"];
|
|
||||||
let NotesSheet { notes, sheet } =
|
|
||||||
deserializer.deserialize_struct("NotesSheet", FIELDS, NotesSheetVisitor)?;
|
|
||||||
let maybe_yml_str_space = || many0(one_of(" \t\r"));
|
|
||||||
let x = all_consuming(terminated(
|
|
||||||
many0(preceded(maybe_yml_str_space(), flat_atom_parser(¬es))),
|
|
||||||
maybe_yml_str_space(),
|
|
||||||
))(dbg!(&sheet))
|
|
||||||
.map_err(nom_err_message)
|
|
||||||
.map_err(AtomsSerializeError::Parsing)
|
|
||||||
.map_err(de::Error::custom)
|
|
||||||
.and_then(|(_, v)| {
|
|
||||||
inflate(v)
|
|
||||||
.map_err(AtomsSerializeError::from)
|
|
||||||
.map_err(de::Error::custom)
|
|
||||||
})
|
|
||||||
.map(Atoms);
|
|
||||||
x
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(debug_assertions, derive(Debug, PartialEq))]
|
#[cfg_attr(debug_assertions, derive(Debug, PartialEq))]
|
||||||
pub enum Atom {
|
pub enum Atom {
|
||||||
Note(u8),
|
Note(u8),
|
||||||
|
|
127
src/bng/score/ser.rs
Normal file
127
src/bng/score/ser.rs
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
use de::Deserializer;
|
||||||
|
use nom::Parser;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
enum AtomsSerializeError {
|
||||||
|
#[error("sheet parsing error: {0}")]
|
||||||
|
Parsing(String),
|
||||||
|
#[error("sheet semantics: {0}")]
|
||||||
|
Inflation(#[from] InflateError),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn nom_err_message(e: nom::Err<nom::error::Error<&str>>) -> String {
|
||||||
|
match e {
|
||||||
|
nom::Err::Incomplete(needed) => format!(
|
||||||
|
"input is incomplete, needed {} byte(s) more",
|
||||||
|
match needed {
|
||||||
|
nom::Needed::Unknown => "?".to_string(),
|
||||||
|
nom::Needed::Size(s) => s.to_string(),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
nom::Err::Error(e) | nom::Err::Failure(e) => format!(
|
||||||
|
"got error code {code:#?} at \"{input}\"",
|
||||||
|
code = e.code,
|
||||||
|
input = e.input
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for Atoms {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(field_identifier, rename_all = "lowercase")]
|
||||||
|
enum Field {
|
||||||
|
Notes,
|
||||||
|
Sheet,
|
||||||
|
}
|
||||||
|
#[derive(Deserialize, new)]
|
||||||
|
struct NotesSheet {
|
||||||
|
notes: String,
|
||||||
|
sheet: String,
|
||||||
|
}
|
||||||
|
struct NotesSheetVisitor;
|
||||||
|
impl<'de> Visitor<'de> for NotesSheetVisitor {
|
||||||
|
type Value = NotesSheet;
|
||||||
|
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
formatter.write_str("a \"notes\" field and a \"sheet\" field")
|
||||||
|
}
|
||||||
|
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||||
|
where
|
||||||
|
A: serde::de::SeqAccess<'de>,
|
||||||
|
{
|
||||||
|
let notes = seq
|
||||||
|
.next_element()?
|
||||||
|
.ok_or_else(|| de::Error::invalid_length(0, &self))?;
|
||||||
|
let sheet = seq
|
||||||
|
.next_element()?
|
||||||
|
.ok_or_else(|| de::Error::invalid_length(1, &self))?;
|
||||||
|
Ok(NotesSheet::new(notes, sheet))
|
||||||
|
}
|
||||||
|
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
|
||||||
|
where
|
||||||
|
A: de::MapAccess<'de>,
|
||||||
|
{
|
||||||
|
let mut notes = None;
|
||||||
|
let mut sheet = None;
|
||||||
|
while let Some(key) = map.next_key()? {
|
||||||
|
match key {
|
||||||
|
Field::Notes => {
|
||||||
|
if notes.is_some() {
|
||||||
|
return Err(de::Error::duplicate_field("notes"));
|
||||||
|
}
|
||||||
|
notes = Some(map.next_value()?);
|
||||||
|
}
|
||||||
|
Field::Sheet => {
|
||||||
|
if sheet.is_some() {
|
||||||
|
return Err(de::Error::duplicate_field("sheet"));
|
||||||
|
}
|
||||||
|
sheet = Some(map.next_value()?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let notes = notes.ok_or_else(|| de::Error::missing_field("notes"))?;
|
||||||
|
let sheet = sheet.ok_or_else(|| de::Error::missing_field("sheet"))?;
|
||||||
|
Ok(NotesSheet::new(notes, sheet))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const FIELDS: &[&str] = &["notes", "sheet"];
|
||||||
|
let NotesSheet { notes, sheet } =
|
||||||
|
deserializer.deserialize_struct("NotesSheet", FIELDS, NotesSheetVisitor)?;
|
||||||
|
flat_atom_parser_mapper::<D, _>(&sheet, flat_atom_parser(¬es))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn maybe_yml_str_space<'a, E>() -> impl Parser<&'a str, Vec<char>, E>
|
||||||
|
where
|
||||||
|
E: nom::error::ParseError<&'a str>,
|
||||||
|
{
|
||||||
|
many0(one_of(" \t\r"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flat_atom_parser_mapper<'a, 'de, D, P>(
|
||||||
|
input: &'a str,
|
||||||
|
parser: P,
|
||||||
|
) -> Result<Atoms, <D as Deserializer<'de>>::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
|
P: Parser<&'a str, FlatAtom, nom::error::Error<&'a str>>,
|
||||||
|
{
|
||||||
|
all_consuming(terminated(
|
||||||
|
many0(preceded(maybe_yml_str_space(), parser)),
|
||||||
|
maybe_yml_str_space(),
|
||||||
|
))(input)
|
||||||
|
.map_err(nom_err_message)
|
||||||
|
.map_err(AtomsSerializeError::Parsing)
|
||||||
|
.map_err(de::Error::custom)
|
||||||
|
.and_then(|(_, v)| {
|
||||||
|
inflate(v)
|
||||||
|
.map_err(AtomsSerializeError::from)
|
||||||
|
.map_err(de::Error::custom)
|
||||||
|
})
|
||||||
|
.map(Atoms)
|
||||||
|
}
|
Loading…
Reference in a new issue