use crate::{TrashRevision, WorkspaceRevision}; use serde::de::{MapAccess, Visitor}; use serde::{de, Deserialize, Deserializer, Serialize}; use std::fmt; use std::sync::Arc; #[derive(Debug, Default, Serialize, Clone, Eq, PartialEq)] pub struct FolderRevision { pub workspaces: Vec>, pub trash: Vec>, } impl<'de> Deserialize<'de> for FolderRevision { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct FolderVisitor<'a>(&'a mut Option); impl<'de, 'a> Visitor<'de> for FolderVisitor<'a> { type Value = (); fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Expect struct FolderRevision") } fn visit_map(self, mut map: A) -> Result where A: MapAccess<'de>, { let f = |map: &mut A, workspaces: &mut Option>, trash: &mut Option>| match map.next_key::() { Ok(Some(key)) => { if key == "workspaces" && workspaces.is_none() { *workspaces = Some(map.next_value::>().ok()?); } if key == "trash" && trash.is_none() { *trash = Some(map.next_value::>().ok()?); } Some(()) } Ok(None) => None, Err(_e) => None, }; let mut workspaces: Option> = None; let mut trash: Option> = None; while f(&mut map, &mut workspaces, &mut trash).is_some() { if workspaces.is_some() && trash.is_some() { break; } } *self.0 = Some(FolderRevision { workspaces: workspaces.unwrap_or_default().into_iter().map(Arc::new).collect(), trash: trash.unwrap_or_default().into_iter().map(Arc::new).collect(), }); Ok(()) } } let mut folder_rev: Option = None; const FIELDS: &[&str] = &["workspaces", "trash"]; let _ = serde::Deserializer::deserialize_struct( deserializer, "FolderRevision", FIELDS, FolderVisitor(&mut folder_rev), ); match folder_rev { None => Err(de::Error::missing_field("workspaces or trash")), Some(folder_rev) => Ok(folder_rev), } } }