1use super::{BerObject, BerObjectContent, BitStringObject};
2use asn1_rs::{ASN1DateTime, Any, Class, Oid, Tag};
3
4#[allow(unused_variables)]
19pub trait Visit<'a> {
20 fn visit_ber(&mut self, ber: &'_ BerObject<'a>, depth: usize) {}
22
23 fn visit_ber_bitstring(&mut self, ignored: u8, data: &'a BitStringObject, depth: usize) {}
25
26 fn visit_ber_bmpstring(&mut self, s: &'a str, depth: usize) {}
28
29 fn visit_ber_boolean(&mut self, b: bool, depth: usize) {}
31
32 fn visit_ber_endofcontent(&mut self, depth: usize) {}
34
35 fn visit_ber_enum(&mut self, e: u64, depth: usize) {}
37
38 fn visit_ber_generalstring(&mut self, s: &'a str, depth: usize) {}
40
41 fn visit_ber_generalizedtime(&mut self, t: &'a ASN1DateTime, depth: usize) {}
43
44 fn visit_ber_graphicstring(&mut self, s: &'a str, depth: usize) {}
46
47 fn visit_ber_ia5string(&mut self, s: &'a str, depth: usize) {}
49
50 fn visit_ber_integer(&mut self, raw_bytes: &'a [u8], depth: usize) {}
52
53 fn visit_ber_null(&mut self, depth: usize) {}
55
56 fn visit_ber_numericstring(&mut self, s: &'a str, depth: usize) {}
58
59 fn visit_ber_oid(&mut self, oid: &'a Oid, depth: usize) {}
61
62 fn visit_ber_objectdescriptor(&mut self, s: &'a str, depth: usize) {}
64
65 fn visit_ber_octetstring(&mut self, b: &'a [u8], depth: usize) {}
67
68 fn visit_ber_optional(&mut self, obj: Option<&'a BerObject<'a>>, depth: usize) {}
70
71 fn visit_ber_printablestring(&mut self, s: &'a str, depth: usize) {}
73
74 fn visit_ber_relative_oid(&mut self, oid: &'a Oid, depth: usize) {}
76
77 fn visit_ber_sequence(&mut self, ber: &'_ [BerObject<'a>], depth: usize) {}
79
80 fn visit_ber_set(&mut self, ber: &'_ [BerObject<'a>], depth: usize) {}
82
83 fn visit_ber_teletexstring(&mut self, s: &'a str, depth: usize) {}
85
86 fn visit_ber_tagged(&mut self, class: Class, tag: Tag, obj: &'_ BerObject<'a>, depth: usize) {}
88
89 fn visit_ber_utctime(&mut self, t: &'a ASN1DateTime, depth: usize) {}
91
92 fn visit_ber_utf8string(&mut self, s: &'a str, depth: usize) {}
94
95 fn visit_ber_universalstring(&mut self, raw_bytes: &'a [u8], depth: usize) {}
97
98 fn visit_ber_videotextstring(&mut self, raw_bytes: &'a str, depth: usize) {}
100
101 fn visit_ber_visiblestring(&mut self, raw_bytes: &'a str, depth: usize) {}
103
104 fn visit_ber_unknown(&mut self, ber: &'_ Any<'a>, depth: usize) {}
106
107 fn run(&mut self, ber: &'a BerObject<'a>) {
111 visit_ber_bfs(self, ber, 0)
112 }
113
114 fn run_at(&mut self, ber: &'a BerObject<'a>, depth: usize) {
120 visit_ber_bfs(self, ber, depth)
121 }
122}
123
124fn visit_ber_bfs<'a, V>(v: &mut V, ber: &'a BerObject<'a>, depth: usize)
125where
126 V: Visit<'a> + ?Sized,
127{
128 v.visit_ber(ber, depth);
129
130 match ber.content {
131 BerObjectContent::BitString(ignored, ref data) => {
132 v.visit_ber_bitstring(ignored, data, depth);
133 }
134 BerObjectContent::BmpString(s) => v.visit_ber_bmpstring(s, depth),
135 BerObjectContent::Boolean(b) => v.visit_ber_boolean(b, depth),
136 BerObjectContent::EndOfContent => v.visit_ber_endofcontent(depth),
137 BerObjectContent::Enum(val) => v.visit_ber_enum(val, depth),
138 BerObjectContent::GeneralString(s) => v.visit_ber_generalstring(s, depth),
139 BerObjectContent::GeneralizedTime(ref t) => v.visit_ber_generalizedtime(t, depth),
140 BerObjectContent::GraphicString(s) => v.visit_ber_graphicstring(s, depth),
141 BerObjectContent::IA5String(s) => v.visit_ber_ia5string(s, depth),
142 BerObjectContent::Integer(s) => v.visit_ber_integer(s, depth),
143 BerObjectContent::Null => v.visit_ber_null(depth),
144 BerObjectContent::NumericString(s) => v.visit_ber_numericstring(s, depth),
145 BerObjectContent::OID(ref oid) => v.visit_ber_oid(oid, depth),
146 BerObjectContent::ObjectDescriptor(s) => v.visit_ber_objectdescriptor(s, depth),
147 BerObjectContent::OctetString(b) => v.visit_ber_octetstring(b, depth),
148 BerObjectContent::Optional(ref obj) => {
149 let opt = obj.as_ref().map(|b| b.as_ref());
150 v.visit_ber_optional(opt, depth)
151 }
152 BerObjectContent::PrintableString(s) => v.visit_ber_printablestring(s, depth),
153 BerObjectContent::RelativeOID(ref oid) => v.visit_ber_relative_oid(oid, depth),
154 BerObjectContent::Sequence(ref l) => {
155 v.visit_ber_sequence(l, depth);
156 for item in l.iter() {
157 visit_ber_bfs(v, item, depth + 1);
158 }
159 }
160 BerObjectContent::Set(ref l) => {
161 v.visit_ber_set(l, depth);
162 for item in l.iter() {
163 visit_ber_bfs(v, item, depth + 1);
164 }
165 }
166 BerObjectContent::T61String(s) => v.visit_ber_teletexstring(s, depth),
167 BerObjectContent::Tagged(class, tag, ref obj) => {
168 v.visit_ber_tagged(class, tag, obj.as_ref(), depth)
169 }
170 BerObjectContent::UTCTime(ref t) => v.visit_ber_utctime(t, depth),
171 BerObjectContent::UTF8String(s) => v.visit_ber_utf8string(s, depth),
172 BerObjectContent::UniversalString(b) => v.visit_ber_universalstring(b, depth),
173 BerObjectContent::Unknown(ref inner) => v.visit_ber_unknown(inner, depth),
174 BerObjectContent::VideotexString(s) => v.visit_ber_videotextstring(s, depth),
175 BerObjectContent::VisibleString(s) => v.visit_ber_visiblestring(s, depth),
176 }
177}
178
179#[cfg(test)]
180mod tests {
181 use super::Visit;
182 use crate::ber::BerObject;
183
184 #[derive(Debug)]
185 struct BerObjectVisitor {}
186
187 impl<'a> Visit<'a> for BerObjectVisitor {
188 fn visit_ber(&mut self, ber: &'_ BerObject<'a>, depth: usize) {
189 eprintln!("Depth {}: Object with tag {}", depth, ber.tag());
190 }
191 }
192}