Coverage Report

Created: 2021-11-03 07:11

/rust/registry/src/github.com-1ecc6299db9ec823/der-parser-4.0.2/src/ber/ber.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::ber::bytes_to_u64;
2
use crate::error::BerError;
3
use crate::oid::Oid;
4
use rusticata_macros::newtype_enum;
5
use std::convert::AsRef;
6
use std::convert::From;
7
use std::convert::TryFrom;
8
use std::ops::Index;
9
use std::vec::Vec;
10
11
0
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
Unexecuted instantiation: <der_parser::ber::ber::BerClassFromIntError as core::cmp::PartialEq>::ne
Unexecuted instantiation: <der_parser::ber::ber::BerClassFromIntError as core::cmp::PartialEq>::eq
12
pub struct BerClassFromIntError(pub(crate) ());
13
14
/// BER Object class of tag
15
464k
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
16
#[repr(u8)]
17
pub enum BerClass {
18
    Universal = 0b00,
19
    Application = 0b01,
20
    ContextSpecific = 0b10,
21
    Private = 0b11,
22
}
23
24
/// Defined in X.680 section 8.4
25
/// X.690 doesn't specify the maxmimum tag size so we're assuming that people
26
/// aren't going to need anything more than a u32.
27
5.25M
#[derive(Clone, Copy, PartialEq, Eq)]
<der_parser::ber::ber::BerTag as core::cmp::PartialEq>::eq
Line
Count
Source
27
526k
#[derive(Clone, Copy, PartialEq, Eq)]
<der_parser::ber::ber::BerTag as core::cmp::PartialEq>::ne
Line
Count
Source
27
4.73M
#[derive(Clone, Copy, PartialEq, Eq)]
28
pub struct BerTag(pub u32);
29
30
newtype_enum! {
31
impl debug BerTag {
32
    EndOfContent = 0x0,
33
    Boolean = 0x1,
34
    Integer = 0x2,
35
    BitString = 0x3,
36
    OctetString = 0x4,
37
    Null = 0x05,
38
    Oid = 0x06,
39
    ObjDescriptor = 0x07,
40
    External = 0x08,
41
    RealType = 0x09,
42
    Enumerated = 0xa,
43
    EmbeddedPdv = 0xb,
44
    Utf8String = 0xc,
45
    RelativeOid = 0xd,
46
47
    Sequence = 0x10,
48
    Set = 0x11,
49
    NumericString = 0x12,
50
    PrintableString = 0x13,
51
    T61String = 0x14,
52
53
    Ia5String = 0x16,
54
    UtcTime = 0x17,
55
    GeneralizedTime = 0x18,
56
57
    GeneralString = 27, // 0x1b
58
59
    BmpString = 0x1e,
60
61
    Invalid = 0xff,
62
}
63
}
64
65
/// Representation of a DER-encoded (X.690) object
66
7.60k
#[derive(Debug, Clone, PartialEq)]
Unexecuted instantiation: <der_parser::ber::ber::BerObject as core::cmp::PartialEq>::ne
Unexecuted instantiation: <der_parser::ber::ber::BerObject as core::cmp::PartialEq>::eq
67
pub struct BerObject<'a> {
68
    pub header: BerObjectHeader<'a>,
69
    pub content: BerObjectContent<'a>,
70
}
71
72
7.60k
#[derive(Clone, Copy, Debug)]
73
pub struct BerObjectHeader<'a> {
74
    pub class: BerClass,
75
    pub structured: u8,
76
    pub tag: BerTag,
77
    pub len: u64,
78
79
    pub raw_tag: Option<&'a [u8]>,
80
}
81
82
7.60k
#[derive(Debug, Clone, PartialEq)]
Unexecuted instantiation: <der_parser::ber::ber::BerObjectContent as core::cmp::PartialEq>::eq
Unexecuted instantiation: <der_parser::ber::ber::BerObjectContent as core::cmp::PartialEq>::ne
83
pub enum BerObjectContent<'a> {
84
    EndOfContent,
85
    Boolean(bool),
