mind_tree/
encoding.rs

1//! Encoding representation of trees and nodes
2
3use serde::{de::Error as _, Deserialize, Serialize};
4use std::path::PathBuf;
5
6#[derive(Clone, Copy, Debug, Eq, PartialEq)]
7pub enum TreeType {
8  /// A root.
9  Root = 0,
10
11  /// A local root.
12  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  /// Protocol version the tree is compatible with.
40  #[serde(default)]
41  pub version: Version,
42
43  /// Type of node.
44  #[serde(rename = "type")]
45  pub ty: TreeType,
46
47  /// A tree is also a node, so we flatten the content of a node when doing deser.
48  #[serde(flatten)]
49  pub node: Node,
50}
51
52#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
53pub struct Node {
54  /// Icon associated with this node.
55  #[serde(default)]
56  pub(crate) icon: String,
57
58  /// Whether the node is expanded or collapsed.
59  #[serde(default)]
60  pub(crate) is_expanded: bool,
61
62  /// Text associated with the node.
63  pub(crate) contents: Vec<Text>,
64
65  /// Data file associated with, if any.
66  #[serde(skip_serializing_if = "Option::is_none")]
67  pub(crate) data: Option<PathBuf>,
68
69  /// Link associated with, if any.
70  #[serde(skip_serializing_if = "Option::is_none")]
71  pub(crate) url: Option<String>,
72
73  /// Children nodes, if any.
74  #[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}