use crate::generics::{PlaybackSlots, RecordingBufferSlots, Slots};
use crate::projects::SlotAttributes;
use crate::settings::{LoopMode, SlotType, TimeStretchMode, TrigQuantizationMode};
use serde::{
de::{self, MapAccess, Visitor},
Deserialize, Deserializer,
};
use std::fmt;
use std::path::PathBuf;
impl<'de> Deserialize<'de> for SlotAttributes {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
enum Field {
SlotType,
SlotId,
Path,
Timestretch,
Loop,
Quant,
Gain,
Bpm,
}
const FIELDS: &[&str] = &[
"slot_type",
"slot_id",
"path",
"timestrech_mode",
"loop_mode",
"trig_quantization_mode",
"gain",
"bpm",
];
impl<'de> Deserialize<'de> for Field {
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
where
D: Deserializer<'de>,
{
struct FieldVisitor;
impl Visitor<'_> for FieldVisitor {
type Value = Field;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(
FIELDS
.iter()
.map(|x| format!["`{x}`"])
.collect::<Vec<_>>()
.join(" or ")
.as_str(),
)
}
fn visit_str<E>(self, value: &str) -> Result<Field, E>
where
E: de::Error,
{
match value {
"slot_type" => Ok(Field::SlotType),
"slot_id" => Ok(Field::SlotId),
"path" => Ok(Field::Path),
"timestrech_mode" => Ok(Field::Timestretch),
"loop_mode" => Ok(Field::Loop),
"trig_quantization_mode" => Ok(Field::Quant),
"gain" => Ok(Field::Gain),
"bpm" => Ok(Field::Bpm),
_ => Err(de::Error::unknown_field(value, FIELDS)),
}
}
}
deserializer.deserialize_identifier(FieldVisitor)
}
}
struct SlotAttributesVisitor;
impl<'de> Visitor<'de> for SlotAttributesVisitor {
type Value = SlotAttributes;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("struct SlotAttributes")
}
fn visit_map<V>(self, mut map: V) -> Result<SlotAttributes, V::Error>
where
V: MapAccess<'de>,
{
let mut slot_type = None;
let mut slot_id = None;
let mut path = None;
let mut timestretch_mode = None;
let mut loop_mode = None;
let mut trig_quantization_mode = None;
let mut gain = None;
let mut bpm = None;
while let Some(key) = map.next_key()? {
match key {
Field::SlotType => {
if slot_type.is_some() {
return Err(de::Error::duplicate_field("slot_type"));
}
slot_type = Some(map.next_value::<SlotType>()?);
}
Field::SlotId => {
if slot_id.is_some() {
return Err(de::Error::duplicate_field("slot_id"));
}
slot_id = Some(map.next_value::<u8>()?);
}
Field::Path => {
if path.is_some() {
return Err(de::Error::duplicate_field("path"));
}
path = Some(map.next_value::<PathBuf>()?);
}
Field::Timestretch => {
if timestretch_mode.is_some() {
return Err(de::Error::duplicate_field("timestretch_mode"));
}
timestretch_mode = Some(map.next_value::<TimeStretchMode>()?);
}
Field::Loop => {
if loop_mode.is_some() {
return Err(de::Error::duplicate_field("loop_mode"));
}
loop_mode = Some(map.next_value::<LoopMode>()?);
}
Field::Quant => {
if trig_quantization_mode.is_some() {
return Err(de::Error::duplicate_field("trig_quantization_mode"));
}
trig_quantization_mode =
Some(map.next_value::<TrigQuantizationMode>()?);
}
Field::Gain => {
if gain.is_some() {
return Err(de::Error::duplicate_field("gain"));
}
gain = Some(map.next_value::<u8>()?);
}
Field::Bpm => {
if bpm.is_some() {
return Err(de::Error::duplicate_field("bpm"));
}
bpm = Some(map.next_value::<u16>()?);
}
}
}
let slot = SlotAttributes {
slot_type: slot_type.ok_or_else(|| de::Error::missing_field("slot_type"))?,
slot_id: slot_id.ok_or_else(|| de::Error::missing_field("slot_type"))?,
path, timestrech_mode: timestretch_mode
.ok_or_else(|| de::Error::missing_field("trimstretch_mode"))?,
loop_mode: loop_mode.ok_or_else(|| de::Error::missing_field("loop_mode"))?,
trig_quantization_mode: trig_quantization_mode
.ok_or_else(|| de::Error::missing_field("trig_quantization_mode"))?,
gain: gain.ok_or_else(|| de::Error::missing_field("gain"))?,
bpm: bpm.ok_or_else(|| de::Error::missing_field("bpm"))?,
};
Ok(slot)
}
}
deserializer.deserialize_struct("SampleSlot", FIELDS, SlotAttributesVisitor)
}
}
impl<'de> Deserialize<'de> for Slots<Option<SlotAttributes>> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
enum Field {
Static,
Flex,
Recording,
}
impl<'de> Deserialize<'de> for Field {
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
where
D: Deserializer<'de>,
{
struct FieldVisitor;
impl Visitor<'_> for FieldVisitor {
type Value = Field;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("`static_slots` or `flex_slots` or `recording_buffers`")
}
fn visit_str<E>(self, value: &str) -> Result<Field, E>
where
E: de::Error,
{
match value {
"static_slots" => Ok(Field::Static),
"flex_slots" => Ok(Field::Flex),
"recording_buffers" => Ok(Field::Recording),
_ => Err(de::Error::unknown_field(value, FIELDS)),
}
}
}
deserializer.deserialize_identifier(FieldVisitor)
}
}
struct SampleSlotsVisitor;
impl<'de> Visitor<'de> for SampleSlotsVisitor {
type Value = Slots<Option<SlotAttributes>>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("struct Slots<Option<SlotAttributes>>")
}
fn visit_unit<E>(self) -> Result<Slots<Option<SlotAttributes>>, E> {
Ok(Slots::<Option<SlotAttributes>>::default())
}
fn visit_map<V>(self, mut map: V) -> Result<Slots<Option<SlotAttributes>>, V::Error>
where
V: MapAccess<'de>,
{
let mut s_slots = None;
let mut f_slots = None;
let mut r_slots = None;
while let Some(key) = map.next_key()? {
match key {
Field::Static => {
if s_slots.is_some() {
return Err(de::Error::duplicate_field("static_slots"));
}
s_slots =
Some(map.next_value::<PlaybackSlots<Option<SlotAttributes>>>()?);
}
Field::Flex => {
if f_slots.is_some() {
return Err(de::Error::duplicate_field("flex_slots"));
}
f_slots =
Some(map.next_value::<PlaybackSlots<Option<SlotAttributes>>>()?);
}
Field::Recording => {
if r_slots.is_some() {
return Err(de::Error::duplicate_field("recording_buffers"));
}
r_slots = Some(
map.next_value::<RecordingBufferSlots<Option<SlotAttributes>>>()?,
);
}
}
}
let static_slots =
s_slots.ok_or_else(|| de::Error::missing_field("static_slots"))?;
let flex_slots = f_slots.ok_or_else(|| de::Error::missing_field("flex_slots"))?;
let recording_buffers =
r_slots.ok_or_else(|| de::Error::missing_field("recording_buffers"))?;
Ok(Slots::new(flex_slots, recording_buffers, static_slots))
}
}
const FIELDS: &[&str] = &["static_slots", "flex_slots", "recording_buffers"];
deserializer.deserialize_struct("SampleSlots", FIELDS, SampleSlotsVisitor)
}
}