1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//! Serializing `indextree` structure.
//!
//! ## Version support
//!
//! | `indextree` version | `serde_indextree` version |
//! |---------------------|---------------------------|
//! | 3.3.x               | 0.1.x                     |
//! | 4.0.x               | 0.2.x                     |
//!
//! ## Usage
//!
//! `serde_indextree` provides two struct: `Node` for serializing
//! a node and its descendants, `SiblingNodes` for serializing a
//! node and its siblings in sequence.
//!
//! ```rust
//! use indextree::Arena;
//! use serde::Serialize;
//! use serde_indextree::Node;
//! use serde_json::to_string_pretty;
//!
//! #[derive(Serialize)]
//! struct HtmlElement {
//!     tag: &'static str
//! }
//!
//! // <html>
//! // <head>
//! //     <title></title>
//! // <head>
//! // <body>
//! //     <h1></h1>
//! //     <h2></h2>
//! // </body>
//! // </html>
//! let arena = &mut Arena::new();
//! let a = arena.new_node(HtmlElement { tag: "html" });
//! let b = arena.new_node(HtmlElement { tag: "head" });
//! a.append(b, arena);
//! let c = arena.new_node(HtmlElement { tag: "title" });
//! b.append(c, arena);
//! let d = arena.new_node(HtmlElement { tag: "body" });
//! a.append(d, arena);
//! let e = arena.new_node(HtmlElement { tag: "h1" });
//! d.append(e, arena);
//! let f = arena.new_node(HtmlElement { tag: "h2" });
//! d.append(f, arena);
//!
//! println!("{}", to_string_pretty(&Node::new(a, arena)).unwrap());
//! // {
//! //   "tag": "html",
//! //   "children": [
//! //     {
//! //       "tag": "head",
//! //       "children": [
//! //         {
//! //           "tag": "title"
//! //         }
//! //       ]
//! //     },
//! //     {
//! //       "tag": "body",
//! //       "children": [
//! //         {
//! //           "tag": "h1"
//! //         },
//! //         {
//! //           "tag": "h2"
//! //         }
//! //       ]
//! //     }
//! //   ]
//! // }
//! ```
//!
//! ## Customization
//!
//! Unfortunately, `serde_indextree` doesn't come up with any customization.
//!
//! If you want to rename field names or anything, just copy the entire code
//! (only 40+ lines) and modify it at your wish.
//!
//! ## License
//!
//! MIT

use indextree::{Arena, NodeId};
use serde::ser::{SerializeSeq, Serializer};
use serde::Serialize;

/// Convenience wrapper struct for serializing a node and its descendants.
#[derive(Serialize)]
pub struct Node<'a, T: Serialize> {
    #[serde(flatten)]
    data: &'a T,
    #[serde(skip_serializing_if = "Option::is_none")]
    children: Option<SiblingNodes<'a, T>>,
}

impl<'a, T: Serialize> Node<'a, T> {
    pub fn new(id: NodeId, arena: &'a Arena<T>) -> Self {
        let node = &arena[id];
        Node {
            data: &node.get(),
            children: node
                .first_child()
                .map(|first| SiblingNodes::new(first, arena)),
        }
    }
}

/// Convenience wrapper struct for serializing a node and its siblings.
pub struct SiblingNodes<'a, T: Serialize> {
    first: NodeId,
    arena: &'a Arena<T>,
}

impl<'a, T: Serialize> SiblingNodes<'a, T> {
    pub fn new(id: NodeId, arena: &'a Arena<T>) -> Self {
        SiblingNodes { first: id, arena }
    }
}

impl<T: Serialize> Serialize for SiblingNodes<'_, T> {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        let mut seq = serializer.serialize_seq(None)?;
        for node in self.first.following_siblings(&self.arena) {
            seq.serialize_element(&Node::new(node, &self.arena))?;
        }
        seq.end()
    }
}