From e7d295474457370a253cad4c5907f71a15341c77 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Fri, 5 Feb 2021 14:21:32 +0000 Subject: [PATCH] Add option deserialisation --- src/event/config.rs | 14 +++++- src/event/shortcuts.rs | 104 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 1 deletion(-) diff --git a/src/event/config.rs b/src/event/config.rs index a685bac98..7793ed7a1 100644 --- a/src/event/config.rs +++ b/src/event/config.rs @@ -6,6 +6,8 @@ //! Event handling configuration use super::shortcuts::Shortcuts; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; use std::path::Path; use thiserror::Error; @@ -52,7 +54,7 @@ impl Default for ConfigFormat { /// Event handling configuration #[derive(Debug)] -#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Config { pub shortcuts: Shortcuts, } @@ -90,6 +92,16 @@ impl Config { } match format { + #[cfg(feature = "json")] + ConfigFormat::Json => { + let r = std::io::BufReader::new(std::fs::File::open(path)?); + Ok(serde_json::from_reader(r)?) + } + #[cfg(feature = "yaml")] + ConfigFormat::Yaml => { + let r = std::io::BufReader::new(std::fs::File::open(path)?); + Ok(serde_yaml::from_reader(r)?) + } _ => Err(ConfigError::UnsupportedFormat(format)), } } diff --git a/src/event/shortcuts.rs b/src/event/shortcuts.rs index f35cf9b63..2a828ab6d 100644 --- a/src/event/shortcuts.rs +++ b/src/event/shortcuts.rs @@ -8,8 +8,12 @@ use super::{Command, ModifiersState, VirtualKeyCode}; use linear_map::LinearMap; #[cfg(feature = "serde")] +use serde::de::{self, Deserialize, Deserializer, MapAccess, Unexpected, Visitor}; +#[cfg(feature = "serde")] use serde::ser::{Serialize, SerializeMap, Serializer}; use std::collections::HashMap; +#[cfg(feature = "serde")] +use std::fmt; /// Shortcut manager #[derive(Debug)] @@ -253,3 +257,103 @@ impl Serialize for Shortcuts { map.end() } } + +// #[derive(Error, Debug)] +// pub enum DeError { +// #[error("invalid modifier state: {0}")] +// State(String), +// } + +#[cfg(feature = "serde")] +struct ModifierStateVisitor(ModifiersState); +#[cfg(feature = "serde")] +impl<'de> Visitor<'de> for ModifierStateVisitor { + type Value = ModifierStateVisitor; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("none or ctrl or alt-shift-super etc.") + } + + fn visit_str(self, u: &str) -> Result { + let mut v = u; + let mut state = ModifiersState::empty(); + + if v.starts_with("ctrl") { + state |= ModifiersState::CTRL; + v = &v[v.len().min(4)..]; + } + if v.starts_with("-") { + v = &v[1..]; + } + if v.starts_with("alt") { + state |= ModifiersState::ALT; + v = &v[v.len().min(3)..]; + } + if v.starts_with("-") { + v = &v[1..]; + } + if v.starts_with("shift") { + state |= ModifiersState::SHIFT; + v = &v[v.len().min(5)..]; + } + if v.starts_with("-") { + v = &v[1..]; + } + if v.starts_with("super") { + state |= ModifiersState::LOGO; + v = &v[v.len().min(5)..]; + } + + if v.is_empty() || u == "none" { + Ok(ModifierStateVisitor(state)) + } else { + Err(E::invalid_value( + Unexpected::Str(u), + &"none or ctrl or alt-shift-super etc.", + )) + } + } +} + +#[cfg(feature = "serde")] +impl<'de> Deserialize<'de> for ModifierStateVisitor { + fn deserialize(d: D) -> Result + where + D: Deserializer<'de>, + { + d.deserialize_str(ModifierStateVisitor(Default::default())) + } +} + +#[cfg(feature = "serde")] +struct ShortcutsVisitor; +#[cfg(feature = "serde")] +impl<'de> Visitor<'de> for ShortcutsVisitor { + type Value = Shortcuts; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("{ : { : } }") + } + + fn visit_map(self, mut reader: A) -> Result + where + A: MapAccess<'de>, + { + let mut map = LinearMap::>::new(); + while let Some(key) = reader.next_key::()? { + let value = reader.next_value()?; + map.insert(key.0, value); + } + Ok(Shortcuts { map }) + } +} + +#[cfg(feature = "serde")] +impl<'de> Deserialize<'de> for Shortcuts { + fn deserialize(d: D) -> Result + where + D: Deserializer<'de>, + { + d.deserialize_map(ShortcutsVisitor) + } +}