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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
use downcast_rs::{impl_downcast, Downcast};
use std::any::TypeId;
use std::fmt::Debug;

use crate::common::sourcemap::SourcePos;
use crate::common::TypeKey;
use crate::parser::extset::NodeExtSet;
use crate::parser::inline::Text;
use crate::parser::renderer::HTMLRenderer;
use crate::Renderer;

/// Single node in the CommonMark AST.
#[derive(Debug)]
#[readonly::make]
pub struct Node {
    /// Array of child nodes.
    pub children: Vec<Node>,

    /// Source mapping info.
    pub srcmap: Option<SourcePos>,

    /// Custom data specific to this token.
    pub ext: NodeExtSet,

    /// Additional attributes to be added to resulting html.
    pub attrs: Vec<(&'static str, String)>,

    /// Type name, used for debugging.
    #[readonly]
    pub node_type: TypeKey,

    /// Storage for arbitrary token-specific data.
    #[readonly]
    pub node_value: Box<dyn NodeValue>,
}

impl Node {
    /// Create a new [Node](Node) with a custom value.
    pub fn new<T: NodeValue>(value: T) -> Self {
        Self {
            children:   Vec::new(),
            srcmap:     None,
            attrs:      Vec::new(),
            ext:        NodeExtSet::new(),
            node_type:  TypeKey::of::<T>(),
            node_value: Box::new(value),
        }
    }

    /// Return std::any::type_name() of node value.
    pub fn name(&self) -> &'static str {
        self.node_type.name
    }

    /// Check that this node value is of given type.
    pub fn is<T: NodeValue>(&self) -> bool {
        self.node_type.id == TypeId::of::<T>()
    }

    /// Downcast node value to specific type.
    pub fn cast<T: NodeValue>(&self) -> Option<&T> {
        if self.node_type.id == TypeId::of::<T>() {
            Some(self.node_value.downcast_ref::<T>().unwrap())
            // performance note: `node_type.id` improves walk speed by a LOT by removing indirection
            // (~5% of overall program speed), so having type id duplicated in Node is very beneficial;
            // we can also remove extra check with downcast_unchecked, but it doesn't do much
            //Some(unsafe { &*(&*self.node_value as *const dyn NodeValue as *const T) })
        } else {
            None
        }
    }

    /// Downcast node value to specific type.
    pub fn cast_mut<T: NodeValue>(&mut self) -> Option<&mut T> {
        if self.node_type.id == TypeId::of::<T>() {
            Some(self.node_value.downcast_mut::<T>().unwrap())
            // performance note: see above
            //Some(unsafe { &mut *(&mut *self.node_value as *mut dyn NodeValue as *mut T) })
        } else {
            None
        }
    }

    /// Render this node to HTML.
    pub fn render(&self) -> String {
        let mut fmt = HTMLRenderer::<false>::new();
        fmt.render(self);
        fmt.into()
    }

    /// Render this node to XHTML, it adds slash to self-closing tags like this: `<img />`.
    ///
    /// This mode exists for compatibility with CommonMark tests.
    pub fn xrender(&self) -> String {
        let mut fmt = HTMLRenderer::<true>::new();
        fmt.render(self);
        fmt.into()
    }

    /// Replace custom value with another value (this is roughly equivalent
    /// to replacing the entire node and copying children and sourcemaps).
    pub fn replace<T: NodeValue>(&mut self, value: T) {
        self.node_type  = TypeKey::of::<T>();
        self.node_value = Box::new(value);
    }

    /// Execute function `f` recursively on every member of AST tree
    /// (using preorder deep-first search).
    pub fn walk<'a>(&'a self, mut f: impl FnMut(&'a Node, u32)) {
        // performance note: this is faster than emulating recursion using vec stack
        fn walk_recursive<'b>(node: &'b Node, depth: u32, f: &mut impl FnMut(&'b Node, u32)) {
            f(node, depth);
            for n in node.children.iter() {
                stacker::maybe_grow(64*1024, 1024*1024, || {
                    walk_recursive(n, depth + 1, f);
                });
            }
        }

        walk_recursive(self, 0, &mut f);
    }

    /// Execute function `f` recursively on every member of AST tree
    /// (using preorder deep-first search).
    pub fn walk_mut(&mut self, mut f: impl FnMut(&mut Node, u32)) {
        // performance note: this is faster than emulating recursion using vec stack
        fn walk_recursive(node: &mut Node, depth: u32, f: &mut impl FnMut(&mut Node, u32)) {
            f(node, depth);
            for n in node.children.iter_mut() {
                stacker::maybe_grow(64*1024, 1024*1024, || {
                    walk_recursive(n, depth + 1, f);
                });
            }
        }

        walk_recursive(self, 0, &mut f);
    }

    /// Execute function `f` recursively on every member of AST tree
    /// (using postorder deep-first search).
    pub fn walk_post(&self, mut f: impl FnMut(&Node, u32)) {
        fn walk_recursive(node: &Node, depth: u32, f: &mut impl FnMut(&Node, u32)) {
            for n in node.children.iter() {
                stacker::maybe_grow(64*1024, 1024*1024, || {
                    walk_recursive(n, depth + 1, f);
                });
            }
            f(node, depth);
        }

        walk_recursive(self, 0, &mut f);
    }

    /// Execute function `f` recursively on every member of AST tree
    /// (using postorder deep-first search).
    pub fn walk_post_mut(&mut self, mut f: impl FnMut(&mut Node, u32)) {
        fn walk_recursive(node: &mut Node, depth: u32, f: &mut impl FnMut(&mut Node, u32)) {
            for n in node.children.iter_mut() {
                stacker::maybe_grow(64*1024, 1024*1024, || {
                    walk_recursive(n, depth + 1, f);
                });
            }
            f(node, depth);
        }

        walk_recursive(self, 0, &mut f);
    }

    /// Walk recursively through child nodes and collect all text nodes
    /// into a single string.
    pub fn collect_text(&self) -> String {
        let mut result = String::new();

        self.walk(|node, _| {
            if let Some(text) = node.cast::<Text>() {
                result.push_str(text.content.as_str());
            }
        });

        result
    }
}

impl Drop for Node {
    fn drop(&mut self) {
        self.walk_post_mut(|node, _| {
            drop(std::mem::take(&mut node.children));
        });
    }
}

#[derive(Debug)]
#[doc(hidden)]
pub struct NodeEmpty;
impl NodeValue for NodeEmpty {}

impl Default for Node {
    /// Create empty Node. Empty node should only be used as placeholder for functions like
    /// std::mem::take, and it cannot be rendered.
    fn default() -> Self {
        Node::new(NodeEmpty)
    }
}

/// Contents of the specific AST node.
pub trait NodeValue : Debug + Downcast {
    /// Output HTML corresponding to this node using Renderer API.
    ///
    /// Example implementation looks like this:
    /// ```rust
    /// # const IGNORE : &str = stringify! {
    /// fn render(&self, node: &Node, fmt: &mut dyn Renderer) {
    ///    fmt.open("div", &[]);
    ///    fmt.contents(&node.children);
    ///    fmt.close("div");
    ///    fmt.cr();
    /// }
    /// # };
    /// ```
    fn render(&self, node: &Node, fmt: &mut dyn Renderer) {
        let _ = fmt;
        unimplemented!("{} doesn't implement render", node.name());
    }
}

impl_downcast!(NodeValue);