diff --git a/Cargo.lock b/Cargo.lock index e216313..daae2bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1293,6 +1293,12 @@ dependencies = [ "tracing-futures", ] +[[package]] +name = "half" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3" + [[package]] name = "hashbrown" version = "0.9.1" @@ -2029,6 +2035,7 @@ dependencies = [ "reqwest 0.9.24", "rspotify", "serde", + "serde_cbor", "serde_json", "strum 0.20.0", "strum_macros 0.20.1", @@ -3200,6 +3207,16 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde_cbor" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622" +dependencies = [ + "half", + "serde", +] + [[package]] name = "serde_derive" version = "1.0.125" diff --git a/Cargo.toml b/Cargo.toml index 2e185bd..78a446d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,6 +47,7 @@ strum_macros = "0.20.1" libc = "0.2" regex = "1" ioctl-rs = { version = "0.2", optional = true } +serde_cbor = "0.11.1" [dependencies.cursive] version = "0.16.3" diff --git a/src/config.rs b/src/config.rs index 51a482e..9f6e141 100644 --- a/src/config.rs +++ b/src/config.rs @@ -9,7 +9,7 @@ use platform_dirs::AppDirs; use crate::command::{SortDirection, SortKey}; use crate::playable::Playable; use crate::queue; -use crate::serialization::{Serializer, TOML}; +use crate::serialization::{Serializer, CBOR, TOML}; pub const CLIENT_ID: &str = "d420a117a32841c2b3474932e49fb54b"; @@ -66,7 +66,6 @@ pub struct QueueState { pub current_track: Option, pub random_order: Option>, pub track_progress: std::time::Duration, - #[serde(skip_serializing_if = "Vec::is_empty")] pub queue: Vec, } @@ -76,7 +75,6 @@ pub struct UserState { pub shuffle: bool, pub repeat: queue::RepeatSetting, pub queuestate: QueueState, - #[serde(serialize_with = "toml::ser::tables_last")] pub playlist_orders: HashMap, } @@ -109,8 +107,8 @@ impl Config { }); let mut userstate = { - let path = config_path("userstate.toml"); - TOML.load_or_generate_default(path, || Ok(UserState::default()), true) + let path = config_path("userstate.cbor"); + CBOR.load_or_generate_default(path, || Ok(UserState::default()), true) .expect("could not load user state") }; @@ -145,9 +143,9 @@ impl Config { } pub fn save_state(&self) { - let path = config_path("userstate.toml"); + let path = config_path("userstate.cbor"); debug!("saving user state to {}", path.display()); - if let Err(e) = TOML.write(path, self.state().clone()) { + if let Err(e) = CBOR.write(path, self.state().clone()) { error!("Could not save user state: {}", e); } } diff --git a/src/serialization.rs b/src/serialization.rs index e7c3f53..ae0b72b 100644 --- a/src/serialization.rs +++ b/src/serialization.rs @@ -68,4 +68,42 @@ impl Serializer for TomlSerializer { } } +pub struct CborSerializer {} +impl Serializer for CborSerializer { + fn load, T: serde::Serialize + serde::de::DeserializeOwned>( + &self, + path: P, + ) -> Result { + let contents = std::fs::read(&path) + .map_err(|e| format!("Unable to read {}: {}", path.as_ref().to_string_lossy(), e))?; + serde_cbor::from_slice(&contents).map_err(|e| { + format!( + "Unable to parse CBOR {}: {}", + path.as_ref().to_string_lossy(), + e + ) + }) + } + + fn write, T: serde::Serialize>(&self, path: P, value: T) -> Result { + let file = std::fs::File::create(&path).map_err(|e| { + format!( + "Failed creating file {}: {}", + path.as_ref().to_string_lossy(), + e + ) + })?; + serde_cbor::to_writer(file, &value) + .map(|_| value) + .map_err(|e| { + format!( + "Failed writing content to {}: {}", + path.as_ref().display(), + e + ) + }) + } +} + pub static TOML: TomlSerializer = TomlSerializer {}; +pub static CBOR: CborSerializer = CborSerializer {};