inlyne 0.5.1

Introducing Inlyne, a GPU powered yet browserless tool to help you quickly view markdown files in the blink of an eye.
use std::str::FromStr;

use crate::keybindings::action::HistDirection;

use super::action::{Action, VertDirection, Zoom};
use super::{Key, KeyCombo, ModifiedKey};

use serde::{de, Deserialize, Deserializer};
use winit::event::{ModifiersState, VirtualKeyCode as VirtKey};

impl<'de> Deserialize<'de> for Action {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        #[derive(Deserialize)]
        enum FlatAction {
            HistoryNext,
            HistoryPrevious,
            ToTop,
            ToBottom,
            ScrollUp,
            ScrollDown,
            PageUp,
            PageDown,
            ZoomIn,
            ZoomOut,
            ZoomReset,
            Copy,
            Quit,
        }

        let action = match FlatAction::deserialize(deserializer)? {
            FlatAction::HistoryNext => Action::History(HistDirection::Next),
            FlatAction::HistoryPrevious => Action::History(HistDirection::Prev),
            FlatAction::ToTop => Action::ToEdge(VertDirection::Up),
            FlatAction::ToBottom => Action::ToEdge(VertDirection::Down),
            FlatAction::ScrollUp => Action::Scroll(VertDirection::Up),
            FlatAction::ScrollDown => Action::Scroll(VertDirection::Down),
            FlatAction::PageUp => Action::Page(VertDirection::Up),
            FlatAction::PageDown => Action::Page(VertDirection::Down),
            FlatAction::ZoomIn => Action::Zoom(Zoom::In),
            FlatAction::ZoomOut => Action::Zoom(Zoom::Out),
            FlatAction::ZoomReset => Action::Zoom(Zoom::Reset),
            FlatAction::Copy => Action::Copy,
            FlatAction::Quit => Action::Quit,
        };

        Ok(action)
    }
}

impl<'de> Deserialize<'de> for Key {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        #[derive(Deserialize)]
        #[serde(untagged)]
        enum StringOrNum {
            Str(String),
            Num(u32),
        }

        match StringOrNum::deserialize(deserializer)? {
            StringOrNum::Str(s) => Key::from_str(&s).map_err(de::Error::custom),
            StringOrNum::Num(num) => Ok(Self::ScanCode(num)),
        }
    }
}

struct ShortKey {
    key: Key,
    shift: bool,
}

impl<'de> Deserialize<'de> for ShortKey {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        #[derive(Deserialize)]
        #[serde(untagged)]
        enum StringOrNum {
            Str(String),
            Num(u32),
        }

        let shifted_key = |virt_key| {
            Ok(Self {
                key: Key::Resolved(virt_key),
                shift: true,
            })
        };

        match StringOrNum::deserialize(deserializer)? {
            StringOrNum::Str(s) => match &*s {
                "A" => shifted_key(VirtKey::A),
                "B" => shifted_key(VirtKey::B),
                "C" => shifted_key(VirtKey::C),
                "D" => shifted_key(VirtKey::D),
                "E" => shifted_key(VirtKey::E),
                "F" => shifted_key(VirtKey::F),
                "G" => shifted_key(VirtKey::G),
                "H" => shifted_key(VirtKey::H),
                "I" => shifted_key(VirtKey::I),
                "J" => shifted_key(VirtKey::J),
                "K" => shifted_key(VirtKey::K),
                "L" => shifted_key(VirtKey::L),
                "M" => shifted_key(VirtKey::M),
                "N" => shifted_key(VirtKey::N),
                "O" => shifted_key(VirtKey::O),
                "P" => shifted_key(VirtKey::P),
                "Q" => shifted_key(VirtKey::Q),
                "R" => shifted_key(VirtKey::R),
                "S" => shifted_key(VirtKey::S),
                "T" => shifted_key(VirtKey::T),
                "U" => shifted_key(VirtKey::U),
                "V" => shifted_key(VirtKey::V),
                "W" => shifted_key(VirtKey::W),
                "X" => shifted_key(VirtKey::X),
                "Y" => shifted_key(VirtKey::Y),
                "Z" => shifted_key(VirtKey::Z),
                other => match Key::from_str(other) {
                    Ok(key) => Ok(Self { key, shift: false }),
                    Err(err) => Err(de::Error::custom(err)),
                },
            },
            StringOrNum::Num(num) => Ok(Self {
                key: Key::ScanCode(num),
                shift: false,
            }),
        }
    }
}

impl<'de> Deserialize<'de> for ModifiedKey {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        #[derive(Deserialize)]
        enum ModifierType {
            Alt,
            Ctrl,
            Os,
            Shift,
        }

        #[derive(Deserialize)]
        #[serde(untagged)]
        enum ModOrMods {
            Mod(ModifierType),
            Mods(Vec<ModifierType>),
        }

        #[derive(Deserialize)]
        struct Inner {
            key: ShortKey,
            #[serde(rename = "mod")]
            mod_: ModOrMods,
        }

        #[derive(Deserialize)]
        #[serde(untagged)]
        enum KeyOrModifiedKey {
            Key(ShortKey),
            ModifiedKey(Inner),
        }

        Ok(match KeyOrModifiedKey::deserialize(deserializer)? {
            KeyOrModifiedKey::Key(ShortKey { key, shift }) => {
                let mut mods = ModifiersState::empty();
                if shift {
                    mods |= ModifiersState::SHIFT;
                }
                ModifiedKey(key, mods)
            }
            KeyOrModifiedKey::ModifiedKey(Inner {
                key: ShortKey { key, shift },
                mod_,
            }) => {
                let mut modifiers = ModifiersState::empty();
                let mod_ = match mod_ {
                    ModOrMods::Mod(m) => vec![m],
                    ModOrMods::Mods(mods) => mods,
                };
                for ty in mod_ {
                    modifiers |= match ty {
                        ModifierType::Alt => ModifiersState::ALT,
                        ModifierType::Ctrl => ModifiersState::CTRL,
                        ModifierType::Os => ModifiersState::LOGO,
                        ModifierType::Shift => ModifiersState::SHIFT,
                    };
                }
                if shift {
                    modifiers |= ModifiersState::SHIFT;
                }

                ModifiedKey(key, modifiers)
            }
        })
    }
}

impl<'de> Deserialize<'de> for KeyCombo {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        #[derive(Deserialize)]
        #[serde(untagged)]
        enum ModifiedKeyOrModifiedKeys {
            Key(ModifiedKey),
            Keys(Vec<ModifiedKey>),
        }

        let keys = match ModifiedKeyOrModifiedKeys::deserialize(deserializer)? {
            ModifiedKeyOrModifiedKeys::Key(key) => vec![key],
            ModifiedKeyOrModifiedKeys::Keys(keys) => keys,
        };

        Ok(KeyCombo(keys))
    }
}