Coverage Report

Created: 2026-05-16 07:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/der-parser-8.2.0/src/ber/visit.rs
Line
Count
Source
1
use super::{BerObject, BerObjectContent, BitStringObject};
2
use asn1_rs::{ASN1DateTime, Any, Class, Oid, Tag};
3
4
/// BER object tree traversal to walk a shared borrow of a BER object
5
///
6
/// When implementing your own visitor, define your own `visit_ber_xxx` methods.
7
///
8
/// Note that `visit_ber` is called for every object, so if you implement multiple visitor methods they
9
/// will be called multiple times for the same object. Generally, if `visit_ber` is implemented, then other
10
/// methods are not needed.
11
///
12
/// For example, on a `Sequence` item, `visit_ber` is called first, then `visit_ber_sequence`, and then
13
/// `visit_ber` for every sequence object (recursively).
14
///
15
/// Entry point: use the [`Visit::run`] or [`Visit::run_at`] methods.
16
///
17
/// Visitor functions
18
#[allow(unused_variables)]
19
pub trait Visit<'a> {
20
    /// Called for every BER object
21
0
    fn visit_ber(&mut self, ber: &'_ BerObject<'a>, depth: usize) {}
22
23
    /// Called for BER bitstring objects
24
0
    fn visit_ber_bitstring(&mut self, ignored: u8, data: &'a BitStringObject, depth: usize) {}
25
26
    /// Called for BER bmpstring objects
27
0
    fn visit_ber_bmpstring(&mut self, s: &'a str, depth: usize) {}
28
29
    /// Called for BER boolean objects
30
0
    fn visit_ber_boolean(&mut self, b: bool, depth: usize) {}
31
32
    /// Called for BER end-of-content objects
33
0
    fn visit_ber_endofcontent(&mut self, depth: usize) {}
34
35
    /// Called for BER enum objects
36
0
    fn visit_ber_enum(&mut self, e: u64, depth: usize) {}
37
38
    /// Called for BER generalstring objects
39
0
    fn visit_ber_generalstring(&mut self, s: &'a str, depth: usize) {}
40
41
    /// Called for BER generalizedtime objects
42
0
    fn visit_ber_generalizedtime(&mut self, t: &'a ASN1DateTime, depth: usize) {}
43
44
    /// Called for BER graphicstring objects
45
0
    fn visit_ber_graphicstring(&mut self, s: &'a str, depth: usize) {}
46
47
    /// Called for BER ia5string objects
48
0
    fn visit_ber_ia5string(&mut self, s: &'a str, depth: usize) {}
49
50
    /// Called for BER integer objects
51
0
    fn visit_ber_integer(&mut self, raw_bytes: &'a [u8], depth: usize) {}
52
53
    /// Called for BER null objects
54
0
    fn visit_ber_null(&mut self, depth: usize) {}
55
56
    /// Called for BER numericstring objects
57
0
    fn visit_ber_numericstring(&mut self, s: &'a str, depth: usize) {}
58
59
    /// Called for BER OID objects
60
0
    fn visit_ber_oid(&mut self, oid: &'a Oid, depth: usize) {}
61
62
    /// Called for BER object descriptor objects
63
0
    fn visit_ber_objectdescriptor(&mut self, s: &'a str, depth: usize) {}
64
65
    /// Called for BER octetstring objects
66
0
    fn visit_ber_octetstring(&mut self, b: &'a [u8], depth: usize) {}
67
68
    /// Called for BER optional objects
69
0
    fn visit_ber_optional(&mut self, obj: Option<&'a BerObject<'a>>, depth: usize) {}
70
71
    /// Called for BER printablestring objects
72
0
    fn visit_ber_printablestring(&mut self, s: &'a str, depth: usize) {}
73
74
    /// Called for BER relative OID objects
75
0
    fn visit_ber_relative_oid(&mut self, oid: &'a Oid, depth: usize) {}
76
77
    /// Called for BER sequence objects
78
0
    fn visit_ber_sequence(&mut self, ber: &'_ [BerObject<'a>], depth: usize) {}
79
80
    /// Called for BER set objects
81
0
    fn visit_ber_set(&mut self, ber: &'_ [BerObject<'a>], depth: usize) {}
82
83
    /// Called for BER teletexstring objects
84
0
    fn visit_ber_teletexstring(&mut self, s: &'a str, depth: usize) {}
85
86
    /// Called for BER tagged objects
87
0
    fn visit_ber_tagged(&mut self, class: Class, tag: Tag, obj: &'_ BerObject<'a>, depth: usize) {}
88
89
    /// Called for BER generalizedtime objects
90
0
    fn visit_ber_utctime(&mut self, t: &'a ASN1DateTime, depth: usize) {}
91
92
    /// Called for BER utf8string objects
93
0
    fn visit_ber_utf8string(&mut self, s: &'a str, depth: usize) {}
94
95
    /// Called for BER universalstring objects
96
0
    fn visit_ber_universalstring(&mut self, raw_bytes: &'a [u8], depth: usize) {}
97
98
    /// Called for BER videotexstring objects
99
0
    fn visit_ber_videotextstring(&mut self, raw_bytes: &'a str, depth: usize) {}
100
101
    /// Called for BER visiblestring objects
102
0
    fn visit_ber_visiblestring(&mut self, raw_bytes: &'a str, depth: usize) {}
103
104
    /// Called for BER unknown objects
105
0
    fn visit_ber_unknown(&mut self, ber: &'_ Any<'a>, depth: usize) {}
106
107
    /// Perform a BFS traversal of the BER object, calling the visitor functions during he traversal
108
    ///
109
    /// Usually, this method should not be redefined (unless implementing a custom traversal)
110
0
    fn run(&mut self, ber: &'a BerObject<'a>) {
111
0
        visit_ber_bfs(self, ber, 0)
112
0
    }
113
114
    /// Perform a BFS traversal of the BER object, calling the visitor functions during he traversal
115
    ///
116
    /// Start at specified depth.
117
    ///
118
    /// Usually, this method should not be redefined (unless implementing a custom traversal)
119
0
    fn run_at(&mut self, ber: &'a BerObject<'a>, depth: usize) {
120
0
        visit_ber_bfs(self, ber, depth)
121
0
    }
122
}
123
124
0
fn visit_ber_bfs<'a, V>(v: &mut V, ber: &'a BerObject<'a>, depth: usize)
125
0
where
126
0
    V: Visit<'a> + ?Sized,
127
{
128
0
    v.visit_ber(ber, depth);
129
130
0
    match ber.content {
131
0
        BerObjectContent::BitString(ignored, ref data) => {
132
0
            v.visit_ber_bitstring(ignored, data, depth);
133
0
        }
134
0
        BerObjectContent::BmpString(s) => v.visit_ber_bmpstring(s, depth),
135
0
        BerObjectContent::Boolean(b) => v.visit_ber_boolean(b, depth),
136
0
        BerObjectContent::EndOfContent => v.visit_ber_endofcontent(depth),
137
0
        BerObjectContent::Enum(val) => v.visit_ber_enum(val, depth),
138
0
        BerObjectContent::GeneralString(s) => v.visit_ber_generalstring(s, depth),
139
0
        BerObjectContent::GeneralizedTime(ref t) => v.visit_ber_generalizedtime(t, depth),
140
0
        BerObjectContent::GraphicString(s) => v.visit_ber_graphicstring(s, depth),
141
0
        BerObjectContent::IA5String(s) => v.visit_ber_ia5string(s, depth),
142
0
        BerObjectContent::Integer(s) => v.visit_ber_integer(s, depth),
143
0
        BerObjectContent::Null => v.visit_ber_null(depth),
144
0
        BerObjectContent::NumericString(s) => v.visit_ber_numericstring(s, depth),
145
0
        BerObjectContent::OID(ref oid) => v.visit_ber_oid(oid, depth),
146
0
        BerObjectContent::ObjectDescriptor(s) => v.visit_ber_objectdescriptor(s, depth),
147
0
        BerObjectContent::OctetString(b) => v.visit_ber_octetstring(b, depth),
148
0
        BerObjectContent::Optional(ref obj) => {
149
0
            let opt = obj.as_ref().map(|b| b.as_ref());
150
0
            v.visit_ber_optional(opt, depth)
151
        }
152
0
        BerObjectContent::PrintableString(s) => v.visit_ber_printablestring(s, depth),
153
0
        BerObjectContent::RelativeOID(ref oid) => v.visit_ber_relative_oid(oid, depth),
154
0
        BerObjectContent::Sequence(ref l) => {
155
0
            v.visit_ber_sequence(l, depth);
156
0
            for item in l.iter() {
157
0
                visit_ber_bfs(v, item, depth + 1);
158
0
            }
159
        }
160
0
        BerObjectContent::Set(ref l) => {
161
0
            v.visit_ber_set(l, depth);
162
0
            for item in l.iter() {
163
0
                visit_ber_bfs(v, item, depth + 1);
164
0
            }
165
        }
166
0
        BerObjectContent::T61String(s) => v.visit_ber_teletexstring(s, depth),
167
0
        BerObjectContent::Tagged(class, tag, ref obj) => {
168
0
            v.visit_ber_tagged(class, tag, obj.as_ref(), depth)
169
        }
170
0
        BerObjectContent::UTCTime(ref t) => v.visit_ber_utctime(t, depth),
171
0
        BerObjectContent::UTF8String(s) => v.visit_ber_utf8string(s, depth),
172
0
        BerObjectContent::UniversalString(b) => v.visit_ber_universalstring(b, depth),
173
0
        BerObjectContent::Unknown(ref inner) => v.visit_ber_unknown(inner, depth),
174
0
        BerObjectContent::VideotexString(s) => v.visit_ber_videotextstring(s, depth),
175
0
        BerObjectContent::VisibleString(s) => v.visit_ber_visiblestring(s, depth),
176
    }
177
0
}
178
179
#[cfg(test)]
180
mod 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
}