From 93067b3010c0c724204e177825c0e9822a94345a Mon Sep 17 00:00:00 2001 From: p6nj Date: Mon, 4 Nov 2024 22:26:33 -0500 Subject: [PATCH] cleaning my room --- src/bng/score.rs | 109 +------------------------------------ src/bng/score/ser.rs | 127 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+), 107 deletions(-) create mode 100644 src/bng/score/ser.rs diff --git a/src/bng/score.rs b/src/bng/score.rs index d283760..0595765 100644 --- a/src/bng/score.rs +++ b/src/bng/score.rs @@ -27,7 +27,9 @@ use thiserror::Error; use utils::{inflate, InflateError}; mod lex; +mod ser; mod utils; +pub use ser::*; use super::Expression as Instruction; @@ -35,113 +37,6 @@ use super::Expression as Instruction; #[cfg_attr(debug_assertions, derive(Serialize, Debug))] pub struct Atoms(Vec); -#[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>) -> 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(deserializer: D) -> Result - 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(self, mut seq: A) -> Result - 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(self, mut map: A) -> Result - 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))] pub enum Atom { Note(u8), diff --git a/src/bng/score/ser.rs b/src/bng/score/ser.rs new file mode 100644 index 0000000..ef8b300 --- /dev/null +++ b/src/bng/score/ser.rs @@ -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>) -> 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(deserializer: D) -> Result + 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(self, mut seq: A) -> Result + 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(self, mut map: A) -> Result + 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::(&sheet, flat_atom_parser(¬es)) + } +} + +fn maybe_yml_str_space<'a, E>() -> impl Parser<&'a str, Vec, 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>::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) +}