From 6a1ddb71e018f2ec4bb40963c84506e55c26983c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E9=9B=85=20misaki=20masa?= Date: Wed, 18 Mar 2026 14:13:23 +0800 Subject: [PATCH] feat: deserialize from `Data` (#3778) --- yazi-shared/src/data/data.rs | 233 ------------------------ yazi-shared/src/data/de.rs | 342 +++++++++++++++++++++++++++++++++++ yazi-shared/src/data/mod.rs | 2 +- 3 files changed, 343 insertions(+), 234 deletions(-) create mode 100644 yazi-shared/src/data/de.rs diff --git a/yazi-shared/src/data/data.rs b/yazi-shared/src/data/data.rs index 4453c0e4..b14346b9 100644 --- a/yazi-shared/src/data/data.rs +++ b/yazi-shared/src/data/data.rs @@ -242,239 +242,6 @@ impl Data { } } -impl<'de> serde::Deserializer<'de> for &Data { - type Error = serde::de::value::Error; - - fn deserialize_any(self, _visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - Err(serde::de::Error::custom("any not supported")) - } - - fn deserialize_bool(self, visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - visitor.visit_bool(self.try_into().map_err(serde::de::Error::custom)?) - } - - fn deserialize_i8(self, visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - visitor.visit_i8(self.try_into().map_err(serde::de::Error::custom)?) - } - - fn deserialize_i16(self, visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - visitor.visit_i16(self.try_into().map_err(serde::de::Error::custom)?) - } - - fn deserialize_i32(self, visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - visitor.visit_i32(self.try_into().map_err(serde::de::Error::custom)?) - } - - fn deserialize_i64(self, visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - visitor.visit_i64(self.try_into().map_err(serde::de::Error::custom)?) - } - - fn deserialize_u8(self, visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - visitor.visit_u8(self.try_into().map_err(serde::de::Error::custom)?) - } - - fn deserialize_u16(self, visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - visitor.visit_u16(self.try_into().map_err(serde::de::Error::custom)?) - } - - fn deserialize_u32(self, visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - visitor.visit_u32(self.try_into().map_err(serde::de::Error::custom)?) - } - - fn deserialize_u64(self, visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - visitor.visit_u64(self.try_into().map_err(serde::de::Error::custom)?) - } - - fn deserialize_f32(self, visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - visitor.visit_f32(self.try_into().map_err(serde::de::Error::custom)?) - } - - fn deserialize_f64(self, visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - visitor.visit_f64(self.try_into().map_err(serde::de::Error::custom)?) - } - - fn deserialize_char(self, _visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - Err(serde::de::Error::custom("not a char")) - } - - fn deserialize_str(self, visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - visitor.visit_str(self.try_into().map_err(serde::de::Error::custom)?) - } - - fn deserialize_string(self, _visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - Err(serde::de::Error::custom("string not supported")) - } - - fn deserialize_bytes(self, visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - visitor.visit_bytes(self.try_into().map_err(serde::de::Error::custom)?) - } - - fn deserialize_byte_buf(self, _visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - Err(serde::de::Error::custom("byte buf not supported")) - } - - fn deserialize_option(self, visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - match self { - Data::Nil => visitor.visit_none(), - _ => visitor.visit_some(self), - } - } - - fn deserialize_unit(self, visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - visitor.visit_unit() - } - - fn deserialize_unit_struct( - self, - _name: &'static str, - visitor: V, - ) -> Result - where - V: serde::de::Visitor<'de>, - { - visitor.visit_unit() - } - - fn deserialize_newtype_struct( - self, - _name: &'static str, - visitor: V, - ) -> Result - where - V: serde::de::Visitor<'de>, - { - visitor.visit_newtype_struct(self) - } - - fn deserialize_seq(self, _visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - Err(serde::de::Error::custom("seq not supported")) - } - - fn deserialize_tuple(self, _len: usize, _visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - Err(serde::de::Error::custom("tuple not supported")) - } - - fn deserialize_tuple_struct( - self, - _name: &'static str, - _len: usize, - _visitor: V, - ) -> Result - where - V: serde::de::Visitor<'de>, - { - Err(serde::de::Error::custom("tuple struct not supported")) - } - - fn deserialize_map(self, _visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - Err(serde::de::Error::custom("map not supported")) - } - - fn deserialize_struct( - self, - _name: &'static str, - _fields: &'static [&'static str], - _visitor: V, - ) -> Result - where - V: serde::de::Visitor<'de>, - { - Err(serde::de::Error::custom("struct not supported")) - } - - fn deserialize_enum( - self, - _name: &'static str, - _variants: &'static [&'static str], - _visitor: V, - ) -> Result - where - V: serde::de::Visitor<'de>, - { - Err(serde::de::Error::custom("enum not supported")) - } - - fn deserialize_identifier(self, _visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - Err(serde::de::Error::custom("identifier not supported")) - } - - fn deserialize_ignored_any(self, _visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - Err(serde::de::Error::custom("ignored any not supported")) - } -} - // --- Macros macro_rules! impl_into_integer { ($t:ty) => { diff --git a/yazi-shared/src/data/de.rs b/yazi-shared/src/data/de.rs new file mode 100644 index 00000000..46b10919 --- /dev/null +++ b/yazi-shared/src/data/de.rs @@ -0,0 +1,342 @@ +use serde::de::{Error, IntoDeserializer, MapAccess, SeqAccess}; + +use crate::data::{Data, DataKey}; + +impl<'de> serde::Deserializer<'de> for &Data { + type Error = serde::de::value::Error; + + fn deserialize_any(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + match self { + Data::Nil => visitor.visit_unit(), + Data::Boolean(b) => visitor.visit_bool(*b), + Data::Integer(i) => visitor.visit_i64(*i), + Data::Number(n) => visitor.visit_f64(*n), + Data::String(s) => visitor.visit_str(s), + Data::List(l) => visitor.visit_seq(DataSeqAccess { iter: l.iter() }), + Data::Dict(d) => visitor.visit_map(DataMapAccess { iter: d.iter(), value: None }), + Data::Id(i) => visitor.visit_u64(i.get()), + Data::Url(_) => Err(Error::custom("url not supported")), + Data::Path(_) => Err(Error::custom("path not supported")), + Data::Bytes(b) => visitor.visit_bytes(b), + Data::Any(_) => Err(Error::custom("any not supported")), + } + } + + fn deserialize_bool(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_bool(self.try_into().map_err(Error::custom)?) + } + + fn deserialize_i8(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_i8(self.try_into().map_err(Error::custom)?) + } + + fn deserialize_i16(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_i16(self.try_into().map_err(Error::custom)?) + } + + fn deserialize_i32(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_i32(self.try_into().map_err(Error::custom)?) + } + + fn deserialize_i64(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_i64(self.try_into().map_err(Error::custom)?) + } + + fn deserialize_u8(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_u8(self.try_into().map_err(Error::custom)?) + } + + fn deserialize_u16(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_u16(self.try_into().map_err(Error::custom)?) + } + + fn deserialize_u32(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_u32(self.try_into().map_err(Error::custom)?) + } + + fn deserialize_u64(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_u64(self.try_into().map_err(Error::custom)?) + } + + fn deserialize_f32(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_f32(self.try_into().map_err(Error::custom)?) + } + + fn deserialize_f64(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_f64(self.try_into().map_err(Error::custom)?) + } + + fn deserialize_char(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + let s: &str = self.try_into().map_err(Error::custom)?; + let mut chars = s.chars(); + match (chars.next(), chars.next()) { + (Some(ch), None) => visitor.visit_char(ch), + _ => Err(Error::custom("not a char")), + } + } + + fn deserialize_str(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_str(self.try_into().map_err(Error::custom)?) + } + + fn deserialize_string(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + let s: &str = self.try_into().map_err(Error::custom)?; + visitor.visit_string(s.to_owned()) + } + + fn deserialize_bytes(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_bytes(self.try_into().map_err(Error::custom)?) + } + + fn deserialize_byte_buf(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + let bytes: &[u8] = self.try_into().map_err(Error::custom)?; + visitor.visit_byte_buf(bytes.to_vec()) + } + + fn deserialize_option(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + match self { + Data::Nil => visitor.visit_none(), + _ => visitor.visit_some(self), + } + } + + fn deserialize_unit(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + match self { + Data::Nil => visitor.visit_unit(), + _ => Err(Error::custom("expected unit")), + } + } + + fn deserialize_unit_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result + where + V: serde::de::Visitor<'de>, + { + match self { + Data::Nil => visitor.visit_unit(), + _ => Err(Error::custom("expected unit struct")), + } + } + + fn deserialize_newtype_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_newtype_struct(self) + } + + fn deserialize_seq(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + match self { + Data::List(l) => visitor.visit_seq(DataSeqAccess { iter: l.iter() }), + Data::Bytes(b) => visitor.visit_seq(DataByteSeqAccess { iter: b.iter() }), + _ => Err(Error::custom("not a sequence")), + } + } + + fn deserialize_tuple(self, _len: usize, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + fn deserialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + visitor: V, + ) -> Result + where + V: serde::de::Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + fn deserialize_map(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + if let Data::Dict(d) = self { + visitor.visit_map(DataMapAccess { iter: d.iter(), value: None }) + } else { + Err(Error::custom("not a map")) + } + } + + fn deserialize_struct( + self, + _name: &'static str, + _fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: serde::de::Visitor<'de>, + { + self.deserialize_map(visitor) + } + + fn deserialize_enum( + self, + _name: &'static str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: serde::de::Visitor<'de>, + { + match self { + Data::String(s) => visitor.visit_enum((&**s).into_deserializer()), + _ => Err(Error::custom("not an enum")), + } + } + + fn deserialize_identifier(self, _visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + Err(Error::custom("identifier not supported")) + } + + fn deserialize_ignored_any(self, _visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + Err(Error::custom("ignored any not supported")) + } +} + +struct DataSeqAccess<'a> { + iter: std::slice::Iter<'a, Data>, +} + +impl<'de> SeqAccess<'de> for DataSeqAccess<'_> { + type Error = serde::de::value::Error; + + fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> + where + T: serde::de::DeserializeSeed<'de>, + { + self.iter.next().map(|value| seed.deserialize(value)).transpose() + } + + fn size_hint(&self) -> Option { Some(self.iter.len()) } +} + +struct DataByteSeqAccess<'a> { + iter: std::slice::Iter<'a, u8>, +} + +impl<'de> SeqAccess<'de> for DataByteSeqAccess<'_> { + type Error = serde::de::value::Error; + + fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> + where + T: serde::de::DeserializeSeed<'de>, + { + self.iter.next().map(|value| seed.deserialize((*value).into_deserializer())).transpose() + } + + fn size_hint(&self) -> Option { Some(self.iter.len()) } +} + +struct DataMapAccess<'a> { + iter: hashbrown::hash_map::Iter<'a, DataKey, Data>, + value: Option<&'a Data>, +} + +impl<'de> MapAccess<'de> for DataMapAccess<'_> { + type Error = serde::de::value::Error; + + fn next_key_seed(&mut self, seed: K) -> Result, Self::Error> + where + K: serde::de::DeserializeSeed<'de>, + { + let Some((key, value)) = self.iter.next() else { return Ok(None) }; + self.value = Some(value); + + match key { + DataKey::Boolean(b) => seed.deserialize((*b).into_deserializer()).map(Some), + DataKey::Integer(i) => seed.deserialize((*i).into_deserializer()).map(Some), + DataKey::Number(n) => seed.deserialize((*n).into_deserializer()).map(Some), + DataKey::String(s) => seed.deserialize((&**s).into_deserializer()).map(Some), + DataKey::Id(id) => seed.deserialize(id.get().into_deserializer()).map(Some), + _ => Err(Error::custom("unsupported map key type")), + } + } + + fn next_value_seed(&mut self, seed: V) -> Result + where + V: serde::de::DeserializeSeed<'de>, + { + seed.deserialize(self.value.take().ok_or_else(|| Error::custom("value missing for key"))?) + } + + fn size_hint(&self) -> Option { Some(self.iter.len()) } +} diff --git a/yazi-shared/src/data/mod.rs b/yazi-shared/src/data/mod.rs index 67f01151..ca7fb9d8 100644 --- a/yazi-shared/src/data/mod.rs +++ b/yazi-shared/src/data/mod.rs @@ -1 +1 @@ -yazi_macro::mod_flat!(any data key); +yazi_macro::mod_flat!(any data de key);