#[cfg(not(any(
feature = "json",
feature = "json5",
feature = "yaml",
feature = "ron",
feature = "lexpr"
)))]
compile_error!("You must select one serializer / deserializer feature");
cfg_exclusive::cfg_exclusive! {
serializer_deserializer,
["json", "json5", "yaml", "ron", "lexpr"],
"You can select only one serializer / deserializer feature (json, json5, yaml, toml, ron or lexpr)"
}
#[cfg(any(feature = "json5", feature = "ron"))]
use std::io::read_to_string;
use std::{env::args, fs::File, io::Read};
use anyhow::Context;
use bliplab::{Channel, PathOrString, Song, VariableChange};
use cfg_if::cfg_if;
use serde::{Serialize, de::DeserializeOwned};
const TARGET: &str = "BLIP lab file";
fn example_song() -> Song<'static> {
Song::new(
Default::default(),
[(
"Piano".into(),
Channel::new(
PathOrString::String("hi".into()),
vec!["do", "ré", "mi"].into_iter().map(Into::into),
"sin(2*pi()*(442*2^((n+1)/N))*t)".parse().unwrap(),
[
('l', 4f64),
('L', 0.0),
('t', 0.0),
('T', 60.0),
('N', 12.0),
],
[],
[(
"L".into(),
VariableChange::new('L', "2^(2-log(2, l))*(60/T)".parse().unwrap()),
)],
),
)],
)
}
fn prettify<V: Serialize>(value: &V) -> anyhow::Result<String> {
cfg_if! {
if #[cfg(feature = "json")] {
serde_json::to_string_pretty(value).map_err(Into::into)
} else if #[cfg(feature = "json5")] {
json5::to_string(value).map_err(Into::into)
} else if #[cfg(feature = "yaml")] {
serde_yaml::to_string(value).map_err(Into::into)
} else if #[cfg(feature = "ron")] {
ron::to_string(value).map_err(Into::into)
} else if #[cfg(feature = "lexpr")] {
serde_lexpr::to_string(value).map_err(Into::into)
}
}
}
fn from_reader<R: Read, T: DeserializeOwned>(reader: R) -> anyhow::Result<T> {
cfg_if! {
if #[cfg(feature = "json")] {
serde_json::from_reader(reader).map_err(Into::into)
} else if #[cfg(feature = "json5")] {
json5::from_str(&read_to_string(reader)?).map_err(Into::into)
} else if #[cfg(feature = "yaml")] {
serde_yaml::from_reader(reader).map_err(Into::into)
} else if #[cfg(feature = "ron")] {
ron::from_str(&read_to_string(reader)?).map_err(Into::into)
} else if #[cfg(feature = "lexpr")] {
serde_lexpr::from_reader(reader).map_err(Into::into)
}
}
}
fn main() -> anyhow::Result<()> {
let string = args().skip(1).next().context(format!(
"You need to give a single argument with the filename of your {TARGET}."
))?;
if let Some(argument) = string.strip_prefix("--") {
if argument == "example" {
println!(
"{}",
prettify(&example_song())
.context("Can't serialize the example song, this is a bug.")?
);
} else if argument == "help" {
println!(
"BLIP lab file player. Pass it a path to a {TARGET} or use with \"--example\" for an example {TARGET}."
);
} else {
eprintln!("Unknown argument: \"{argument}\"");
}
} else {
let song: Song =
from_reader(File::open(string).context(format!("Failed to open the {TARGET}."))?)
.context(format!("Failed to read the {TARGET}."))?;
println!(
"{}",
prettify(&song).context("Failed to pretty print the song! What?!")?
);
}
Ok(())
}