use std::{ops::Deref, sync::Arc}; use arc_swap::ArcSwap; use hashbrown::HashMap; use serde::{Deserialize, Deserializer, de::{self, MapAccess, SeqAccess, Visitor}}; use yazi_codegen::{DeserializeOver, Overlay}; use yazi_shared::SnakeCasedString; use yazi_shim::arc_swap::IntoPointee; use crate::theme::CustomField; #[derive(Debug, Default, DeserializeOver, Overlay)] pub struct CustomSection(ArcSwap>); impl Deref for CustomSection { type Target = ArcSwap>; fn deref(&self) -> &Self::Target { &self.0 } } impl From> for CustomSection { fn from(value: HashMap) -> Self { Self(value.into_pointee()) } } impl CustomSection { pub(super) fn unwrap_unchecked(self) -> HashMap { Arc::try_unwrap(self.0.into_inner()).expect("unique custom section arc") } } impl<'de> Deserialize<'de> for CustomSection { fn deserialize>(de: D) -> Result { struct V; impl<'de> Visitor<'de> for V { type Value = CustomSection; fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.write_str("a style section table or a skippable scalar") } fn visit_map>(self, mut map: M) -> Result { let mut fields = HashMap::with_capacity(map.size_hint().unwrap_or(0)); while let Some(k) = map.next_key::()? { fields.insert(k, map.next_value::()?); } Ok(CustomSection(fields.into_pointee())) } fn visit_bool(self, _: bool) -> Result { Ok(CustomSection::default()) } fn visit_i64(self, _: i64) -> Result { Ok(CustomSection::default()) } fn visit_u64(self, _: u64) -> Result { Ok(CustomSection::default()) } fn visit_f64(self, _: f64) -> Result { Ok(CustomSection::default()) } fn visit_str(self, _: &str) -> Result { Ok(CustomSection::default()) } fn visit_bytes(self, _: &[u8]) -> Result { Ok(CustomSection::default()) } fn visit_none(self) -> Result { Ok(CustomSection::default()) } fn visit_unit(self) -> Result { Ok(CustomSection::default()) } fn visit_some>(self, de: D2) -> Result { CustomSection::deserialize(de) } fn visit_seq>(self, mut seq: A) -> Result { while seq.next_element::()?.is_some() {} Ok(CustomSection::default()) } } de.deserialize_any(V) } }