Skip to main content

der/tag/
number.rs

1//! ASN.1 tag numbers
2
3use super::Tag;
4use core::fmt;
5
6/// ASN.1 tag numbers (i.e. lower 5 bits of a [`Tag`]).
7///
8/// From X.690 Section 8.1.2.2:
9///
10/// > bits 5 to 1 shall encode the number of the tag as a binary integer with
11/// > bit 5 as the most significant bit.
12///
13/// This library supports tag numbers ranging from zero to 30 (inclusive) for
14/// universal tags and arbitrary 32-bit tag numbers for application, private
15/// and context-specific tags.
16///
17/// Section 8.1.2.4 describes how to support multi-byte tag numbers, which are
18/// encoded by using a leading tag number of 31 (`0b11111`).
19#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
20pub struct TagNumber(pub u32);
21
22impl TagNumber {
23    /// Mask value used to obtain the tag number from a tag octet.
24    pub(super) const MASK: u8 = 0b11111;
25
26    /// Create a new tag number.
27    #[deprecated(
28        since = "0.8.0",
29        note = "use TagNumber(value) directly as inner field is now pub"
30    )]
31    #[must_use]
32    pub const fn new(value: u32) -> Self {
33        Self(value)
34    }
35
36    /// Create an `APPLICATION` tag with this tag number.
37    #[must_use]
38    pub fn application(self, constructed: bool) -> Tag {
39        Tag::Application {
40            constructed,
41            number: self,
42        }
43    }
44
45    /// Create a `CONTEXT-SPECIFIC` tag with this tag number.
46    #[must_use]
47    pub fn context_specific(self, constructed: bool) -> Tag {
48        Tag::ContextSpecific {
49            constructed,
50            number: self,
51        }
52    }
53
54    /// Create a `PRIVATE` tag with this tag number.
55    #[must_use]
56    pub fn private(self, constructed: bool) -> Tag {
57        Tag::Private {
58            constructed,
59            number: self,
60        }
61    }
62
63    /// Get the inner value.
64    #[must_use]
65    pub fn value(self) -> u32 {
66        self.0
67    }
68}
69
70impl From<u32> for TagNumber {
71    fn from(value: u32) -> TagNumber {
72        TagNumber(value)
73    }
74}
75
76impl From<TagNumber> for u32 {
77    fn from(number: TagNumber) -> u32 {
78        number.0
79    }
80}
81
82impl fmt::Display for TagNumber {
83    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84        write!(f, "{}", self.0)
85    }
86}
87
88// Implement by hand because the derive would create invalid values.
89// Use the constructor to create a valid value.
90#[cfg(feature = "arbitrary")]
91impl<'a> arbitrary::Arbitrary<'a> for TagNumber {
92    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
93        Ok(Self(u.int_in_range(0..=30)?))
94    }
95
96    fn size_hint(depth: usize) -> (usize, Option<usize>) {
97        u8::size_hint(depth)
98    }
99}