cdragon_prop/
visitor.rs

1//! Visit a nested bin value
2
3use super::{
4    BinEntry,
5    data::*,
6    binvalue_map_type,
7    binvalue_map_keytype,
8};
9
10/// Interface to visit values of nested bin values
11///
12/// Visit methods of nested types can return `false` to not visit nested values.
13/// By default, everything is visited.
14///
15/// [visit_type()](Self::visit_type()) can be used to easily ignore some types.
16/// It is used for default implementations and internal shortcuts.
17#[allow(missing_docs)]
18pub trait BinVisitor {
19    type Error;
20
21    /// Called to visit an entry
22    ///
23    /// This method exists so an implementation can execute code after an entry has been visited.
24    fn traverse_entry(&mut self, value: &BinEntry) -> Result<(), Self::Error> {
25        value.traverse_bin(self)
26    }
27
28    /// Return true to visit given type
29    fn visit_type(&mut self, _btype: BinType) -> bool { true }
30
31    fn visit_entry(&mut self, _value: &BinEntry) -> Result<bool, Self::Error> { Ok(true) }
32    fn visit_field(&mut self, value: &BinField) -> Result<bool, Self::Error> { Ok(self.visit_type(value.vtype)) }
33
34    fn visit_none(&mut self, _value: &BinNone) -> Result<(), Self::Error> { Ok(()) }
35    fn visit_bool(&mut self, _value: &BinBool) -> Result<(), Self::Error> { Ok(()) }
36    fn visit_s8(&mut self, _value: &BinS8) -> Result<(), Self::Error> { Ok(()) }
37    fn visit_u8(&mut self, _value: &BinU8) -> Result<(), Self::Error> { Ok(()) }
38    fn visit_s16(&mut self, _value: &BinS16) -> Result<(), Self::Error> { Ok(()) }
39    fn visit_u16(&mut self, _value: &BinU16) -> Result<(), Self::Error> { Ok(()) }
40    fn visit_s32(&mut self, _value: &BinS32) -> Result<(), Self::Error> { Ok(()) }
41    fn visit_u32(&mut self, _value: &BinU32) -> Result<(), Self::Error> { Ok(()) }
42    fn visit_s64(&mut self, _value: &BinS64) -> Result<(), Self::Error> { Ok(()) }
43    fn visit_u64(&mut self, _value: &BinU64) -> Result<(), Self::Error> { Ok(()) }
44    fn visit_float(&mut self, _value: &BinFloat) -> Result<(), Self::Error> { Ok(()) }
45    fn visit_vec2(&mut self, _value: &BinVec2) -> Result<(), Self::Error> { Ok(()) }
46    fn visit_vec3(&mut self, _value: &BinVec3) -> Result<(), Self::Error> { Ok(()) }
47    fn visit_vec4(&mut self, _value: &BinVec4) -> Result<(), Self::Error> { Ok(()) }
48    fn visit_matrix(&mut self, _value: &BinMatrix) -> Result<(), Self::Error> { Ok(()) }
49    fn visit_color(&mut self, _value: &BinColor) -> Result<(), Self::Error> { Ok(()) }
50    fn visit_string(&mut self, _value: &BinString) -> Result<(), Self::Error> { Ok(()) }
51    fn visit_hash(&mut self, _value: &BinHash) -> Result<(), Self::Error> { Ok(()) }
52    fn visit_path(&mut self, _value: &BinPath) -> Result<(), Self::Error> { Ok(()) }
53    fn visit_list(&mut self, value: &BinList) -> Result<bool, Self::Error> {
54        Ok(self.visit_type(BinType::List) && self.visit_type(value.vtype))
55    }
56    fn visit_struct(&mut self, _value: &BinStruct) -> Result<bool, Self::Error> {
57        Ok(self.visit_type(BinType::Struct))
58    }
59    fn visit_embed(&mut self, _value: &BinEmbed) -> Result<bool, Self::Error> {
60        Ok(self.visit_type(BinType::Embed))
61    }
62    fn visit_link(&mut self, _value: &BinLink) -> Result<(), Self::Error> { Ok(()) }
63    fn visit_option(&mut self, value: &BinOption) -> Result<bool, Self::Error> {
64        Ok(self.visit_type(BinType::Option) && self.visit_type(value.vtype))
65    }
66    fn visit_map(&mut self, _value: &BinMap) -> Result<bool, Self::Error> {
67        Ok(self.visit_type(BinType::Map))
68    }
69    fn visit_flag(&mut self, _value: &BinFlag) -> Result<(), Self::Error> { Ok(()) }
70}
71
72/// Interface to traverse nested bin values with a visitor
73pub trait BinTraversal<BV: BinVisitor + ?Sized> {
74    /// Visit the value, recursively
75    fn traverse_bin(&self, visitor: &mut BV) -> Result<(), BV::Error>;
76}
77
78macro_rules! impl_traversal {
79    ($t:ty, $visit:ident) => {
80        impl<BV: BinVisitor + ?Sized> BinTraversal<BV> for $t {
81            #[inline]
82            fn traverse_bin(&self, visitor: &mut BV) -> Result<(), BV::Error> {
83                visitor.$visit(self)
84            }
85        }
86    }
87}
88
89impl_traversal!(BinNone, visit_none);
90impl_traversal!(BinBool, visit_bool);
91impl_traversal!(BinS8, visit_s8);
92impl_traversal!(BinU8, visit_u8);
93impl_traversal!(BinS16, visit_s16);
94impl_traversal!(BinU16, visit_u16);
95impl_traversal!(BinS32, visit_s32);
96impl_traversal!(BinU32, visit_u32);
97impl_traversal!(BinS64, visit_s64);
98impl_traversal!(BinU64, visit_u64);
99impl_traversal!(BinFloat, visit_float);
100impl_traversal!(BinVec2, visit_vec2);
101impl_traversal!(BinVec3, visit_vec3);
102impl_traversal!(BinVec4, visit_vec4);
103impl_traversal!(BinMatrix, visit_matrix);
104impl_traversal!(BinColor, visit_color);
105impl_traversal!(BinString, visit_string);
106impl_traversal!(BinHash, visit_hash);
107impl_traversal!(BinPath, visit_path);
108impl_traversal!(BinLink, visit_link);
109impl_traversal!(BinFlag, visit_flag);
110
111
112impl<BV: BinVisitor + ?Sized> BinTraversal<BV> for BinEntry {
113    fn traverse_bin(&self, visitor: &mut BV) -> Result<(), BV::Error> {
114        if visitor.visit_entry(self)? {
115            for field in self.fields.iter() {
116                field.traverse_bin(visitor)?;
117            }
118        }
119        Ok(())
120    }
121}
122
123impl<BV: BinVisitor + ?Sized> BinTraversal<BV> for BinField {
124    fn traverse_bin(&self, visitor: &mut BV) -> Result<(), BV::Error> {
125        if visitor.visit_field(self)? {
126            binvalue_map_type!(self.vtype, T, {
127                self.downcast::<T>().unwrap().traverse_bin(visitor)?;
128            });
129        }
130        Ok(())
131    }
132}
133
134impl<BV: BinVisitor + ?Sized> BinTraversal<BV> for BinStruct {
135    fn traverse_bin(&self, visitor: &mut BV) -> Result<(), BV::Error> {
136        if visitor.visit_struct(self)? {
137            for field in self.fields.iter() {
138                field.traverse_bin(visitor)?;
139            }
140        }
141        Ok(())
142    }
143}
144
145impl<BV: BinVisitor + ?Sized> BinTraversal<BV> for BinEmbed {
146    fn traverse_bin(&self, visitor: &mut BV) -> Result<(), BV::Error> {
147        if visitor.visit_embed(self)? {
148            for field in self.fields.iter() {
149                field.traverse_bin(visitor)?;
150            }
151        }
152        Ok(())
153    }
154}
155
156impl<BV: BinVisitor + ?Sized> BinTraversal<BV> for BinOption {
157    fn traverse_bin(&self, visitor: &mut BV) -> Result<(), BV::Error> {
158        if visitor.visit_option(self)? {
159            if self.value.is_some() {
160                binvalue_map_type!(self.vtype, V, {
161                    self.downcast::<V>().unwrap().traverse_bin(visitor)?;
162                });
163            }
164        }
165        Ok(())
166    }
167}
168
169impl<BV: BinVisitor + ?Sized> BinTraversal<BV> for BinList {
170    fn traverse_bin(&self, visitor: &mut BV) -> Result<(), BV::Error> {
171        if visitor.visit_list(self)? {
172            binvalue_map_type!(self.vtype, V, {
173                for v in self.downcast::<V>().unwrap().iter() {
174                    v.traverse_bin(visitor)?;
175                }
176            });
177        }
178        Ok(())
179    }
180}
181
182impl<BV: BinVisitor + ?Sized> BinTraversal<BV> for BinMap {
183    fn traverse_bin(&self, visitor: &mut BV) -> Result<(), BV::Error> {
184        if visitor.visit_map(self)? {
185            binvalue_map_keytype!(self.ktype, K, {
186                binvalue_map_type!(self.vtype, V, {
187                    for (k, v) in self.downcast::<K, V>().unwrap() {
188                        k.traverse_bin(visitor)?;
189                        v.traverse_bin(visitor)?;
190                    }
191                })
192            });
193        }
194        Ok(())
195    }
196}
197