Skip to content

Commit

Permalink
Implement Config deserialisation
Browse files Browse the repository at this point in the history
  • Loading branch information
dhardy committed Feb 4, 2021
1 parent 193ad2a commit 33b3feb
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 5 deletions.
19 changes: 15 additions & 4 deletions src/event/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
//! Event handling configuration
use super::shortcuts::Shortcuts;
use serde::Serialize;
use serde::{Deserialize, Serialize};
use std::fs::File;
use std::io::BufWriter;
use std::io::{BufReader, BufWriter};
use std::path::Path;
use thiserror::Error;

Expand Down Expand Up @@ -52,7 +52,7 @@ impl Default for ConfigFormat {
}

/// Event handling configuration
#[derive(Debug, Serialize)]
#[derive(Debug, Deserialize, Serialize)]
pub struct Config {
pub shortcuts: Shortcuts,
}
Expand Down Expand Up @@ -88,7 +88,18 @@ impl Config {
if format == ConfigFormat::None {
format = Self::guess_format(path);
}
todo!()

match format {
ConfigFormat::Json => {
let r = BufReader::new(File::open(path)?);
Ok(serde_yaml::from_reader(r)?)
}
ConfigFormat::Yaml => {
let r = BufReader::new(File::open(path)?);
Ok(serde_yaml::from_reader(r)?)
}
_ => Err(ConfigError::UnsupportedFormat(format)),
}
}

/// Write to a path
Expand Down
2 changes: 1 addition & 1 deletion src/event/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ pub enum Event {
///
/// The exact mapping between the keyboard and these commands is OS-specific.
/// In the future it should be customisable (see `shortcuts` module).
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, serde::Serialize)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub enum Command {
/// Escape key
///
Expand Down
96 changes: 96 additions & 0 deletions src/event/shortcuts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
use super::{Command, ModifiersState, VirtualKeyCode};
use linear_map::LinearMap;
use serde::de::{self, Deserialize, Deserializer, MapAccess, Unexpected, Visitor};
use serde::ser::{Serialize, SerializeMap, Serializer};
use std::collections::HashMap;
use std::fmt;

/// Shortcut manager
#[derive(Debug)]
Expand Down Expand Up @@ -250,3 +252,97 @@ impl Serialize for Shortcuts {
map.end()
}
}

// #[derive(Error, Debug)]
// pub enum DeError {
// #[error("invalid modifier state: {0}")]
// State(String),
// }

struct ModifierStateVisitor(ModifiersState);
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.",
))
}
}
}

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()))
}
}

struct ShortcutsVisitor;
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 })
}
}

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 33b3feb

Please sign in to comment.