1use serde::{de::Error as _, Deserialize, Serialize};
4use std::path::PathBuf;
5
6#[derive(Clone, Copy, Debug, Eq, PartialEq)]
7pub enum TreeType {
8 Root = 0,
10
11 Local = 1,
13}
14
15impl Serialize for TreeType {
16 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
17 where
18 S: serde::Serializer,
19 {
20 (*self as u8).serialize(serializer)
21 }
22}
23
24impl<'de> Deserialize<'de> for TreeType {
25 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
26 where
27 D: serde::Deserializer<'de>,
28 {
29 match u8::deserialize(deserializer)? {
30 0 => Ok(TreeType::Root),
31 1 => Ok(TreeType::Local),
32 _ => Err(D::Error::custom("nope")),
33 }
34 }
35}
36
37#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
38pub struct Tree {
39 #[serde(default)]
41 pub version: Version,
42
43 #[serde(rename = "type")]
45 pub ty: TreeType,
46
47 #[serde(flatten)]
49 pub node: Node,
50}
51
52#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
53pub struct Node {
54 #[serde(default)]
56 pub(crate) icon: String,
57
58 #[serde(default)]
60 pub(crate) is_expanded: bool,
61
62 pub(crate) contents: Vec<Text>,
64
65 #[serde(skip_serializing_if = "Option::is_none")]
67 pub(crate) data: Option<PathBuf>,
68
69 #[serde(skip_serializing_if = "Option::is_none")]
71 pub(crate) url: Option<String>,
72
73 #[serde(default)]
75 #[serde(skip_serializing_if = "Vec::is_empty")]
76 pub(crate) children: Vec<Node>,
77}
78
79impl Node {
80 #[cfg(test)]
81 pub(crate) fn new_by_expand_state(
82 name: impl Into<String>,
83 is_expanded: bool,
84 children: Vec<Node>,
85 ) -> Self {
86 Self {
87 icon: String::new(),
88 is_expanded,
89 contents: vec![Text { text: name.into() }],
90 data: None,
91 url: None,
92 children,
93 }
94 }
95}
96
97#[derive(Clone, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
98pub struct Version(u16);
99
100impl Version {
101 pub const fn current() -> Self {
102 Version(1)
103 }
104}
105
106impl Default for Version {
107 fn default() -> Self {
108 Version::current()
109 }
110}
111
112#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
113pub struct Text {
114 pub text: String,
115}
116
117#[cfg(test)]
118mod tests {
119 use super::Node;
120
121 #[test]
122 fn serialize() {
123 let s = serde_json::to_string(&Node::new_by_expand_state("name", true, Vec::new()));
124 assert_eq!(
125 s.unwrap(),
126 r#"{"icon":"","is_expanded":true,"contents":[{"text":"name"}]}"#
127 );
128 }
129
130 #[test]
131 fn deserialize() {
132 let s = r#"{"icon":"","is_expanded":true,"contents":[{"text":"name"}]}"#;
133 let node = serde_json::from_str::<Node>(s);
134 assert_eq!(
135 node.unwrap(),
136 Node::new_by_expand_state("name", true, Vec::new())
137 );
138 }
139}