klavier-core 0.1.15

Core library of klavier.
Documentation
use serde_json::Value;

use crate::{bar::Bar, ctrl_chg::CtrlChg, key::Key, models::{FromClipboardTextErr, Models}, note::Note, rhythm::Rhythm, tempo::Tempo};

#[derive(Clone, PartialEq, Debug, serde::Deserialize, serde::Serialize)]
pub struct ExportedProject {
    pub key: Option<Key>,
    pub rhythm: Option<Rhythm>,
    pub notes: Vec<Note>,
    pub bars: Vec<Bar>,
    pub tempos: Vec<Tempo>,
    pub dumpers: Vec<CtrlChg>,
    pub softs: Vec<CtrlChg>,
}

impl ExportedProject {
    pub fn from_clipboard_text(json: String) -> Result<Self, FromClipboardTextErr> {
        let mut stream = serde_json::Deserializer::from_str(&json).into_iter::<Value>();
        match stream.next() {
            None => Err(FromClipboardTextErr::EmptyString),
            Some(Ok(ver)) =>
                if let Value::Number(ver_no) = ver {
                    if let Some(v) = ver_no.as_u64() {
                        if v == Models::VERSION {
                            serde_json::from_slice::<'_, ExportedProject>(&json.as_bytes()[stream.byte_offset()..])
                                .map_err(|e| FromClipboardTextErr::CannotParse { err_json: json, detail: e.to_string() })
                        } else {
                            Err(FromClipboardTextErr::VersionErr { detected_ver: v })
                        }
                    } else {
                        Err(FromClipboardTextErr::VersionNotU64 { err_json: json })
                    }
                } else {
                    Err(FromClipboardTextErr::VersionNotU64 { err_json: json })
                },
            Some(Err(e)) => Err(FromClipboardTextErr::CannotParse { err_json: json, detail: e.to_string() })
        }
    }

    pub fn to_models(self) -> Models {
        Models {
            notes: self.notes,
            bars: self.bars,
            tempos: self.tempos,
            dumpers: self.dumpers,
            softs: self.softs,
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::{key::Key, rhythm::Rhythm};
    use super::ExportedProject;

    #[test]
    fn import_key() {
        let proj = ExportedProject {
            key: Some(Key::FLAT_3),
            rhythm: None,
            notes: vec![],
            bars: vec![],
            tempos: vec![],
            dumpers: vec![],
            softs: vec![]
        };
        let json = format!("1{}", serde_json::to_string(&proj).unwrap());
        
        let deserialized = ExportedProject::from_clipboard_text(json).unwrap();
        assert_eq!(deserialized.key, Some(Key::FLAT_3));
    }

    #[test]
    fn import_rhythm() {
        let proj = ExportedProject {
            key: None,
            rhythm: Some(Rhythm::new(3, 4)),
            notes: vec![],
            bars: vec![],
            tempos: vec![],
            dumpers: vec![],
            softs: vec![]
        };
        let json = format!("1{}", serde_json::to_string(&proj).unwrap());

        let deserialized = ExportedProject::from_clipboard_text(json).unwrap();
        assert_eq!(deserialized.rhythm, Some(Rhythm::new(3, 4)));
    }
}