1use std::collections::hash_map::Entry;
2use std::collections::HashMap;
3use std::sync::atomic::{AtomicUsize, Ordering};
4use std::sync::mpsc::channel;
5use std::sync::{Arc, Mutex};
6use std::thread::ThreadId;
7
8use crate::access::vec::ReflectVec;
9use crate::access::{
10 derive::{ReflectStruct, Struct, StructKind},
11 iter::ReflectIter,
12 Access,
13};
14use crate::node_tree::{NodeInfo, NodeTree, PtrMeta, Wrap};
15
16type ObjPtr = (usize, usize);
17
18pub struct Reflector {
23 limit: usize,
24 used: AtomicUsize,
25
26 seen: Mutex<HashMap<ObjPtr, PtrMeta>>,
27 synced_thread: ThreadId,
28}
29
30impl Reflector {
31 pub fn new(limit: usize) -> Arc<Self> {
32 Arc::new(Self {
33 limit,
34 used: AtomicUsize::new(0),
35 seen: Mutex::new(HashMap::new()),
36 synced_thread: std::thread::current().id(),
37 })
38 }
39
40 pub fn reflect_struct(
41 a_self: &Arc<Self>,
42 desc: &Struct,
43 p_struct: &dyn ReflectStruct,
44 anon: bool,
45 ) -> NodeTree {
46 let meta = try_seen_dyn!(p_struct, a_self);
47
48 match &desc.kind {
49 StructKind::Unit => {
50 NodeInfo::Leaf(std::borrow::Cow::Borrowed(desc.name)).with_meta(meta)
51 }
52 StructKind::Tuple(n) => {
53 let mut v = vec![];
54
55 for i in 0..*n {
56 if a_self.limit <= a_self.used.load(Ordering::Relaxed) {
57 v.push(NodeInfo::Limited.into_node());
58 break;
59 }
60
61 let reflect_node = Self::reflect(a_self, p_struct.get_field_by_idx(i).unwrap());
62 v.push(reflect_node);
63 }
64
65 let grouped =
66 NodeInfo::Grouped('(', Box::new(NodeInfo::Delimited(',', v).into_node()), ')');
67
68 let elem = if !desc.name.is_empty() && !anon {
69 NodeInfo::named(desc.name, grouped.into_node())
70 } else {
71 grouped
72 };
73
74 elem.with_meta(meta)
75 }
76 StructKind::Fields(fields) => {
77 let mut result = vec![];
78 let mut items = vec![];
79 let mut missing_keys = false;
80
81 for field in *fields {
82 if a_self.limit <= a_self.used.load(Ordering::Relaxed) {
83 missing_keys = true;
84 break;
85 }
86
87 a_self.used.fetch_add(1, Ordering::SeqCst);
88 items.push((field, p_struct.get_field_by_name(field).unwrap()));
89 }
90
91 for (key, value) in items.into_iter() {
92 let node = {
93 if a_self.limit <= a_self.used.load(Ordering::Relaxed) {
94 NodeInfo::Limited.into_node()
95 } else {
96 Self::reflect(a_self, value)
97 }
98 };
99
100 result.push(
101 NodeInfo::Tuple(
102 Box::new(NodeInfo::Leaf(std::borrow::Cow::Borrowed(key)).into_node()),
103 ":",
104 Box::new(node),
105 )
106 .into_node(),
107 )
108 }
109
110 if missing_keys {
111 result.push(NodeInfo::Limited.into_node());
112 }
113
114 let grouped = NodeInfo::Grouped(
115 '{',
116 Box::new(NodeInfo::Delimited(',', result).into_node()),
117 '}',
118 );
119
120 let elem = if !desc.name.is_empty() && !anon {
121 NodeInfo::named(desc.name, grouped.into_node())
122 } else {
123 grouped
124 };
125
126 elem.with_meta(meta)
127 }
128 }
129 }
130
131 pub fn reflect_map(
132 a_self: &Arc<Self>,
133 iter: &mut dyn ReflectIter<(&dyn Access, &dyn Access)>,
134 name: &'static str,
135 ) -> NodeTree {
136 let meta = try_seen_dyn!(iter, a_self);
137
138 let mut result = vec![];
139 let mut items = vec![];
140 let mut missing_keys = false;
141
142 while let Some((key, value)) = iter.reflect_next() {
143 if a_self.limit <= a_self.used.load(Ordering::Relaxed) {
144 missing_keys = true;
145 break;
146 }
147
148 a_self.used.fetch_add(1, Ordering::SeqCst);
149 items.push((Self::reflect(a_self, key), value));
150 }
151
152 for (key, value) in items.into_iter() {
153 let node = {
154 if a_self.limit <= a_self.used.load(Ordering::Relaxed) {
155 NodeInfo::Limited.into_node()
156 } else {
157 Self::reflect(a_self, value)
158 }
159 };
160
161 let reflect_node = NodeInfo::Tuple(Box::new(key), ":", Box::new(node));
162 result.push(reflect_node.into_node());
163 }
164
165 if missing_keys {
166 result.push(NodeInfo::Limited.into_node());
167 }
168
169 NodeInfo::named(
170 name,
171 NodeInfo::Grouped(
172 '{',
173 Box::new(NodeInfo::Delimited(',', result).into_node()),
174 '}',
175 )
176 .into_node(),
177 )
178 .with_meta(meta)
179 }
180
181 pub fn reflect_set(
182 a_self: &Arc<Self>,
183 iter: &mut dyn ReflectIter<&dyn Access>,
184 name: &'static str,
185 ) -> NodeTree {
186 let mut v = vec![];
187 let meta = try_seen_dyn!(iter, a_self);
188
189 while let Some(member) = iter.reflect_next() {
190 if a_self.limit <= a_self.used.load(Ordering::Relaxed) {
191 v.push(NodeInfo::Limited.into_node());
192 break;
193 }
194
195 let member = Self::reflect(a_self, member);
196 v.push(member);
197 }
198
199 NodeInfo::named(
200 name,
201 NodeInfo::Grouped('{', Box::new(NodeInfo::Delimited(',', v).into_node()), '}')
202 .into_node(),
203 )
204 .with_meta(meta)
205 }
206
207 pub fn reflect_vec(a_self: &Arc<Self>, vec: &dyn ReflectVec, name: &'static str) -> NodeTree {
208 let mut v = vec![];
209
210 let meta = try_seen_dyn!(vec, a_self);
211
212 for i in 0..vec.get_len() {
213 if a_self.limit <= a_self.used.load(Ordering::Relaxed) {
214 v.push(NodeInfo::Limited.into_node());
215 break;
216 }
217
218 let reflect_node = Self::reflect(a_self, vec.get_item(i).unwrap());
219 v.push(reflect_node);
220 }
221
222 let item = NodeInfo::Grouped('[', Box::new(NodeInfo::Delimited(',', v).into_node()), ']');
223
224 let item = if !name.is_empty() {
225 NodeInfo::named(name, item.into_node())
226 } else {
227 item
228 };
229
230 item.with_meta(meta)
231 }
232
233 pub fn seen_ptr(a_self: &Arc<Self>, obj_ptr: ObjPtr) -> Result<NodeTree, PtrMeta> {
234 let mut seen = a_self.seen.lock().unwrap();
235 match seen.entry(obj_ptr) {
236 Entry::Occupied(entry) => {
237 let entry = entry.get();
238 entry.fetch_add(1, Ordering::SeqCst);
239
240 Ok(NodeTree::new(NodeInfo::Repeated, Some(Wrap(entry.clone()))))
241 }
242 Entry::Vacant(entry) => {
243 let meta = Arc::new(AtomicUsize::new(1));
244 entry.insert(meta.clone());
245 Err(meta)
246 }
247 }
248 }
249
250 pub fn reflect(a_self: &Arc<Self>, access: &dyn Access) -> NodeTree {
251 use crate::Reflect::*;
252
253 let immut_access = access.immut_access();
254
255 let reflect_node = match immut_access.reflect {
256 Direct(v) => v.immut_reflector(a_self),
257 Indirect(access) => {
258 let (sender, receiver) = channel();
259 let b_self = a_self.clone();
260
261 access.indirect(Box::new(move |access| {
262 let res = Self::reflect(&b_self, access);
263 let _ = sender.send(res);
264 }));
265
266 if a_self.synced_thread == std::thread::current().id() {
267 receiver.recv().unwrap()
268 } else {
269 NodeInfo::Hole(Box::new(receiver)).into_node()
270 }
271 }
272 };
273
274 a_self.used.fetch_add(1, Ordering::SeqCst);
275 reflect_node
276 }
277}