86
    Integer(&'a [u8]),
87
    BitString(u8, BitStringObject<'a>),
88
    OctetString(&'a [u8]),
89
    Null,
90
    Enum(u64),
91
    OID(Oid<'a>),
92
    RelativeOID(Oid<'a>),
93
    NumericString(&'a str),
94
    PrintableString(&'a str),
95
    IA5String(&'a str),
96
    UTF8String(&'a str),
97
    T61String(&'a [u8]),
98
99
    BmpString(&'a [u8]),
100
101
    Sequence(Vec<BerObject<'a>>),
102
    Set(Vec<BerObject<'a>>),
103
104
    UTCTime(&'a [u8]),
105
    GeneralizedTime(&'a [u8]),
106
107
    GeneralString(&'a [u8]),
108
109
    ContextSpecific(BerTag, Option<Box<BerObject<'a>>>),
110
    Unknown(BerTag, &'a [u8]),
111
}
112
113
impl TryFrom<u8> for BerClass {
114
    type Error = BerClassFromIntError;
115
116
    #[inline]
117
10.2M
    fn try_from(value: u8) -> Result<Self, Self::Error> {
118
10.2M
        match value {
119
6.60M
            0b00 => Ok(BerClass::Universal),
120
2.68M
            0b01 => Ok(BerClass::Application),
121
396k
            0b10 => Ok(BerClass::ContextSpecific),
122
550k
            0b11 => Ok(BerClass::Private),
123
0
            _ => Err(BerClassFromIntError(())),
124
        }
125
10.2M
    }
126
}
127
128
impl<'a> BerObjectHeader<'a> {
129
    /// Test if object class is Universal
130
    #[inline]
131
0
    pub fn is_universal(&self) -> bool {
132
0
        self.class == BerClass::Universal
133
0
    }
134
    /// Test if object class is Application
135
    #[inline]
136
28.4k
    pub fn is_application(&self) -> bool {
137
28.4k
        self.class == BerClass::Application
138
28.4k
    }
139
    /// Test if object class is Context-specific
140
    #[inline]
141
0
    pub fn is_contextspecific(&self) -> bool {
142
0
        self.class == BerClass::ContextSpecific
143
0
    }
144
    /// Test if object class is Private
145
    #[inline]
146
0
    pub fn is_private(&self) -> bool {
147
0
        self.class == BerClass::Private
148
0
    }
149
150
    /// Test if object is primitive
151
    #[inline]
152
0
    pub fn is_primitive(&self) -> bool {
153
0
        self.structured == 0
154
0
    }
155
    /// Test if object is constructed
156
    #[inline]
157
3.91M
    pub fn is_constructed(&self) -> bool {
158
3.91M
        self.structured == 1
159
3.91M
    }
160
}
161
162
impl<'a> BerObject<'a> {
163
    /// Build a BerObject from a header and content.
164
    /// Note: values are not checked, so the tag can be different from the real content, or flags
165
    /// can be invalid.
166
4.43M
    pub fn from_header_and_content<'hdr>(
167
4.43M
        header: BerObjectHeader<'hdr>,
168
4.43M
        content: BerObjectContent<'hdr>,
169
4.43M
    ) -> BerObject<'hdr> {
170
4.43M
        BerObject { header, content }
171
4.43M
    }
172
    /// Build a BerObject from its content, using default flags (no class, correct tag,
173
    /// and structured flag set only for Set and Sequence)
174
5.45k
    pub fn from_obj(c: BerObjectContent) -> BerObject {
175
5.45k
        let class = BerClass::Universal;
176
5.45k
        let tag = c.tag();
177
5.45k
        let structured = match tag {
178
0
            BerTag::Sequence | BerTag::Set => 1,
179
5.45k
            _ => 0,
180
        };
181
5.45k
        let header = BerObjectHeader {
182
5.45k
            class,
183
5.45k
            structured,
184
5.45k
            tag,
185
5.45k
            len: 0,
186
5.45k
            raw_tag: None,
187
5.45k
        };
188
5.45k
        BerObject { header, content: c }
189
5.45k
    }
190
191
    /// Build a DER integer object from a slice containing an encoded integer
192
0
    pub fn from_int_slice(i: &'a [u8]) -> BerObject<'a> {
193
0
        let header = BerObjectHeader {
194
0
            class: BerClass::Universal,
195
0
            structured: 0,
196
0
            tag: BerTag::Integer,
197
0
            len: 0,
198
0
            raw_tag: None,
199
0
        };
200
0
        BerObject {
201
0
            header,
202
0
            content: BerObjectContent::Integer(i),
203
0
        }
204
0
    }
205
206
    /// Set a tag for the BER object
207
0
    pub fn set_raw_tag(self, raw_tag: Option<&'a [u8]>) -> BerObject {
208
0
        let header = BerObjectHeader {
209
0
            raw_tag,
210
0
            ..self.header
211
0
        };
212
0
        BerObject { header, ..self }
213
0
    }
214
215
    /// Build a DER sequence object from a vector of DER objects
216
0
    pub fn from_seq(l: Vec<BerObject>) -> BerObject {
217
0
        BerObject::from_obj(BerObjectContent::Sequence(l))
218
0
    }
219
220
    /// Build a DER set object from a vector of DER objects
221
0
    pub fn from_set(l: Vec<BerObject>) -> BerObject {
222
0
        BerObject::from_obj(BerObjectContent::Set(l))
223
0
    }
224
225
    /// Build a BER header from this object content
226
    #[deprecated(
227
        since = "0.5.0",
228
        note = "please use `obj.header` or `obj.header.clone()` instead"
229
    )]
230
0
    pub fn to_header(&self) -> BerObjectHeader {
231
0
        self.header
232
0
    }
233
234
    /// Attempt to read integer value from DER object.
235
    /// This can fail if the object is not an integer, or if it is too large.
236
    ///
237
    /// ```rust
238
    /// # extern crate der_parser;
239
    /// # use der_parser::ber::{BerObject,BerObjectContent};
240
    /// let der_int  = BerObject::from_int_slice(b"\x01\x00\x01");
241
    /// assert_eq!(
242
    ///     der_int.as_u64(),
243
    ///     Ok(0x10001)
244
    /// );
245
    /// ```
246
0
    pub fn as_u64(&self) -> Result<u64, BerError> {
247
0
        self.content.as_u64()
248
0
    }
249
250
    /// Attempt to read integer value from DER object.
251
    /// This can fail if the object is not an integer, or if it is too large.
252
    ///
253
    /// ```rust
254
    /// # extern crate der_parser;
255
    /// # use der_parser::ber::{BerObject,BerObjectContent};
256
    /// let der_int  = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01"));
257
    /// assert_eq!(
258
    ///     der_int.as_u32(),
259
    ///     Ok(0x10001)
260
    /// );
261
    /// ```
262
915k
    pub fn as_u32(&self) -> Result<u32, BerError> {
263
915k
        self.content.as_u32()
264
915k
    }
265
266
    /// Attempt to read integer value from DER object.
267
    /// This can fail if the object is not a boolean.
268
0
    pub fn as_bool(&self) -> Result<bool, BerError> {
269
0
        self.content.as_bool()
270
0
    }
271
272
    /// Attempt to read an OID value from DER object.
273
    /// This can fail if the object is not an OID.
274
0
    pub fn as_oid(&self) -> Result<&Oid<'a>, BerError> {
275
0
        self.content.as_oid()
276
0
    }
277
278
    /// Attempt to read an OID value from DER object.
279
    /// This can fail if the object is not an OID.
280
32.1k
    pub fn as_oid_val(&self) -> Result<Oid<'a>, BerError> {
281
32.1k
        self.content.as_oid_val()
282
32.1k
    }
283
284
    /// Attempt to read the content from a context-specific DER object.
285
    /// This can fail if the object is not context-specific.
286
    ///
287
    /// Note: the object is cloned.
288
832
    pub fn as_context_specific(&self) -> Result<(BerTag, Option<Box<BerObject<'a>>>), BerError> {
289
832
        self.content.as_context_specific()
290
832
    }
291
292
    /// Attempt to read a reference to a BitString value from DER object.
293
    /// This can fail if the object is not an BitString.
294
    ///
295
    /// Note that this function returns a reference to the BitString. To get an owned value,
296
    /// use [`as_bitstring`](struct.BerObject.html#method.as_bitstring)
297
0
    pub fn as_bitstring_ref(&self) -> Result<&BitStringObject, BerError> {
298
0
        self.content.as_bitstring_ref()
299
0
    }
300
301
    /// Attempt to read a BitString value from DER object.
302
    /// This can fail if the object is not an BitString.
303
0
    pub fn as_bitstring(&'a self) -> Result<BitStringObject<'a>, BerError> {
304
0
        self.content.as_bitstring()
305
0
    }
306
307
    /// Attempt to extract the list of objects from a DER sequence.
308
    /// This can fail if the object is not a sequence.
309
0
    pub fn as_sequence(&self) -> Result<&Vec<BerObject<'a>>, BerError> {
310
0
        self.content.as_sequence()
311
0
    }
312
313
    /// Attempt to extract the list of objects from a DER set.
314
    /// This can fail if the object is not a set.
315
0
    pub fn as_set(&self) -> Result<&Vec<BerObject<'a>>, BerError> {
316
0
        self.content.as_set()
317
0
    }
318
319
    /// Attempt to get the content from a DER object, as a slice.
320
    /// This can fail if the object does not contain a type directly equivalent to a slice (e.g a
321
    /// sequence).
322
    /// This function mostly concerns string types, integers, or unknown DER objects.
323
65.6k
    pub fn as_slice(&self) -> Result<&'a [u8], BerError> {
324
65.6k
        self.content.as_slice()
325
65.6k
    }
326
327
    /// Attempt to get the content from a DER object, as a str.
328
    /// This can fail if the object does not contain a string type.
329
    ///
330
    /// Only NumericString, PrintableString, UTF8String and IA5String
331
    /// are considered here. Other string types can be read using `as_slice`.
332
0
    pub fn as_str(&self) -> Result<&'a str, BerError> {
333
0
        self.content.as_str()
334
0
    }
335
336
    /// Test if object class is Universal
337
0
    pub fn is_universal(&self) -> bool {
338
0
        self.header.class == BerClass::Universal
339
0
    }
340
    /// Test if object class is Application
341
0
    pub fn is_application(&self) -> bool {
342
0
        self.header.class == BerClass::Application
343
0
    }
344
    /// Test if object class is Context-specific
345
0
    pub fn is_contextspecific(&self) -> bool {
346
0
        self.header.class == BerClass::ContextSpecific
347
0
    }
348
    /// Test if object class is Private
349
0
    pub fn is_private(&self) -> bool {
350
0
        self.header.class == BerClass::Private
351
0
    }
352
353
    /// Test if object is primitive
354
0
    pub fn is_primitive(&self) -> bool {
355
0
        self.header.structured == 0
356
0
    }
357
    /// Test if object is constructed
358
0
    pub fn is_constructed(&self) -> bool {
359
0
        self.header.structured == 1
360
0
    }
361
}
362
363
/// Build a DER object from an OID.
364
impl<'a> From<Oid<'a>> for BerObject<'a> {
365
0
    fn from(oid: Oid<'a>) -> BerObject<'a> {
366
0
        BerObject::from_obj(BerObjectContent::OID(oid))
367
0
    }
368
}
369
370
/// Build a DER object from a BerObjectContent.
371
impl<'a> From<BerObjectContent<'a>> for BerObject<'a> {
372
0
    fn from(obj: BerObjectContent<'a>) -> BerObject<'a> {
373
0
        BerObject::from_obj(obj)
374
0
    }
375
}
376
377
/// Replacement function for Option.xor (>= 1.37)
378
#[inline]
379
pub fn xor_option<T>(opta: Option<T>, optb: Option<T>) -> Option<T> {
380
0
    match (opta, optb) {
381
0
        (Some(a), None) => Some(a),
382
0
        (None, Some(b)) => Some(b),
383
0
        _ => None,
384
    }
385
0
}
386
387
/// Compare two BER headers. `len` fields are compared only if both objects have it set (same for `raw_tag`)
388
impl<'a> PartialEq<BerObjectHeader<'a>> for BerObjectHeader<'a> {
389
0
    fn eq(&self, other: &BerObjectHeader) -> bool {
390
0
        self.class == other.class
391
0
            && self.tag == other.tag
392
0
            && self.structured == other.structured
393
            && {
394
0
                if self.len != 0 && other.len != 0 {
395
0
                    self.len == other.len
396
                } else {
397
0
                    true
398
                }
399
            }
400
            && {
401
                // it tag is present for both, compare it
402
0
                if xor_option(self.raw_tag, other.raw_tag).is_none() {
403
0
                    self.raw_tag == other.raw_tag
404
                } else {
405
0
                    true
406
                }
407
            }
408
0
    }
409
}
410
411
impl<'a> BerObjectContent<'a> {
412
4.68k
    pub fn as_u64(&self) -> Result<u64, BerError> {
413
4.68k
        match *self {
414
4.68k
            BerObjectContent::Integer(i) => bytes_to_u64(i),
415
0
            BerObjectContent::Enum(i) => Ok(i as u64),
416
0
            _ => Err(BerError::BerTypeError),
417
        }
418
4.68k
    }
419
420
918k
    pub fn as_u32(&self) -> Result<u32, BerError> {
421
918k
        match *self {
422
908k
            BerObjectContent::Integer(i) => bytes_to_u64(i).and_then(|x| {
423
908k
                if x > u64::from(std::u32::MAX) {
424
359
                    Err(BerError::IntegerTooLarge)
425
                } else {
426
908k
                    Ok(x as u32)
427
                }
428
908k
            }),
429
40
            BerObjectContent::Enum(i) => {
430
40
                if i > u64::from(std::u32::MAX) {
431
16
                    Err(BerError::IntegerTooLarge)
432
                } else {
433
24
                    Ok(i as u32)
434
                }
435
            }
436
9.52k
            _ => Err(BerError::BerTypeError),
437
        }
438
918k
    }
439
440
0
    pub fn as_bool(&self) -> Result<bool, BerError> {
441
0
        match *self {
442
0
            BerObjectContent::Boolean(b) => Ok(b),
443
0
            _ => Err(BerError::BerTypeError),
444
        }
445
0
    }
446
447
45.3k
    pub fn as_oid(&self) -> Result<&Oid<'a>, BerError> {
448
45.3k
        match *self {
449
45.3k
            BerObjectContent::OID(ref o) => Ok(o),
450
0
            BerObjectContent::RelativeOID(ref o) => Ok(o),
451
0
            _ => Err(BerError::BerTypeError),
452
        }
453
45.3k
    }
454
455
32.1k
    pub fn as_oid_val(&self) -> Result<Oid<'a>, BerError> {
456
32.1k
        self.as_oid().map(|o| o.clone())
457
32.1k
    }
458
459
832
    pub fn as_context_specific(&self) -> Result<(BerTag, Option<Box<BerObject<'a>>>), BerError> {
460
832
        match *self {
461
832
            BerObjectContent::ContextSpecific(u, ref o) => Ok((u, o.clone())),
462
0
            _ => Err(BerError::BerTypeError),
463
        }
464
832
    }
465
466
0
    pub fn as_bitstring_ref(&self) -> Result<&BitStringObject, BerError> {
467
0
        match *self {
468
0
            BerObjectContent::BitString(_, ref b) => Ok(b),
469
0
            _ => Err(BerError::BerTypeError),
470
        }
471
0
    }
472
473
0
    pub fn as_bitstring(&'a self) -> Result<BitStringObject<'a>, BerError> {
474
0
        match *self {
475
0
            BerObjectContent::BitString(_, ref b) => Ok(b.to_owned()),
476
0
            _ => Err(BerError::BerTypeError),
477
        }
478
0
    }
479
480
0
    pub fn as_sequence(&self) -> Result<&Vec<BerObject<'a>>, BerError> {
481
0
        match *self {
482
0
            BerObjectContent::Sequence(ref s) => Ok(s),
483
0
            _ => Err(BerError::BerTypeError),
484
        }
485
0
    }
486
487
0
    pub fn as_set(&self) -> Result<&Vec<BerObject<'a>>, BerError> {
488
0
        match *self {
489
0
            BerObjectContent::Set(ref s) => Ok(s),
490
0
            _ => Err(BerError::BerTypeError),
491
        }
492
0
    }
493
494
    #[rustfmt::skip]
495
152k
    pub fn as_slice(&self) -> Result<&'a [u8],BerError> {
496
152k
        match *self {
497
696
            BerObjectContent::NumericString(s) |
498
4.78k
            BerObjectContent::PrintableString(s) |
499
2.03k
            BerObjectContent::UTF8String(s) |
500
8.70k
            BerObjectContent::IA5String(s) => Ok(s.as_ref()),
501
5.45k
            BerObjectContent::Integer(s) |
502
9.50k
            BerObjectContent::BitString(_,BitStringObject{data:s}) |
503
34.9k
            BerObjectContent::OctetString(s) |
504
1.99k
            BerObjectContent::T61String(s) |
505
2.13k
            BerObjectContent::BmpString(s) |
506
1.12k
            BerObjectContent::GeneralString(s) |
507
109k
            BerObjectContent::Unknown(_,s) => Ok(s),
508
34.8k
            _ => Err(BerError::BerTypeError),
509
        }
510
152k
    }
511
512
    #[rustfmt::skip]
513
0
    pub fn as_str(&self) -> Result<&'a str,BerError> {
514
0
        match *self {
515
0
            BerObjectContent::NumericString(s) |
516
0
            BerObjectContent::PrintableString(s) |
517
0
            BerObjectContent::UTF8String(s) |
518
0
            BerObjectContent::IA5String(s) => Ok(s),
519
0
            _ => Err(BerError::BerTypeError),
520
        }
521
0
    }
522
523
    #[rustfmt::skip]
524
5.45k
    pub fn tag(&self) -> BerTag {
525
5.45k
        match *self {
526
0
            BerObjectContent::EndOfContent         => BerTag::EndOfContent,
527
282
            BerObjectContent::Boolean(_)           => BerTag::Boolean,
528
1.50k
            BerObjectContent::Integer(_)           => BerTag::Integer,
529
0
            BerObjectContent::BitString(_,_)       => BerTag::BitString,
530
0
            BerObjectContent::OctetString(_)       => BerTag::OctetString,
531
0
            BerObjectContent::Null                 => BerTag::Null,
532
1.11k
            BerObjectContent::Enum(_)              => BerTag::Enumerated,
533
0
            BerObjectContent::OID(_)               => BerTag::Oid,
534
194
            BerObjectContent::NumericString(_)     => BerTag::NumericString,
535
204
            BerObjectContent::PrintableString(_)   => BerTag::PrintableString,
536
377
            BerObjectContent::IA5String(_)         => BerTag::Ia5String,
537
194
            BerObjectContent::UTF8String(_)        => BerTag::Utf8String,
538
514
            BerObjectContent::RelativeOID(_)       => BerTag::RelativeOid,
539
196
            BerObjectContent::T61String(_)         => BerTag::T61String,
540
195
            BerObjectContent::BmpString(_)         => BerTag::BmpString,
541
0
            BerObjectContent::Sequence(_)          => BerTag::Sequence,
542
0
            BerObjectContent::Set(_)               => BerTag::Set,
543
199
            BerObjectContent::UTCTime(_)           => BerTag::UtcTime,
544
204
            BerObjectContent::GeneralizedTime(_)   => BerTag::GeneralizedTime,
545
216
            BerObjectContent::GeneralString(_)     => BerTag::GeneralString,
546
55
            BerObjectContent::ContextSpecific(x,_) |
547
55
            BerObjectContent::Unknown(x,_)         => x,
548
        }
549
5.45k
    }
550
}
551
552
#[cfg(feature = "bigint")]
553
mod bigint {
554
    use super::{BerObject, BerObjectContent};
555
    use num_bigint::{BigInt, BigUint, Sign};
556
557
    impl<'a> BerObject<'a> {
558
        pub fn as_bigint(&self) -> Option<BigInt> {
559
            match self.content {
560
                BerObjectContent::Integer(s) => Some(BigInt::from_bytes_be(Sign::Plus, s)),
561
                _ => None,
562
            }
563
        }
564
565
        pub fn as_biguint(&self) -> Option<BigUint> {
566
            match self.content {
567
                BerObjectContent::Integer(s) => Some(BigUint::from_bytes_be(s)),
568
                _ => None,
569
            }
570
        }
571
    }
572
}
573
574
// This is a consuming iterator
575
impl<'a> IntoIterator for BerObject<'a> {
576
    type Item = BerObject<'a>;
577
    type IntoIter = BerObjectIntoIterator<'a>;
578
579
2.10k
    fn into_iter(self) -> Self::IntoIter {
580
2.10k
        // match self {
581
2.10k
        //     BerObjectContent::Sequence(ref v) => (),
582
2.10k
        //     _ => (),
583
2.10k
        // };
584
2.10k
        BerObjectIntoIterator { val: self, idx: 0 }
585
2.10k
    }
586
}
587
588
pub struct BerObjectIntoIterator<'a> {
589
    val: BerObject<'a>,
590
    idx: usize,
591
}
592
593
impl<'a> Iterator for BerObjectIntoIterator<'a> {
594
    type Item = BerObject<'a>;
595
8.91k
    fn next(&mut self) -> Option<BerObject<'a>> {
596
        // let result = if self.idx < self.vec.len() {
597
        //     Some(self.vec[self.idx].clone())
598
        // } else {
599
        //     None
600
        // };
601
8.91k
        let res = match self.val.content {
602
8.91k
            BerObjectContent::Sequence(ref v) if self.idx < v.len() => Some(v[self.idx].clone()),
603
0
            BerObjectContent::Set(ref v) if self.idx < v.len() => Some(v[self.idx].clone()),
604
            _ => {
605
2.10k
                if self.idx == 0 {
606
1
                    Some(self.val.clone())
607
                } else {
608
2.10k
                    None
609
                }
610
            }
611
        };
612
8.91k
        self.idx += 1;
613
8.91k
        res
614
8.91k
    }
615
}
616
617
// impl<'a> Iterator for BerObjectContent<'a> {
618
//     type Item = BerObjectContent<'a>;
619
//
620
//     fn next(&mut self) -> Option<BerObjectContent<'a>> {
621
//         None
622
//     }
623
// }
624
625
pub struct BerObjectRefIterator<'a> {
626
    obj: &'a BerObject<'a>,
627
    idx: usize,
628
}
629
630
impl<'a> Iterator for BerObjectRefIterator<'a> {
631
    type Item = &'a BerObject<'a>;
632
0
    fn next(&mut self) -> Option<&'a BerObject<'a>> {
633
0
        let res = match (*self.obj).content {
634
0
            BerObjectContent::Sequence(ref v) if self.idx < v.len() => Some(&v[self.idx]),
635
0
            BerObjectContent::Set(ref v) if self.idx < v.len() => Some(&v[self.idx]),
636
0
            _ => None,
637
        };
638
0
        self.idx += 1;
639
0
        res
640
0
    }
641
}
642
643
impl<'a> BerObject<'a> {
644
0
    pub fn ref_iter(&'a self) -> BerObjectRefIterator<'a> {
645
0
        BerObjectRefIterator { obj: self, idx: 0 }
646
0
    }
647
}
648
649
impl<'a> Index<usize> for BerObject<'a> {
650
    type Output = BerObject<'a>;
651
652
0
    fn index(&self, idx: usize) -> &BerObject<'a> {
653
0
        match (*self).content {
654
0
            BerObjectContent::Sequence(ref v) if idx < v.len() => &v[idx],
655
0
            BerObjectContent::Set(ref v) if idx < v.len() => &v[idx],
656
0
            _ => panic!("Try to index BerObjectContent which is not structured"),
657
        }
658
        // XXX the following
659
        // self.ref_iter().nth(idx).unwrap()
660
        // fails with:
661
        // error: cannot infer an appropriate lifetime for autoref due to conflicting requirements [E0495]
662
        // self.ref_iter().nth(idx).unwrap()
663
0
    }
664
}
665
666
/// BitString wrapper
667
0
#[derive(Clone, Debug, PartialEq)]
Unexecuted instantiation: <der_parser::ber::ber::BitStringObject as core::cmp::PartialEq>::ne
Unexecuted instantiation: <der_parser::ber::ber::BitStringObject as core::cmp::PartialEq>::eq
668
pub struct BitStringObject<'a> {
669
    pub data: &'a [u8],
