bcder/
tag.rs

1//! The identifier octets of a BER encoded value.
2//!
3//! This is a private module. Its public items are re-exported by the parent.
4
5use std::{fmt, io};
6use crate::decode::{DecodeError, Source};
7
8
9//------------ Tag -----------------------------------------------------------
10
11/// The tag of a BER encoded value.
12///
13/// Each BER encoded value starts with a sequence of one or more octets called
14/// the _identifier octets._ They encode both the tag of the value as well as
15/// whether the value uses primitive or constructed encoding. The `Tag` type
16/// represents the tag only. The distinction between primitive and constructed
17/// encoding is captured by the decoder types [`Primitive`] and
18/// [`Constructed`] instead.
19///
20/// The tag in turn consists of two parts: the class and the number – the
21/// `Tag` type includes both of them.
22///
23/// # Limitations
24///
25/// We can only decode up to four identifier octets. That is, we only support
26/// tag numbers between 0 and 1fffff.
27///
28/// [`Primitive`]: decode/struct.Primitive.html
29/// [`Constructed`]: decode/struct.Constructed.html
30//
31//  For the moment, the tag is stored with the constructed bit always cleared.
32#[derive(Clone, Copy, Eq, PartialEq)]
33pub struct Tag([u8; 4]);
34
35/// # Constants for Often Used Tag Values
36///
37impl Tag {
38    /// The mask for checking the class.
39    const CLASS_MASK: u8 = 0xc0;
40
41    /// The mask for checking whether the value is a primitive
42    ///
43    /// A value of 0 indicates primitive.
44    const CONSTRUCTED_MASK: u8 = 0x20;
45
46    /// The mask for the fourth octet data (bits 24-32).
47    ///
48    /// (5 bits – 0b0001_1111).
49    const SINGLEBYTE_DATA_MASK: u8 = 0x1f;
50
51    /// The mask for octet data.
52    ///
53    /// (7 bits – 0b0111_1111).
54    const MULTIBYTE_DATA_MASK: u8 = 0x7f;
55
56    /// The mask for the last octet with identifier data
57    ///
58    /// (1 bit – 0b1000_0000, it is cleared in the last octet).
59    const LAST_OCTET_MASK: u8 = 0x80;
60
61    /// The largest tag number possible with three octets.
62    const MAX_VAL_SPAN_3_OCTETS: u32 = 0x001f_ffff;
63
64    /// The largest tag number possible with two octets.
65    const MAX_VAL_SPAN_2_OCTETS: u32 = 0x3fff;
66
67    /// The largest tag number possible with one octet.
68    const MAX_VAL_SPAN_1_OCTET: u32 = 0x7f;
69
70    /// The largest tag number possible with the fourth octet.
71    const MAX_VAL_FOURTH_OCTET: u32 = 0x1e;
72
73    /// The tag value representing for the ‘universal’ class.
74    const UNIVERSAL: u8 = 0x00;
75
76    /// The tag value representing the ‘application’ class.
77    const APPLICATION: u8 = 0x40;
78
79    /// The tag value representing the ‘context-specific’ class.
80    const CONTEXT_SPECIFIC: u8 = 0x80;
81
82    /// The tag value representing the `private` class.
83    const PRIVATE: u8 = 0xc0;
84
85    /// The tag marking the end-of-value in an indefinite length value.
86    ///
87    /// This is UNIVERSAL 0.
88    pub const END_OF_VALUE: Self = Tag([0, 0, 0, 0]);
89
90    //--- Universal Tags
91    //
92    // See clause 8.4 of X.690.
93
94    /// The tag for the BOOLEAN type, UNIVERSAL 1.
95    pub const BOOLEAN: Self = Tag([1, 0, 0, 0]);
96
97    /// The tag for the INTEGER type, UNIVERSAL 2.
98    pub const INTEGER: Self = Tag([2, 0, 0, 0]);
99
100    /// The tag for the BIT STRING type, UNIVERSAL 3.
101    pub const BIT_STRING: Self = Tag([3, 0, 0, 0]);
102
103    /// The tag for the OCTET STRING type, UNIVERSAL 4.
104    pub const OCTET_STRING: Self = Tag([4, 0, 0, 0]);
105
106    /// The tag for the NULL type, UNIVERSAL 5.
107    pub const NULL: Self = Tag([5, 0, 0, 0]);
108
109    /// The tag for the OBJECT IDENTIFIER type, UNIVERSAL 6.
110    pub const OID: Self = Tag([6, 0, 0, 0]);
111
112    /// The tag for the ObjectDescriptor type, UNIVERSAL 7.
113    pub const OBJECT_DESCRIPTOR: Self = Tag([7, 0, 0, 0]);
114
115    /// The tag for the EXTERNAL and Instance-of types, UNIVERSAL 8.
116    pub const EXTERNAL: Self = Tag([8, 0, 0, 0]);
117
118    /// The tag for the REAL type, UNIVERSAL 9.
119    pub const REAL: Self = Tag([9, 0, 0, 0]);
120
121    /// The tag for the ENUMERATED type, UNIVERSAL 10.
122    pub const ENUMERATED: Self = Tag([10, 0, 0, 0]);
123
124    /// The tag for the EMBEDDED PDV type, UNIVERSAL 11.
125    pub const EMBEDDED_PDV: Self = Tag([11, 0, 0, 0]);
126
127    /// The tag for the UTF8String type, UNIVERSAL 12
128    pub const UTF8_STRING: Self = Tag([12, 0, 0, 0]);
129
130    /// The tag for the RELATIVE-OID type, UNIVERSAL 13.
131    pub const RELATIVE_OID: Self = Tag([13, 0, 0, 0]);
132
133    /// The tag for the TIME type, UNIVERSAL 14.
134    pub const TIME: Self = Tag([14, 0, 0, 0]);
135
136    /// The tag for the SEQUENCE and SEQUENCE OF types, UNIVERSAL 16.
137    pub const SEQUENCE: Self = Tag([16, 0, 0, 0]);
138
139    /// The tag for the SET and SET OF types, UNIVERSAL 17.
140    pub const SET: Self = Tag([17, 0, 0, 0]);
141
142    /// The tag for the NumericString type, UNIVERSAL 18.
143    pub const NUMERIC_STRING: Self = Tag([18, 0, 0, 0]);
144
145    /// The tag for the PrintableString type, UNIVERSAL 19.
146    pub const PRINTABLE_STRING: Self = Tag([19, 0, 0, 0]);
147
148    /// The tag for the TeletexString type, UNIVERSAL 20.
149    pub const TELETEX_STRING: Self = Tag([20, 0, 0, 0]);
150
151    /// The tag for the VideotexString type, UNIVERSAL 21.
152    pub const VIDEOTEX_STRING: Self = Tag([21, 0, 0, 0]);
153
154    /// The tag for the IA5String type, UNIVERSAL 22.
155    pub const IA5_STRING: Self = Tag([22, 0, 0, 0]);
156
157    /// The tag for the UTCTime type, UNIVERSAL 23.
158    pub const UTC_TIME: Self = Tag([23, 0, 0, 0]);
159
160    /// The tag for the GeneralizedType type, UNIVERSAL 24.
161    pub const GENERALIZED_TIME: Self = Tag([24, 0, 0, 0]);
162
163    /// The tag for the GraphicString type, UNIVERSAL 25.
164    pub const GRAPHIC_STRING: Self = Tag([25, 0, 0, 0]);
165
166    /// The tag for the VisibleString type, UNIVERSAL 26.
167    pub const VISIBLE_STRING: Self = Tag([26, 0, 0, 0]);
168
169    /// The tag for the GeneralString type, UNIVERSAL 27.
170    pub const GENERAL_STRING: Self = Tag([27, 0, 0, 0]);
171
172    /// The tag for the UniversalString type, UNIVERSAL 28.
173    pub const UNIVERSAL_STRING: Self = Tag([28, 0, 0, 0]);
174
175    /// The tag for the CHARACTER STRING type, UNIVERSAL 29.
176    pub const CHARACTER_STRING: Self = Tag([29, 0, 0, 0]);
177
178    /// The tag for the BMPString type, UNIVERSAL 30.
179    pub const BMP_STRING: Self = Tag([30, 0, 0, 0]);
180
181    /// The tag for the DATE type, UNIVERSAL 31.
182    pub const DATE: Self = Tag([31, 0, 0, 0]);
183
184    /// The tag for the TIME-OF-DAY type, UNIVERSAL 32.
185    pub const TIME_OF_DAY: Self = Tag([32, 0, 0, 0]);
186
187    /// The tag for the DATE-TIME type, UNIVERSAL 33.
188    pub const DATE_TIME: Self = Tag([33, 0, 0, 0]);
189
190    /// The tag for the DURATION type, UNIVERSAL 34.
191    pub const DURATION: Self = Tag([34, 0, 0, 0]);
192
193    /// The tag for the OID-IRI type, UNIVERSAL 35.
194    pub const OID_IRI: Self = Tag([35, 0, 0, 0]);
195
196    /// The tag for the RELATIVE-OID-IRI type, UNIVERSAL 36.
197    pub const RELATIVE_OID_IRI: Self = Tag([36, 0, 0, 0]);
198
199    //--- The first few context-specific tags.
200    //
201    //    These will be removed once we can have `ctx` be a const fn.
202
203    /// The tag context specific tag `[0]`.
204    pub const CTX_0: Self = Tag([Tag::CONTEXT_SPECIFIC, 0, 0, 0]);
205
206    /// The tag context specific tag `[1]`.
207    pub const CTX_1: Self = Tag([Tag::CONTEXT_SPECIFIC | 1, 0, 0, 0]);
208
209    /// The tag context specific tag `[2]`.
210    pub const CTX_2: Self = Tag([Tag::CONTEXT_SPECIFIC | 2, 0, 0, 0]);
211
212    /// The tag context specific tag `[3]`.
213    pub const CTX_3: Self = Tag([Tag::CONTEXT_SPECIFIC | 3, 0, 0, 0]);
214
215    /// The tag context specific tag `[4]`.
216    pub const CTX_4: Self = Tag([Tag::CONTEXT_SPECIFIC | 4, 0, 0, 0]);
217
218    /// The tag context specific tag `[5]`.
219    pub const CTX_5: Self = Tag([Tag::CONTEXT_SPECIFIC | 5, 0, 0, 0]);
220
221    /// The tag context specific tag `[6]`.
222    pub const CTX_6: Self = Tag([Tag::CONTEXT_SPECIFIC | 6, 0, 0, 0]);
223}
224
225impl Tag {
226    /// Encodes a number into the identifier representation.
227    ///
228    /// There are two forms:
229    /// * low tag number (for tag numbers between 0 and 30):
230    ///   One octet. Bits 8 and 7 specify the class, bit 6 indicates whether
231    ///   the encoding is primitive (0), and bits 5-1 give the tag number.
232    /// * high tag number (for tag numbers 31 and greater):
233    ///   Two or more octets. First octet is as in low-tag-number form,
234    ///   except that bits 5-1 all have value 1. Second and following octets
235    ///   give the tag number, base 128, most significant digit first, with
236    ///   as few digits as possible, and with the bit 8 of each octet except
237    ///   the last set to 1.
238    //
239    /// # Panics
240    ///
241    /// This function panics if the tag number is greater than
242    /// `Self::MAX_VAL_SPAN_3_OCTETS`.
243    #[inline]
244    fn new(class_mask: u8, number: u32) -> Self {
245        assert!(number <= Tag::MAX_VAL_SPAN_3_OCTETS);
246        if number <= Tag::MAX_VAL_FOURTH_OCTET {
247            Tag([class_mask | number as u8, 0, 0, 0])
248        } else if number <= Tag::MAX_VAL_SPAN_1_OCTET {
249            // Fit the number in the third octets
250            let number = number as u8;
251            Tag([class_mask | Tag::SINGLEBYTE_DATA_MASK, number, 0, 0])
252        } else if number <= Tag::MAX_VAL_SPAN_2_OCTETS {
253            // Fit the number in the second and the third octets
254            let first_part = {
255                Tag::MULTIBYTE_DATA_MASK & ((number >> 7) as u8)
256                | Tag::LAST_OCTET_MASK
257            };
258            let second_part = Tag::MULTIBYTE_DATA_MASK & (number as u8);
259            Tag([
260                class_mask | Tag::SINGLEBYTE_DATA_MASK, first_part,
261                second_part, 0
262            ])
263        } else {
264            // Fit the number in the first, second and the third octets
265            let first_part = {
266                Tag::MULTIBYTE_DATA_MASK & ((number >> 14) as u8)
267                | Tag::LAST_OCTET_MASK
268            };
269            let second_part = {
270                Tag::MULTIBYTE_DATA_MASK & ((number >> 7) as u8)
271                | Tag::LAST_OCTET_MASK
272            };
273            let third_part = Tag::MULTIBYTE_DATA_MASK & (number as u8);
274            Tag([
275                class_mask | Tag::SINGLEBYTE_DATA_MASK, first_part,
276                second_part, third_part
277            ])
278        }
279    }
280
281    /// Creates a new tag in the universal class with the given tag number.
282    ///
283    /// # Panics
284    ///
285    /// Currently, this function panics if the tag number is greater than
286    /// `MAX_VAL_SPAN_3_OCTETS`.
287    pub fn universal(number: u32) -> Self {
288        Tag::new(Tag::UNIVERSAL, number)
289    }
290
291    /// Creates a new tag in the application class with the given tag number.
292    ///
293    /// # Panics
294    ///
295    /// Currently, this function panics if the tag number is greater than
296    /// `MAX_VAL_SPAN_3_OCTETS`.
297    pub fn application(number: u32) -> Self {
298        Tag::new(Tag::APPLICATION, number)
299    }
300
301    /// Creates a new tag in the context specific class.
302    ///
303    /// # Panics
304    ///
305    /// Currently, this function panics if the provided tag number is greater
306    /// than `MAX_VAL_SPAN_3_OCTETS`.
307    pub fn ctx(number: u32) -> Self {
308        Tag::new(Tag::CONTEXT_SPECIFIC, number)
309    }
310
311    /// Creates a new tag in the private class with the given tag number.
312    ///
313    /// # Panics
314    ///
315    /// Currently, this function panics if the provided tag number is greater
316    /// than `MAX_VAL_SPAN_3_OCTETS`.
317    pub fn private(number: u32) -> Self {
318        Tag::new(Tag::PRIVATE, number)
319    }
320
321    /// Returns whether the tag is of the universal class.
322    pub fn is_universal(self) -> bool {
323        self.0[0] & Self::CLASS_MASK == Self::UNIVERSAL
324    }
325
326    /// Returns whether the tag is of the application class.
327    pub fn is_application(self) -> bool {
328        self.0[0] & Self::CLASS_MASK == Self::APPLICATION
329    }
330
331    /// Returns whether the tag is of the context specific class.
332    pub fn is_context_specific(self) -> bool {
333        self.0[0] & Self::CLASS_MASK == Self::CONTEXT_SPECIFIC
334    }
335
336    /// Returns whether the tag is of the private class.
337    pub fn is_private(self) -> bool {
338        self.0[0] & Self::CLASS_MASK == Self::PRIVATE
339    }
340
341    /// Returns the number of the tag.
342    pub fn number(self) -> u32 {
343        if (Tag::SINGLEBYTE_DATA_MASK & self.0[0])
344            != Tag::SINGLEBYTE_DATA_MASK
345        {
346            // It's a single byte identifier
347            u32::from(Tag::SINGLEBYTE_DATA_MASK & self.0[0])
348        } else if Tag::LAST_OCTET_MASK & self.0[1] == 0 {
349            // It's a multibyte that starts and ends in the third octet
350            u32::from(Tag::MULTIBYTE_DATA_MASK & self.0[1])
351        } else if Tag::LAST_OCTET_MASK & self.0[2] == 0 {
352            // It's a multibyte that starts in the second octet and ends in
353            // the third octet
354            (u32::from(Tag::MULTIBYTE_DATA_MASK & self.0[1]) << 7)
355            | u32::from(Tag::MULTIBYTE_DATA_MASK & self.0[2])
356        } else {
357            // It's a multibyte that spans the first three octets
358            (u32::from(Tag::MULTIBYTE_DATA_MASK & self.0[1]) << 14)
359            | (u32::from(Tag::MULTIBYTE_DATA_MASK & self.0[2]) << 7)
360            | u32::from(Tag::MULTIBYTE_DATA_MASK & self.0[3])
361        }
362    }
363
364    /// Takes an optional tag from the beginning of a source.
365    ///
366    /// Upon success, returns both the tag and whether the value is
367    /// constructed.
368    pub fn take_opt_from<S: Source>(
369        source: &mut S,
370    ) -> Result<Option<(Self, bool)>, DecodeError<S::Error>> {
371        let byte = match source.take_opt_u8()? {
372            Some(byte) => byte,
373            None => return Ok(None)
374        };
375        // clear constructed bit
376        let mut data = [byte & !Tag::CONSTRUCTED_MASK, 0, 0, 0];
377        let constructed = byte & Tag::CONSTRUCTED_MASK != 0;
378        if (data[0] & Tag::SINGLEBYTE_DATA_MASK) == Tag::SINGLEBYTE_DATA_MASK {
379            for i in 1..=3 {
380                data[i] = source.take_u8()?;
381                if data[i] & Tag::LAST_OCTET_MASK == 0 {
382                    return Ok(Some((Tag(data), constructed)));
383                }
384            }
385        } else {
386            return Ok(Some((Tag(data), constructed)));
387        }
388        Err(source.content_err(
389            "tag values longer than 4 bytes not implemented"
390        ))
391    }
392
393    /// Takes a tag from the beginning of a source.
394    ///
395    /// Upon success, returns both the tag and whether the value is
396    /// constructed. If there are no more octets available in the source,
397    /// an error is returned.
398    pub fn take_from<S: Source>(
399        source: &mut S,
400    ) -> Result<(Self, bool), DecodeError<S::Error>> {
401        match Self::take_opt_from(source)? {
402            Some(res) => Ok(res),
403            None => Err(source.content_err("additional values expected"))
404        }
405    }
406
407    /// Takes a tag from the beginning of a resource if it matches this tag.
408    ///
409    /// If there is no more data available in the source or if the tag is
410    /// something else, returns `Ok(None)`. If the tag matches `self`, returns
411    /// whether the value is constructed.
412    pub fn take_from_if<S: Source>(
413        self,
414        source: &mut S,
415    ) -> Result<Option<bool>, DecodeError<S::Error>> {
416        if source.request(1)? == 0 {
417            return Ok(None)
418        }
419        let byte = source.slice()[0];
420        // clear constructed bit
421        let mut data = [byte & !Tag::CONSTRUCTED_MASK, 0, 0, 0];
422        if (data[0] & Tag::SINGLEBYTE_DATA_MASK) == Tag::SINGLEBYTE_DATA_MASK {
423            let mut i = 1;
424            loop {
425                if source.request(i + 1)? <= i {
426                    // Not enough data for a complete tag.
427                    return Err(source.content_err("short tag value"))
428                }
429                data[i] = source.slice()[i];
430                if data[i] & Tag::LAST_OCTET_MASK == 0 {
431                    break
432                }
433                // We don’t support tags larger than 4 bytes.
434                if i == 3 {
435                    return Err(source.content_err(
436                        "tag values longer than 4 bytes not implemented"
437                    ))
438                }
439                i += 1;
440            }
441        }
442        let (tag, constructed) = (
443            Tag(data),
444            byte & Tag::CONSTRUCTED_MASK != 0
445        );
446        if tag == self {
447            source.advance(tag.encoded_len());
448            Ok(Some(constructed))
449        }
450        else {
451            Ok(None)
452        }
453    }
454
455    /// Returns the number of octets of the encoded form of the tag.
456    #[allow(clippy::trivially_copy_pass_by_ref)] // for possible multi-byte tags
457    pub fn encoded_len(&self) -> usize {
458        if (Tag::SINGLEBYTE_DATA_MASK & self.0[0]) != Tag::SINGLEBYTE_DATA_MASK {
459            1
460        } else if Tag::LAST_OCTET_MASK & self.0[1] == 0 {
461            2
462        } else if Tag::LAST_OCTET_MASK & self.0[2] == 0 {
463            3
464        } else {
465            4
466        }
467    }
468
469    /// Encodes the tag into a target.
470    ///
471    /// If `constructed` is `true`, the encoded tag will signal a value in
472    /// constructed encoding and primitive encoding otherwise.
473    #[allow(clippy::trivially_copy_pass_by_ref)] // for possible multi-byte tags
474    pub fn write_encoded<W: io::Write>(
475        &self,
476        constructed: bool,
477        target: &mut W
478    ) -> Result<(), io::Error> {
479        let mut buf = self.0;
480        if constructed {
481            buf[0] |= Tag::CONSTRUCTED_MASK
482        }
483        target.write_all(&buf[..self.encoded_len()])
484    }
485}
486
487impl fmt::Display for Tag {
488    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
489        match *self {
490            Tag::BOOLEAN => write!(f, "BOOLEAN"),
491            Tag::INTEGER => write!(f, "INTEGER"),
492            Tag::BIT_STRING => write!(f, "BIT STRING"),
493            Tag::OCTET_STRING => write!(f, "OCTET STRING"),
494            Tag::NULL => write!(f, "NULL"),
495            Tag::OID => write!(f, "OBJECT IDENTIFIER"),
496            Tag::OBJECT_DESCRIPTOR => write!(f, "ObjectDescriptor"),
497            Tag::EXTERNAL => write!(f, "EXTERNAL"),
498            Tag::REAL => write!(f, "REAL"),
499            Tag::ENUMERATED => write!(f, "ENUMERATED"),
500            Tag::EMBEDDED_PDV => write!(f, "EMBEDDED PDV"),
501            Tag::UTF8_STRING => write!(f, "UTF8String"),
502            Tag::RELATIVE_OID => write!(f, "RELATIVE-OID"),
503            Tag::TIME => write!(f, "TIME"),
504            Tag::SEQUENCE => write!(f, "SEQUENCE"),
505            Tag::SET => write!(f, "SET"),
506            Tag::NUMERIC_STRING => write!(f, "NumericString"),
507            Tag::PRINTABLE_STRING => write!(f, "PrintableString"),
508            Tag::TELETEX_STRING => write!(f, "TeletexString"),
509            Tag::VIDEOTEX_STRING => write!(f, "VideotexString"),
510            Tag::IA5_STRING => write!(f, "IA5String"),
511            Tag::UTC_TIME => write!(f, "UTCTime"),
512            Tag::GENERALIZED_TIME => write!(f, "GeneralizedTime"),
513            Tag::GRAPHIC_STRING => write!(f, "GraphicString"),
514            Tag::VISIBLE_STRING => write!(f, "VisibleString"),
515            Tag::GENERAL_STRING => write!(f, "GeneralString"),
516            Tag::UNIVERSAL_STRING => write!(f, "UniversalString"),
517            Tag::CHARACTER_STRING => write!(f, "CHARACTER STRING"),
518            Tag::BMP_STRING => write!(f, "BMPString"),
519            Tag::DATE => write!(f, "DATE"),
520            Tag::TIME_OF_DAY => write!(f, "TIME-OF-DAY"),
521            Tag::DATE_TIME => write!(f, "DATE-TIME"),
522            Tag::DURATION => write!(f, "DURATION"),
523            Tag::OID_IRI => write!(f, "OID-IRI"),
524            Tag::RELATIVE_OID_IRI => write!(f, "RELATIVE-OID-IRI"),
525            tag => {
526                match tag.0[0] & Tag::CLASS_MASK {
527                    Tag::UNIVERSAL => write!(f, "[UNIVERSAL ")?,
528                    Tag::APPLICATION => write!(f, "[APPLICATION ")?,
529                    Tag::CONTEXT_SPECIFIC => write!(f, "[")?,
530                    Tag::PRIVATE => write!(f, "[PRIVATE ")?,
531                    _ => unreachable!()
532                }
533                write!(f, "{}]", tag.number())
534            }
535        }
536    }
537}
538
539impl fmt::Debug for Tag {
540    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
541        write!(f, "Tag({})", self)
542    }
543}
544
545//============ Tests =========================================================
546
547#[cfg(test)]
548mod test {
549    use super::*;
550    use crate::decode::IntoSource;
551
552    const TYPES: &[u8] = &[Tag::UNIVERSAL, Tag::APPLICATION, Tag::CONTEXT_SPECIFIC, Tag::PRIVATE];
553
554    #[test]
555    fn test_single_octet_tags() {
556        // Test edge cases.
557        let range: Vec<u32> = (0..5).chain(
558            Tag::MAX_VAL_FOURTH_OCTET-5..Tag::MAX_VAL_FOURTH_OCTET
559        ).collect();
560        for &typ in TYPES {
561            for i in range.clone() {
562                let tag = Tag::new(typ, i);
563                let expected = Tag([typ | i as u8, 0, 0, 0]);
564                let decoded = Tag::take_from(
565                    &mut tag.0.into_source()
566                ).unwrap();
567                assert_eq!(
568                    tag.take_from_if(&mut tag.0.into_source()).unwrap(),
569                    Some(false)
570                );
571                // The value is not constructed.
572                assert!(!decoded.1);
573                // The tag is the same
574                assert_eq!(decoded.0, expected);
575                // We get the same number back.
576                assert_eq!(tag.number(), i);
577                // The representation is correct.
578                assert_eq!(tag, expected);
579
580            }
581        }
582    }
583
584    #[test]
585    fn test_double_octets_tags() {
586        // Test edge cases.
587        let range: Vec<u32> = (
588            Tag::MAX_VAL_FOURTH_OCTET+1..Tag::MAX_VAL_FOURTH_OCTET+5
589        ).chain(
590            Tag::MAX_VAL_SPAN_1_OCTET-5..Tag::MAX_VAL_SPAN_1_OCTET
591        ).collect();
592        for &typ in TYPES {
593            for i in range.clone() {
594                let tag = Tag::new(typ, i);
595                let expected = Tag([
596                        Tag::SINGLEBYTE_DATA_MASK | typ, i as u8, 0, 0
597                ]);
598                let decoded = Tag::take_from(
599                    &mut tag.0.into_source()
600                ).unwrap();
601                assert_eq!(
602                    tag.take_from_if(&mut tag.0.into_source()).unwrap(),
603                    Some(false)
604                );
605                assert!(
606                    tag.take_from_if(
607                        &mut tag.0[0..1].into_source()
608                    ).is_err(),
609                );
610                // The value is not constructed.
611                assert!(!decoded.1);
612                // The tag is the same
613                assert_eq!(decoded.0, expected);
614                assert_eq!(tag.number(), i);
615                assert_eq!(tag, expected);
616            }
617        }
618    }
619
620    #[test]
621    fn test_three_octets_tags() {
622        // Test edge cases.
623        let range: Vec<u32> = (
624            Tag::MAX_VAL_SPAN_1_OCTET+1..Tag::MAX_VAL_SPAN_1_OCTET + 5
625        ).chain(
626            Tag::MAX_VAL_SPAN_2_OCTETS-5..Tag::MAX_VAL_SPAN_2_OCTETS
627        ).collect();
628        for &typ in TYPES {
629            for i in range.clone() {
630                let tag = Tag::new(typ, i);
631                let expected = Tag([
632                    Tag::SINGLEBYTE_DATA_MASK | typ,
633                    (i >> 7) as u8 | Tag::LAST_OCTET_MASK,
634                    i as u8 & !Tag::LAST_OCTET_MASK,
635                    0
636                ]);
637                let decoded = Tag::take_from(
638                    &mut tag.0.into_source()
639                ).unwrap();
640                assert_eq!(
641                    tag.take_from_if(&mut tag.0.into_source()).unwrap(),
642                    Some(false)
643                );
644                assert!(
645                    tag.take_from_if(
646                        &mut tag.0[0..2].into_source()
647                    ).is_err(),
648                );
649                // The value is not constructed.
650                assert!(!decoded.1);
651                // The tag is the same
652                assert_eq!(decoded.0, expected);
653                assert_eq!(tag.number(), i);
654                assert_eq!(tag, expected);
655            }
656        }
657    }
658
659    #[test]
660    fn test_four_octets_tags() {
661        // Test edge cases.
662        let range: Vec<u32> = (
663            Tag::MAX_VAL_SPAN_2_OCTETS+1..Tag::MAX_VAL_SPAN_2_OCTETS + 5
664        ).chain(
665            Tag::MAX_VAL_SPAN_3_OCTETS-5..Tag::MAX_VAL_SPAN_3_OCTETS
666        ).collect();
667        for &typ in TYPES {
668            for i in range.clone() {
669                let tag = Tag::new(typ, i);
670                let expected = Tag([
671                    Tag::SINGLEBYTE_DATA_MASK | typ,
672                    (i >> 14) as u8 | Tag::LAST_OCTET_MASK,
673                    (i >> 7) as u8 | Tag::LAST_OCTET_MASK,
674                    i as u8 & !Tag::LAST_OCTET_MASK
675                ]);
676                let decoded = Tag::take_from(
677                    &mut tag.0.into_source()
678                ).unwrap();
679                assert_eq!(
680                    tag.take_from_if(&mut tag.0.into_source()).unwrap(),
681                    Some(false)
682                );
683                assert!(
684                    tag.take_from_if(
685                        &mut tag.0[0..3].into_source()
686                    ).is_err(),
687                );
688                // The value is not constructed.
689                assert!(!decoded.1);
690                // The tag is the same
691                assert_eq!(decoded.0, expected);
692                assert_eq!(tag.number(), i);
693                assert_eq!(tag, expected);
694            }
695        }
696    }
697
698    #[test]
699    fn test_tags_failures() {
700        let large_tag = [
701            0b1111_1111, 0b1000_0000, 0b1000_0000, 0b1000_0000, 0b1000_0000
702        ];
703        assert!(
704            Tag::take_from(&mut large_tag.into_source()).is_err()
705        );
706        let short_tag = [0b1111_1111, 0b1000_0000];
707        assert!(
708            Tag::take_from(&mut short_tag.into_source()).is_err()
709        );
710    }
711}