interact/util/
node_tree.rs1use std::borrow::Cow;
2use std::io::Cursor;
3use std::io::Write;
4use std::ops::Deref;
5use std::sync::atomic::AtomicUsize;
6use std::sync::mpsc::Receiver;
7use std::sync::Arc;
8
9type Delimiter = char;
10
11#[derive(Debug)]
12pub enum NodeInfo {
13 Grouped(char, Box<NodeTree>, char),
14 Delimited(Delimiter, Vec<NodeTree>),
15 Named(Box<NodeTree>, Box<NodeTree>),
16 Tuple(Box<NodeTree>, &'static str, Box<NodeTree>),
17 Leaf(Cow<'static, str>),
18 Hole(Box<Receiver<NodeTree>>),
19 BorrowedMut,
20 Locked,
21 Repeated,
22 Limited,
23}
24
25pub type PtrMeta = Arc<AtomicUsize>;
26
27#[derive(Debug)]
28pub struct Wrap(pub PtrMeta);
29
30#[derive(Debug)]
33pub struct NodeTree {
34 pub info: NodeInfo,
35 pub meta: Option<Wrap>,
36 pub size: usize,
37}
38
39impl NodeTree {
40 pub fn new(info: NodeInfo, meta: Option<Wrap>) -> Self {
41 Self {
42 info,
43 meta,
44 size: 0,
45 }
46 }
47}
48
49impl Eq for Wrap {}
50impl PartialEq for Wrap {
51 fn eq(&self, other: &Self) -> bool {
52 Arc::ptr_eq(&self.0, &other.0)
53 }
54}
55
56struct Printer {
57 accum: Cursor<Vec<u8>>,
58}
59
60impl Printer {
61 fn write(&mut self, s: &str) -> Result<(), std::io::Error> {
62 self.accum.write_all(s.as_bytes())?;
63 Ok(())
64 }
65}
66
67impl NodeInfo {
68 pub fn into_node(self) -> NodeTree {
69 NodeTree {
70 info: self,
71 meta: None,
72 size: 0,
73 }
74 }
75
76 pub fn with_meta(self, ptr_meta: PtrMeta) -> NodeTree {
77 NodeTree {
78 info: self,
79 meta: Some(Wrap(ptr_meta)),
80 size: 0,
81 }
82 }
83
84 pub fn named(name: &'static str, a_self: NodeTree) -> Self {
85 NodeInfo::Named(
86 Box::new(NodeTree {
87 info: NodeInfo::Leaf(Cow::Borrowed(name)),
88 meta: None,
89 size: 0,
90 }),
91 Box::new(a_self),
92 )
93 }
94
95 pub fn format(&self) -> Result<Vec<u8>, std::io::Error> {
96 let mut state = Printer {
97 accum: Cursor::new(Vec::new()),
98 };
99
100 self.inner_pretty_print(&mut state)?;
101
102 let Printer { accum, .. } = state;
103
104 Ok(accum.into_inner())
105 }
106
107 fn inner_pretty_print(&self, state: &mut Printer) -> Result<(), std::io::Error> {
108 use crate::NodeInfo::*;
109
110 match self {
111 Grouped(prefix, sub, end) => {
112 let space = match sub.deref().info {
113 Delimited(_, ref v) if v.is_empty() => "",
114 _ => " ",
115 };
116
117 state.write(&format!("{}{}", prefix, space))?;
118 sub.info.inner_pretty_print(state)?;
119 state.write(&format!("{}{}", space, end))?;
120 }
121 Delimited(delimiter, v) => {
122 for (idx, i) in v.iter().enumerate() {
123 if idx > 0 {
124 state.write(&format!("{} ", delimiter))?;
125 }
126
127 i.info.inner_pretty_print(state)?;
128 }
129 }
130 Tuple(key, sep, value) => {
131 key.info.inner_pretty_print(state)?;
132 state.write(&format!(" {} ", sep))?;
133 value.info.inner_pretty_print(state)?;
134 }
135 Named(item, next) => {
136 item.info.inner_pretty_print(state)?;
137 state.write(&" ")?;
138 next.info.inner_pretty_print(state)?;
139 }
140 Leaf(s) => {
141 state.write(s)?;
142 }
143 Hole(_) => {
144 state.write(&format!("<hole>"))?;
145 }
146 BorrowedMut => {
147 state.write(&format!("<borrowed-mut>"))?;
148 }
149 Locked => {
150 state.write(&format!("<locked>"))?;
151 }
152 Limited => {
153 state.write("...")?;
154 }
155 Repeated => {
156 state.write(&format!("<repeated>"))?;
157 }
158 };
159
160 Ok(())
161 }
162}
163
164impl NodeTree {
165 pub fn resolve(&mut self) -> usize {
166 use crate::NodeInfo::*;
167
168 loop {
169 let mut count = 1;
170
171 let r = match &mut self.info {
172 Grouped(_, sub, _) => {
173 count += 2 + sub.resolve();
174 None
175 }
176 Delimited(_, v) => {
177 for i in v.iter_mut() {
178 count += i.resolve() + 2;
179 }
180 None
181 }
182 Tuple(key, sep, value) => {
183 count += key.resolve();
184 count += sep.len() + 2;
185 count += value.resolve();
186 None
187 }
188 Named(item, next) => {
189 count += item.resolve();
190 count += next.resolve();
191 None
192 }
193 Leaf(v) => {
194 count += v.len();
195 None
196 }
197 Hole(receiver) => Some((*receiver).recv().unwrap()),
198 Limited => None,
199 Repeated => None,
200 BorrowedMut => None,
201 Locked => None,
202 };
203
204 if let Some(r) = r {
205 *self = r;
206 continue;
207 }
208
209 self.size = count;
210
211 return count;
212 }
213 }
214}
215
216use std::fmt;
217
218impl fmt::Display for NodeInfo {
219 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
220 let v = self.format().unwrap();
221
222 write!(f, "{}", String::from_utf8_lossy(v.as_slice()))
223 }
224}