670
}
671
672
impl<'a> BitStringObject<'a> {
673
    /// Test if bit `bitnum` is set
674
0
    pub fn is_set(&self, bitnum: usize) -> bool {
675
0
        let byte_pos = bitnum / 8;
676
0
        if byte_pos >= self.data.len() {
677
0
            return false;
678
0
        }
679
0
        let b = 7 - (bitnum % 8);
680
0
        (self.data[byte_pos] & (1 << b)) != 0
681
0
    }
682
}
683
684
impl<'a> AsRef<[u8]> for BitStringObject<'a> {
685
0
    fn as_ref(&self) -> &[u8] {
686
0
        self.data
687
0
    }
688
}
689
690
#[cfg(test)]
691
mod tests {
692
    use crate::ber::*;
693
    use crate::oid::*;
694
695
    #[test]
696
    fn test_der_as_u64() {
697
        let der_obj = BerObject::from_int_slice(b"\x01\x00\x02");
698
        assert_eq!(der_obj.as_u64(), Ok(0x10002));
699
    }
700
701
    #[test]
702
    fn test_der_seq_iter() {
703
        let der_obj = BerObject::from_obj(BerObjectContent::Sequence(vec![
704
            BerObject::from_int_slice(b"\x01\x00\x01"),
705
            BerObject::from_int_slice(b"\x01\x00\x00"),
706
        ]));
707
        let expected_values = vec![
708
            BerObject::from_int_slice(b"\x01\x00\x01"),
709
            BerObject::from_int_slice(b"\x01\x00\x00"),
710
        ];
711
712
        for (idx, v) in der_obj.ref_iter().enumerate() {
713
            // println!("v: {:?}", v);
714
            assert_eq!((*v), expected_values[idx]);
715
        }
716
    }
717
718
    #[test]
719
    fn test_der_from_oid() {
720
        let obj: BerObject = Oid::from(&[1, 2]).unwrap().into();
721
        let expected = BerObject::from_obj(BerObjectContent::OID(Oid::from(&[1, 2]).unwrap()));
722
723
        assert_eq!(obj, expected);
724
    }
725
726
    #[test]
727
    fn test_der_bistringobject() {
728
        let obj = BitStringObject {
729
            data: &[0x0f, 0x00, 0x40],
730
        };
731
        assert!(!obj.is_set(0));
732
        assert!(obj.is_set(7));
733
        assert!(!obj.is_set(9));
734
        assert!(obj.is_set(17));
735
    }
736
737
    #[test]
738
    fn test_der_bistringobject_asref() {
739
        fn assert_equal<T: AsRef<[u8]>>(s: T, b: &[u8]) {
740
            assert_eq!(s.as_ref(), b);
741
        }
742
        let b: &[u8] = &[0x0f, 0x00, 0x40];
743
        let obj = BitStringObject { data: b };
744
        assert_equal(obj, b);
745
    }
746
747
    #[cfg(feature = "bigint")]
748
    #[test]
749
    fn test_der_to_bigint() {
750
        let obj = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01"));
751
        let expected = ::num_bigint::BigInt::from(0x10001);
752
753
        assert_eq!(obj.as_bigint(), Some(expected));
754
    }
755
756
    #[cfg(feature = "bigint")]
757
    #[test]
758
    fn test_der_to_biguint() {
759
        let obj = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01"));
760
        let expected = ::num_bigint::BigUint::from(0x10001 as u32);
761
762
        assert_eq!(obj.as_biguint(), Some(expected));
763
    }
764
}