Skip to content

Commit

Permalink
Add option deserialisation
Browse files Browse the repository at this point in the history
  • Loading branch information
dhardy committed Feb 5, 2021
1 parent 3ca235a commit e7d2954
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 1 deletion.
14 changes: 13 additions & 1 deletion src/event/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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,
}
Expand Down Expand Up @@ -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)),
}
}
Expand Down
104 changes: 104 additions & 0 deletions src/event/shortcuts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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<E: de::Error>(self, u: &str) -> Result<Self::Value, E> {
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: D) -> Result<Self, D::Error>
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("{ <modifiers> : { <key> : <command> } }")
}

fn visit_map<A>(self, mut reader: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
let mut map = LinearMap::<ModifiersState, HashMap<VirtualKeyCode, Command>>::new();
while let Some(key) = reader.next_key::<ModifierStateVisitor>()? {
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: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
d.deserialize_map(ShortcutsVisitor)
}
}

0 comments on commit e7d2954

Please sign in to comment.