folder_rev.rs 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. use crate::{TrashRevision, WorkspaceRevision};
  2. use serde::de::{MapAccess, Visitor};
  3. use serde::{de, Deserialize, Deserializer, Serialize};
  4. use std::fmt;
  5. use std::sync::Arc;
  6. #[derive(Debug, Default, Serialize, Clone, Eq, PartialEq)]
  7. pub struct FolderRevision {
  8. pub workspaces: Vec<Arc<WorkspaceRevision>>,
  9. pub trash: Vec<Arc<TrashRevision>>,
  10. }
  11. impl<'de> Deserialize<'de> for FolderRevision {
  12. fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  13. where
  14. D: Deserializer<'de>,
  15. {
  16. struct FolderVisitor<'a>(&'a mut Option<FolderRevision>);
  17. impl<'de, 'a> Visitor<'de> for FolderVisitor<'a> {
  18. type Value = ();
  19. fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
  20. formatter.write_str("Expect struct FolderRevision")
  21. }
  22. fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
  23. where
  24. A: MapAccess<'de>,
  25. {
  26. let f = |map: &mut A,
  27. workspaces: &mut Option<Vec<WorkspaceRevision>>,
  28. trash: &mut Option<Vec<TrashRevision>>| match map.next_key::<String>()
  29. {
  30. Ok(Some(key)) => {
  31. if key == "workspaces" && workspaces.is_none() {
  32. *workspaces = Some(map.next_value::<Vec<WorkspaceRevision>>().ok()?);
  33. }
  34. if key == "trash" && trash.is_none() {
  35. *trash = Some(map.next_value::<Vec<TrashRevision>>().ok()?);
  36. }
  37. Some(())
  38. }
  39. Ok(None) => None,
  40. Err(_e) => None,
  41. };
  42. let mut workspaces: Option<Vec<WorkspaceRevision>> = None;
  43. let mut trash: Option<Vec<TrashRevision>> = None;
  44. while f(&mut map, &mut workspaces, &mut trash).is_some() {
  45. if workspaces.is_some() && trash.is_some() {
  46. break;
  47. }
  48. }
  49. *self.0 = Some(FolderRevision {
  50. workspaces: workspaces.unwrap_or_default().into_iter().map(Arc::new).collect(),
  51. trash: trash.unwrap_or_default().into_iter().map(Arc::new).collect(),
  52. });
  53. Ok(())
  54. }
  55. }
  56. let mut folder_rev: Option<FolderRevision> = None;
  57. const FIELDS: &[&str] = &["workspaces", "trash"];
  58. let _ = serde::Deserializer::deserialize_struct(
  59. deserializer,
  60. "FolderRevision",
  61. FIELDS,
  62. FolderVisitor(&mut folder_rev),
  63. );
  64. match folder_rev {
  65. None => Err(de::Error::missing_field("workspaces or trash")),
  66. Some(folder_rev) => Ok(folder_rev),
  67. }
  68. }
  69. }