Skip to content

Commit

Permalink
feat: add serde (#75)
Browse files Browse the repository at this point in the history
* feat: add `serde`

* into_string
  • Loading branch information
amrbashir authored Apr 24, 2024
1 parent cd9051d commit a468ede
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 24 deletions.
5 changes: 5 additions & 0 deletions .changes/serde.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"global-hotkey": "patch"
---

Add `serde` feature flag and implement `Deserialize` and `Serialize` for `GlobalHotKeyEvent`, `HotKeyState` and `HotKey` types.
5 changes: 5 additions & 0 deletions .changes/to_string.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"global-hotkey": "patch"
---

Add `HotKey::into_string` method and implement `Display` for `HotKey`.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ jobs:
sudo apt-get install -y libgtk-3-dev libxdo-dev
- uses: dtolnay/rust-toolchain@stable
- run: cargo test
- run: cargo test --all-features
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,15 @@ repository = "https://github.com/amrbashir/global-hotkey"
documentation = "https://docs.rs/global-hotkey"
categories = [ "gui" ]

[features]
serde = [ "dep:serde" ]

[dependencies]
crossbeam-channel = "0.5"
keyboard-types = "0.7"
once_cell = "1"
thiserror = "1"
serde = { version = "1", optional = true, features = ["derive"] }

[target."cfg(target_os = \"macos\")".dependencies]
bitflags = "2"
Expand Down
83 changes: 60 additions & 23 deletions src/hotkey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
//!

pub use keyboard_types::{Code, Modifiers};
use std::{borrow::Borrow, hash::Hash, str::FromStr};
use std::{borrow::Borrow, fmt::Display, hash::Hash, str::FromStr};

#[cfg(target_os = "macos")]
pub const CMD_OR_CTRL: Modifiers = Modifiers::SUPER;
Expand All @@ -50,9 +50,35 @@ pub enum HotKeyParseError {
/// one key ([`Code`](crate::hotkey::Code)).
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct HotKey {
pub(crate) mods: Modifiers,
pub(crate) key: Code,
id: u32,
/// The hotkey modifiers.
pub mods: Modifiers,
/// The hotkey key.
pub key: Code,
/// The hotkey id.
pub id: u32,
}

#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for HotKey {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let hotkey = String::deserialize(deserializer)?;
hotkey
.parse()
.map_err(|e: HotKeyParseError| serde::de::Error::custom(e.to_string()))
}
}

#[cfg(feature = "serde")]
impl serde::Serialize for HotKey {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.to_string().serialize(serializer)
}
}

impl HotKey {
Expand All @@ -65,27 +91,13 @@ impl HotKey {
mods.insert(Modifiers::SUPER);
}

let id = Self::generate_hash(mods, key);

Self { mods, key, id }
let mut hotkey = Self { mods, key, id: 0 };
hotkey.id = hotkey.generate_hash();
hotkey
}

fn generate_hash(mods: Modifiers, key: Code) -> u32 {
let mut hotkey_str = String::new();
if mods.contains(Modifiers::SHIFT) {
hotkey_str.push_str("shift+")
}
if mods.contains(Modifiers::CONTROL) {
hotkey_str.push_str("control+")
}
if mods.contains(Modifiers::ALT) {
hotkey_str.push_str("alt+")
}
if mods.contains(Modifiers::SUPER) {
hotkey_str.push_str("super+")
}
hotkey_str.push_str(&key.to_string());

fn generate_hash(&self) -> u32 {
let hotkey_str = self.into_string();
let mut hasher = std::collections::hash_map::DefaultHasher::new();
hotkey_str.hash(&mut hasher);
std::hash::Hasher::finish(&hasher) as u32
Expand All @@ -105,6 +117,31 @@ impl HotKey {
let key = key.borrow();
self.mods == *modifiers & base_mods && self.key == *key
}

/// Converts this hotkey into a string.
pub fn into_string(self) -> String {
let mut hotkey = String::new();
if self.mods.contains(Modifiers::SHIFT) {
hotkey.push_str("shift+")
}
if self.mods.contains(Modifiers::CONTROL) {
hotkey.push_str("control+")
}
if self.mods.contains(Modifiers::ALT) {
hotkey.push_str("alt+")
}
if self.mods.contains(Modifiers::SUPER) {
hotkey.push_str("super+")
}
hotkey.push_str(&self.key.to_string());
hotkey
}
}

impl Display for HotKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.into_string())
}
}

// HotKey::from_str is available to be backward
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ use hotkey::HotKey;

/// Describes the state of the [`HotKey`].
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum HotKeyState {
/// The [`HotKey`] is pressed (the key is down).
Pressed,
Expand All @@ -71,6 +72,7 @@ pub enum HotKeyState {

/// Describes a global hotkey event emitted when a [`HotKey`] is pressed or released.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct GlobalHotKeyEvent {
/// Id of the associated [`HotKey`].
pub id: u32,
Expand Down

0 comments on commit a468ede

Please sign in to comment.