der_parser/ber/
visit_mut.rs

1use super::{BerObject, BerObjectContent, BitStringObject};
2use alloc::vec::Vec;
3use asn1_rs::{ASN1DateTime, Any, Class, Oid, Tag};
4
5/// BER object tree traversal to walk a shared borrow of a BER object
6///
7/// When implementing your own visitor, define your own `visit_ber_xxx` methods.
8///
9/// Note that `visit_ber` is called for every object, so if you implement multiple visitor methods they
10/// will be called multiple times for the same object. Generally, if `visit_ber` is implemented, then other
11/// methods are not needed.
12///
13/// For example, on a `Sequence` item, `visit_ber` is called first, then `visit_ber_sequence`, and then
14/// `visit_ber` for every sequence object (recursively).
15///
16/// Entry point: use the [`VisitMut::run`] or [`VisitMut::run_at`] methods.
17///
18/// Visitor functions
19#[allow(unused_variables)]
20pub trait VisitMut<'a> {
21    /// Called for every BER object
22    fn visit_ber_mut(&mut self, ber: &'_ mut BerObject<'a>, depth: usize) {}
23
24    /// Called for BER bitstring objects
25    fn visit_ber_bitstring_mut(
26        &mut self,
27        ignored: &mut u8,
28        data: &'a mut BitStringObject,
29        depth: usize,
30    ) {
31    }
32
33    /// Called for BER bmpstring objects
34    fn visit_ber_bmpstring_mut(&mut self, s: &'a mut &'_ str, depth: usize) {}
35
36    /// Called for BER boolean objects
37    fn visit_ber_boolean_mut(&mut self, b: &'a mut bool, depth: usize) {}
38
39    /// Called for BER end-of-content objects
40    fn visit_ber_endofcontent_mut(&mut self, depth: usize) {}
41
42    /// Called for BER enum objects
43    fn visit_ber_enum_mut(&mut self, e: &'a mut u64, depth: usize) {}
44
45    /// Called for BER generalstring objects
46    fn visit_ber_generalstring_mut(&mut self, s: &'a mut &'_ str, depth: usize) {}
47
48    /// Called for BER generalizedtime objects
49    fn visit_ber_generalizedtime_mut(&mut self, t: &'a ASN1DateTime, depth: usize) {}
50
51    /// Called for BER graphicstring objects
52    fn visit_ber_graphicstring_mut(&mut self, s: &'a mut &'_ str, depth: usize) {}
53
54    /// Called for BER ia5string objects
55    fn visit_ber_ia5string_mut(&mut self, s: &'a mut &'_ str, depth: usize) {}
56
57    /// Called for BER integer objects
58    fn visit_ber_integer_mut(&mut self, raw_bytes: &'a mut &'_ [u8], depth: usize) {}
59
60    /// Called for BER null objects
61    fn visit_ber_null_mut(&mut self, depth: usize) {}
62
63    /// Called for BER numericstring objects
64    fn visit_ber_numericstring_mut(&mut self, s: &'a mut &'_ str, depth: usize) {}
65
66    /// Called for BER OID objects
67    fn visit_ber_oid_mut(&mut self, oid: &'a mut Oid, depth: usize) {}
68
69    /// Called for BER object descriptor objects
70    fn visit_ber_objectdescriptor_mut(&mut self, s: &'a mut &'_ str, depth: usize) {}
71
72    /// Called for BER octetstring objects
73    fn visit_ber_octetstring_mut(&mut self, b: &'a [u8], depth: usize) {}
74
75    /// Called for BER optional objects
76    fn visit_ber_optional_mut(&mut self, obj: Option<&'a mut BerObject<'a>>, depth: usize) {}
77
78    /// Called for BER printablestring objects
79    fn visit_ber_printablestring_mut(&mut self, s: &'a mut &'_ str, depth: usize) {}
80
81    /// Called for BER relative OID objects
82    fn visit_ber_relative_oid_mut(&mut self, oid: &'a mut Oid, depth: usize) {}
83
84    /// Called for BER sequence objects
85    fn visit_ber_sequence_mut(&mut self, l: &'_ mut Vec<BerObject<'a>>, depth: usize) {}
86
87    /// Called for BER set objects
88    fn visit_ber_set_mut(&mut self, ber: &'_ mut Vec<BerObject<'a>>, depth: usize) {}
89
90    /// Called for BER teletexstring objects
91    fn visit_ber_teletexstring_mut(&mut self, s: &'a mut &'_ str, depth: usize) {}
92
93    /// Called for BER tagged objects
94    fn visit_ber_tagged_mut(
95        &mut self,
96        class: &'a mut Class,
97        tag: &'a mut Tag,
98        obj: &'a mut BerObject<'a>,
99        depth: usize,
100    ) {
101    }
102
103    /// Called for BER generalizedtime objects
104    fn visit_ber_utctime_mut(&mut self, t: &'a ASN1DateTime, depth: usize) {}
105
106    /// Called for BER utf8string objects
107    fn visit_ber_utf8string_mut(&mut self, s: &'a str, depth: usize) {}
108
109    /// Called for BER universalstring objects
110    fn visit_ber_universalstring_mut(&mut self, raw_bytes: &'a mut &'_ [u8], depth: usize) {}
111
112    /// Called for BER videotexstring objects
113    fn visit_ber_videotextstring_mut(&mut self, raw_bytes: &'a mut &'_ str, depth: usize) {}
114
115    /// Called for BER visiblestring objects
116    fn visit_ber_visiblestring_mut(&mut self, raw_bytes: &'a mut &'_ str, depth: usize) {}
117
118    /// Called for BER unknown objects
119    fn visit_ber_unknown_mut(&mut self, ber: &'_ mut Any<'a>, depth: usize) {}
120
121    /// Perform a BFS traversal of the BER object, calling the visitor functions during he traversal
122    ///
123    /// Usually, this method should not be redefined (unless implementing a custom traversal)
124    fn run(&mut self, ber: &'a mut BerObject<'a>) {
125        visit_ber_bfs_mut(self, ber, 0)
126    }
127
128    /// Perform a BFS traversal of the BER object, calling the visitor functions during he traversal
129    ///
130    /// Start at specified depth.
131    ///
132    /// Usually, this method should not be redefined (unless implementing a custom traversal)
133    fn run_at(&mut self, ber: &'a mut BerObject<'a>, depth: usize) {
134        visit_ber_bfs_mut(self, ber, depth)
135    }
136}
137
138fn visit_ber_bfs_mut<'a, V>(v: &mut V, ber: &'a mut BerObject<'a>, depth: usize)
139where
140    V: VisitMut<'a> + ?Sized,
141{
142    v.visit_ber_mut(ber, depth);
143
144    match ber.content {
145        BerObjectContent::BitString(ref mut ignored, ref mut data) => {
146            v.visit_ber_bitstring_mut(ignored, data, depth);
147        }
148        BerObjectContent::BmpString(ref mut s) => v.visit_ber_bmpstring_mut(s, depth),
149        BerObjectContent::Boolean(ref mut b) => v.visit_ber_boolean_mut(b, depth),
150        BerObjectContent::EndOfContent => v.visit_ber_endofcontent_mut(depth),
151        BerObjectContent::Enum(ref mut val) => v.visit_ber_enum_mut(val, depth),
152        BerObjectContent::GeneralString(ref mut s) => v.visit_ber_generalstring_mut(s, depth),
153        BerObjectContent::GeneralizedTime(ref t) => v.visit_ber_generalizedtime_mut(t, depth),
154        BerObjectContent::GraphicString(ref mut s) => v.visit_ber_graphicstring_mut(s, depth),
155        BerObjectContent::IA5String(ref mut s) => v.visit_ber_ia5string_mut(s, depth),
156        BerObjectContent::Integer(ref mut s) => v.visit_ber_integer_mut(s, depth),
157        BerObjectContent::Null => v.visit_ber_null_mut(depth),
158        BerObjectContent::NumericString(ref mut s) => v.visit_ber_numericstring_mut(s, depth),
159        BerObjectContent::OID(ref mut oid) => v.visit_ber_oid_mut(oid, depth),
160        BerObjectContent::ObjectDescriptor(ref mut s) => v.visit_ber_objectdescriptor_mut(s, depth),
161        BerObjectContent::OctetString(ref mut b) => v.visit_ber_octetstring_mut(b, depth),
162        BerObjectContent::Optional(ref mut obj) => {
163            let opt = obj.as_mut().map(|b| b.as_mut());
164            v.visit_ber_optional_mut(opt, depth)
165        }
166        BerObjectContent::PrintableString(ref mut s) => v.visit_ber_printablestring_mut(s, depth),
167        BerObjectContent::RelativeOID(ref mut oid) => v.visit_ber_relative_oid_mut(oid, depth),
168        BerObjectContent::Sequence(ref mut l) => {
169            v.visit_ber_sequence_mut(l, depth);
170            for item in l.iter_mut() {
171                visit_ber_bfs_mut(v, item, depth + 1);
172            }
173        }
174        BerObjectContent::Set(ref mut l) => {
175            v.visit_ber_set_mut(l, depth);
176            for item in l.iter_mut() {
177                visit_ber_bfs_mut(v, item, depth + 1);
178            }
179        }
180        BerObjectContent::T61String(ref mut s) => v.visit_ber_teletexstring_mut(s, depth),
181        BerObjectContent::Tagged(ref mut class, ref mut tag, ref mut obj) => {
182            v.visit_ber_tagged_mut(class, tag, obj.as_mut(), depth)
183        }
184        BerObjectContent::UTCTime(ref t) => v.visit_ber_utctime_mut(t, depth),
185        BerObjectContent::UTF8String(ref mut s) => v.visit_ber_utf8string_mut(s, depth),
186        BerObjectContent::UniversalString(ref mut b) => v.visit_ber_universalstring_mut(b, depth),
187        BerObjectContent::Unknown(ref mut inner) => v.visit_ber_unknown_mut(inner, depth),
188        BerObjectContent::VideotexString(ref mut s) => v.visit_ber_videotextstring_mut(s, depth),
189        BerObjectContent::VisibleString(ref mut s) => v.visit_ber_visiblestring_mut(s, depth),
190    }
191}
192
193#[cfg(test)]
194mod tests {
195    use super::VisitMut;
196    use crate::ber::BerObject;
197
198    #[derive(Debug)]
199    struct BerObjectVisitor {}
200
201    impl<'a> VisitMut<'a> for BerObjectVisitor {
202        fn visit_ber_mut(&mut self, ber: &'_ mut BerObject<'a>, depth: usize) {
203            eprintln!("Depth {}: Object with tag {}", depth, ber.tag());
204        }
205    }
206}