valuable/
visit.rs

1use crate::*;
2
3/// Traverse a value's fields and variants.
4///
5/// Each method of the `Visit` trait is a hook that enables the implementor to
6/// observe value fields. By default, most methods are implemented as a no-op.
7/// The `visit_primitive_slice` default implementation will iterate the slice,
8/// calling `visit_value` with each item.
9///
10/// To recurse, the implementor must implement methods to visit the arguments.
11///
12/// # Examples
13///
14/// Recursively printing a Rust value.
15///
16/// ```
17/// use valuable::{NamedValues, Valuable, Value, Visit};
18///
19/// struct Print(String);
20///
21/// impl Print {
22///     fn indent(&self) -> Print {
23///        Print(format!("{}    ", self.0))
24///     }
25/// }
26///
27/// impl Visit for Print {
28///     fn visit_value(&mut self, value: Value<'_>) {
29///         match value {
30///             Value::Structable(v) => {
31///                 let def = v.definition();
32///                 // Print the struct name
33///                 println!("{}{}:", self.0, def.name());
34///
35///                 // Visit fields
36///                 let mut visit = self.indent();
37///                 v.visit(&mut visit);
38///             }
39///             Value::Enumerable(v) => {
40///                 let def = v.definition();
41///                 let variant = v.variant();
42///                 // Print the enum name
43///                 println!("{}{}::{}:", self.0, def.name(), variant.name());
44///
45///                 // Visit fields
46///                 let mut visit = self.indent();
47///                 v.visit(&mut visit);
48///             }
49///             Value::Listable(v) => {
50///                 println!("{}", self.0);
51///
52///                 // Visit fields
53///                 let mut visit = self.indent();
54///                 v.visit(&mut visit);
55///             }
56///             Value::Mappable(v) => {
57///                 println!("{}", self.0);
58///
59///                 // Visit fields
60///                 let mut visit = self.indent();
61///                 v.visit(&mut visit);
62///             }
63///             // Primitive or unknown type, just render Debug
64///             v => println!("{:?}", v),
65///         }
66///     }
67///
68///     fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) {
69///         for (field, value) in named_values {
70///             print!("{}- {}: ", self.0, field.name());
71///             value.visit(self);
72///         }
73///     }
74///
75///     fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) {
76///         for value in values {
77///             print!("{}- ", self.0);
78///             value.visit(self);
79///         }
80///     }
81///
82///     fn visit_entry(&mut self, key: Value<'_>, value: Value<'_>) {
83///         print!("{}- {:?}: ", self.0, key);
84///         value.visit(self);
85///     }
86/// }
87///
88/// #[derive(Valuable)]
89/// struct Person {
90///     name: String,
91///     age: u32,
92///     addresses: Vec<Address>,
93/// }
94///
95/// #[derive(Valuable)]
96/// struct Address {
97///     street: String,
98///     city: String,
99///     zip: String,
100/// }
101///
102/// let person = Person {
103///     name: "Angela Ashton".to_string(),
104///     age: 31,
105///     addresses: vec![
106///         Address {
107///             street: "123 1st Ave".to_string(),
108///             city: "Townsville".to_string(),
109///             zip: "12345".to_string(),
110///         },
111///         Address {
112///             street: "555 Main St.".to_string(),
113///             city: "New Old Town".to_string(),
114///             zip: "55555".to_string(),
115///         },
116///     ],
117/// };
118///
119/// let mut print = Print("".to_string());
120/// valuable::visit(&person, &mut print);
121/// ```
122pub trait Visit {
123    /// Visit a single value.
124    ///
125    /// The `visit_value` method is called once when visiting single primitive
126    /// values. When visiting `Listable` types, the `visit_value` method is
127    /// called once per item in the listable type.
128    ///
129    /// Note, in the case of Listable types containing primitive types,
130    /// `visit_primitive_slice` can be implemented instead for less overhead.
131    ///
132    /// # Examples
133    ///
134    /// Visiting a single value.
135    ///
136    /// ```
137    /// use valuable::{Valuable, Visit, Value};
138    ///
139    /// struct Print;
140    ///
141    /// impl Visit for Print {
142    ///     fn visit_value(&mut self, value: Value<'_>) {
143    ///         println!("{:?}", value);
144    ///     }
145    /// }
146    ///
147    /// let my_val = 123;
148    /// my_val.visit(&mut Print);
149    /// ```
150    ///
151    /// Visiting multiple values in a list.
152    ///
153    /// ```
154    /// use valuable::{Valuable, Value, Visit};
155    ///
156    /// struct PrintList { comma: bool };
157    ///
158    /// impl Visit for PrintList {
159    ///     fn visit_value(&mut self, value: Value<'_>) {
160    ///         match value {
161    ///             Value::Listable(v) => v.visit(self),
162    ///             value => {
163    ///                 if self.comma {
164    ///                     println!(", {:?}", value);
165    ///                 } else {
166    ///                     print!("{:?}", value);
167    ///                     self.comma = true;
168    ///                 }
169    ///             }
170    ///         }
171    ///     }
172    /// }
173    ///
174    /// let my_list = vec![1, 2, 3, 4, 5];
175    /// valuable::visit(&my_list, &mut PrintList { comma: false });
176    /// ```
177    fn visit_value(&mut self, value: Value<'_>);
178
179    /// Visit a struct or enum's named fields.
180    ///
181    /// When the struct/enum is statically defined, all fields are known ahead
182    /// of time and `visit_named_fields` is called once with all field values.
183    /// When the struct/enum is dynamic, then the `visit_named_fields` method
184    /// may be called multiple times.
185    ///
186    /// See [`Structable`] and [`Enumerable`] for static vs. dynamic details.
187    ///
188    /// # Examples
189    ///
190    /// Visiting all fields in a struct.
191    ///
192    /// ```
193    /// use valuable::{NamedValues, Valuable, Value, Visit};
194    ///
195    /// #[derive(Valuable)]
196    /// struct MyStruct {
197    ///     hello: String,
198    ///     world: u32,
199    /// }
200    ///
201    /// struct Print;
202    ///
203    /// impl Visit for Print {
204    ///     fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) {
205    ///         for (field, value) in named_values {
206    ///             println!("{:?}: {:?}", field, value);
207    ///         }
208    ///     }
209    ///
210    ///     fn visit_value(&mut self, value: Value<'_>) {
211    ///         match value {
212    ///             Value::Structable(v) => v.visit(self),
213    ///             _ => {} // do nothing for other types
214    ///         }
215    ///     }
216    /// }
217    ///
218    /// let my_struct = MyStruct {
219    ///     hello: "Hello world".to_string(),
220    ///     world: 42,
221    /// };
222    ///
223    /// valuable::visit(&my_struct, &mut Print);
224    /// ```
225    fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) {
226        let _ = named_values;
227    }
228
229    /// Visit a struct or enum's unnamed fields.
230    ///
231    /// When the struct/enum is statically defined, all fields are known ahead
232    /// of time and `visit_unnamed_fields` is called once with all field values.
233    /// When the struct/enum is dynamic, then the `visit_unnamed_fields` method
234    /// may be called multiple times.
235    ///
236    /// See [`Structable`] and [`Enumerable`] for static vs. dynamic details.
237    ///
238    /// # Examples
239    ///
240    /// Visiting all fields in a struct.
241    ///
242    /// ```
243    /// use valuable::{Valuable, Value, Visit};
244    ///
245    /// #[derive(Valuable)]
246    /// struct MyStruct(String, u32);
247    ///
248    /// struct Print;
249    ///
250    /// impl Visit for Print {
251    ///     fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) {
252    ///         for value in values {
253    ///             println!("{:?}", value);
254    ///         }
255    ///     }
256    ///
257    ///     fn visit_value(&mut self, value: Value<'_>) {
258    ///         match value {
259    ///             Value::Structable(v) => v.visit(self),
260    ///             _ => {} // do nothing for other types
261    ///         }
262    ///     }
263    /// }
264    ///
265    /// let my_struct = MyStruct("Hello world".to_string(), 42);
266    ///
267    /// valuable::visit(&my_struct, &mut Print);
268    /// ```
269    fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) {
270        let _ = values;
271    }
272
273    /// Visit a primitive slice.
274    ///
275    /// This method exists as an optimization when visiting [`Listable`] types.
276    /// By default, `Listable` types are visited by passing each item to
277    /// `visit_value`. However, if the listable stores a **primitive** type
278    /// within contiguous memory, then `visit_primitive_slice` is called
279    /// instead.
280    ///
281    /// When implementing `visit_primitive_slice`, be aware that the method may
282    /// be called multiple times for a single `Listable` type.
283    ///
284    /// # Examples
285    ///
286    /// A vec calls `visit_primitive_slice` one time, but a `VecDeque` will call
287    /// `visit_primitive_slice` twice.
288    ///
289    /// ```
290    /// use valuable::{Valuable, Value, Visit, Slice};
291    /// use std::collections::VecDeque;
292    ///
293    /// struct Count(u32);
294    ///
295    /// impl Visit for Count {
296    ///     fn visit_primitive_slice(&mut self, slice: Slice<'_>) {
297    ///         self.0 += 1;
298    ///     }
299    ///
300    ///     fn visit_value(&mut self, value: Value<'_>) {
301    ///         match value {
302    ///             Value::Listable(v) => v.visit(self),
303    ///             _ => {} // do nothing for other types
304    ///         }
305    ///     }
306    /// }
307    ///
308    /// let vec = vec![1, 2, 3, 4, 5];
309    ///
310    /// let mut count = Count(0);
311    /// valuable::visit(&vec, &mut count);
312    /// assert_eq!(1, count.0);
313    ///
314    /// let mut vec_deque = VecDeque::from(vec);
315    ///
316    /// let mut count = Count(0);
317    /// valuable::visit(&vec_deque, &mut count);
318    ///
319    /// assert_eq!(2, count.0);
320    /// ```
321    fn visit_primitive_slice(&mut self, slice: Slice<'_>) {
322        for value in slice {
323            self.visit_value(value);
324        }
325    }
326
327    /// Visit a `Mappable`'s entries.
328    ///
329    /// The `visit_entry` method is called once for each entry contained by a
330    /// `Mappable.`
331    ///
332    /// # Examples
333    ///
334    /// Visit a map's entries
335    ///
336    /// ```
337    /// use valuable::{Valuable, Value, Visit};
338    /// use std::collections::HashMap;
339    ///
340    /// let mut map = HashMap::new();
341    /// map.insert("hello", 123);
342    /// map.insert("world", 456);
343    ///
344    /// struct Print;
345    ///
346    /// impl Visit for Print {
347    ///     fn visit_entry(&mut self, key: Value<'_>, value: Value<'_>) {
348    ///         println!("{:?} => {:?}", key, value);
349    ///     }
350    ///
351    ///     fn visit_value(&mut self, value: Value<'_>) {
352    ///         match value {
353    ///             Value::Mappable(v) => v.visit(self),
354    ///             _ => {} // do nothing for other types
355    ///         }
356    ///     }
357    /// }
358    ///
359    /// valuable::visit(&map, &mut Print);
360    /// ```
361    fn visit_entry(&mut self, key: Value<'_>, value: Value<'_>) {
362        let _ = (key, value);
363    }
364}
365
366macro_rules! deref {
367    (
368        $(
369            $(#[$attrs:meta])*
370            $ty:ty,
371        )*
372    ) => {
373        $(
374            $(#[$attrs])*
375            impl<T: ?Sized + Visit> Visit for $ty {
376                fn visit_value(&mut self, value: Value<'_>) {
377                    T::visit_value(&mut **self, value)
378                }
379
380                fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) {
381                    T::visit_named_fields(&mut **self, named_values)
382                }
383
384                fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) {
385                    T::visit_unnamed_fields(&mut **self, values)
386                }
387
388                fn visit_primitive_slice(&mut self, slice: Slice<'_>) {
389                    T::visit_primitive_slice(&mut **self, slice)
390                }
391
392                fn visit_entry(&mut self, key: Value<'_>, value: Value<'_>) {
393                    T::visit_entry(&mut **self, key, value)
394                }
395            }
396        )*
397    };
398}
399
400deref! {
401    &mut T,
402    #[cfg(feature = "alloc")]
403    alloc::boxed::Box<T>,
404}
405
406/// Inspects a value by calling the relevant [`Visit`] methods with `value`'s
407/// data.
408///
409/// This method calls [`Visit::visit_value()`] with the provided [`Valuable`]
410/// instance. See [`Visit`] documentation for more details.
411///
412/// # Examples
413///
414/// Extract a single field from a struct. Note: if the same field is repeatedly
415/// extracted from a struct, it is preferable to obtain the associated
416/// [`NamedField`] once and use it repeatedly.
417///
418/// ```
419/// use valuable::{NamedValues, Valuable, Value, Visit};
420///
421/// #[derive(Valuable)]
422/// struct MyStruct {
423///     foo: usize,
424///     bar: usize,
425/// }
426///
427/// struct GetFoo(usize);
428///
429/// impl Visit for GetFoo {
430///     fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) {
431///         if let Some(foo) = named_values.get_by_name("foo") {
432///             if let Some(val) = foo.as_usize() {
433///                 self.0 = val;
434///             }
435///         }
436///     }
437///
438///     fn visit_value(&mut self, value: Value<'_>) {
439///         if let Value::Structable(v) = value {
440///             v.visit(self);
441///         }
442///     }
443/// }
444///
445/// let my_struct = MyStruct {
446///     foo: 123,
447///     bar: 456,
448/// };
449///
450/// let mut get_foo = GetFoo(0);
451/// valuable::visit(&my_struct, &mut get_foo);
452///
453/// assert_eq!(123, get_foo.0);
454/// ```
455///
456/// [`Visit`]: Visit [`NamedField`]: crate::NamedField
457pub fn visit(value: &impl Valuable, visit: &mut dyn Visit) {
458    visit.visit_value(value.as_value());
459}