瀏覽代碼

more resilient keyboard event deserialization

Evan Almloff 2 年之前
父節點
當前提交
1cc4260f70
共有 1 個文件被更改,包括 33 次插入6 次删除
  1. 33 6
      packages/html/src/events/keyboard.rs

+ 33 - 6
packages/html/src/events/keyboard.rs

@@ -5,6 +5,16 @@ use std::convert::TryInto;
 use std::fmt::{Debug, Formatter};
 use std::str::FromStr;
 
+#[cfg(feature = "serialize")]
+fn resilient_deserialize_code<'de, D>(deserializer: D) -> Result<Code, D::Error>
+where
+    D: serde::Deserializer<'de>,
+{
+    use serde::Deserialize;
+    // If we fail to deserialize the code for any reason, just return Unidentified instead of failing.
+    Ok(Code::deserialize(deserializer).unwrap_or(Code::Unidentified))
+}
+
 pub type KeyboardEvent = Event<KeyboardData>;
 #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
 #[derive(Clone, PartialEq, Eq)]
@@ -27,6 +37,10 @@ pub struct KeyboardData {
     pub key_code: KeyCode,
 
     /// the physical key on the keyboard
+    #[cfg_attr(
+        feature = "serialize",
+        serde(deserialize_with = "resilient_deserialize_code")
+    )]
     code: Code,
 
     /// Indicate if the `alt` modifier key was pressed during this keyboard event
@@ -102,7 +116,7 @@ impl KeyboardData {
     /// The value of the key pressed by the user, taking into consideration the state of modifier keys such as Shift as well as the keyboard locale and layout.
     pub fn key(&self) -> Key {
         #[allow(deprecated)]
-        FromStr::from_str(&self.key).expect("could not parse")
+        FromStr::from_str(&self.key).unwrap_or(Key::Unidentified)
     }
 
     /// A physical key on the keyboard (as opposed to the character generated by pressing the key). In other words, this property returns a value that isn't altered by keyboard layout or the state of the modifier keys.
@@ -158,10 +172,24 @@ impl Debug for KeyboardData {
     }
 }
 
-#[cfg_attr(
-    feature = "serialize",
-    derive(serde_repr::Serialize_repr, serde_repr::Deserialize_repr)
-)]
+#[cfg(feature = "serialize")]
+impl<'de> serde::Deserialize<'de> for KeyCode {
+    fn deserialize<D>(deserializer: D) -> Result<KeyCode, D::Error>
+    where
+        D: serde::Deserializer<'de>,
+    {
+        // We could be deserializing a unicode character, so we need to use u64 even if the output only takes u8
+        let value = u64::deserialize(deserializer)?;
+
+        if let Ok(smaller_uint) = value.try_into() {
+            Ok(KeyCode::from_raw_code(smaller_uint))
+        } else {
+            Ok(KeyCode::Unknown)
+        }
+    }
+}
+
+#[cfg_attr(feature = "serialize", derive(serde_repr::Serialize_repr))]
 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
 #[repr(u8)]
 pub enum KeyCode {
@@ -525,7 +553,6 @@ pub enum KeyCode {
     // kanji, = 244
     // unlock trackpad (Chrome/Edge), = 251
     // toggle touchpad, = 255
-    #[cfg_attr(feature = "serialize", serde(other))]
     Unknown,
 }