Skip to main content

der/tag/
class.rs

1//! Class of an ASN.1 tag.
2
3use core::fmt;
4
5/// `UNIVERSAL`: built-in types whose meaning is the same in all
6/// applications.
7pub const CLASS_UNIVERSAL: u8 = 0b00000000;
8/// `APPLICATION`: types whose meaning is specific to an application.
9pub const CLASS_APPLICATION: u8 = 0b01000000;
10/// `CONTEXT-SPECIFIC`: types whose meaning is specific to a given
11/// structured type.
12pub const CLASS_CONTEXT_SPECIFIC: u8 = 0b10000000;
13/// `PRIVATE`: types whose meaning is specific to a given enterprise.
14pub const CLASS_PRIVATE: u8 = 0b11000000;
15
16/// Class of an ASN.1 tag.
17#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
18#[repr(u8)]
19pub enum Class {
20    /// `UNIVERSAL`: built-in types whose meaning is the same in all
21    /// applications.
22    Universal = CLASS_UNIVERSAL,
23
24    /// `APPLICATION`: types whose meaning is specific to an application,
25    ///
26    /// Types in two different applications may have the same
27    /// application-specific tag and different meanings.
28    Application = CLASS_APPLICATION,
29
30    /// `CONTEXT-SPECIFIC`: types whose meaning is specific to a given
31    /// structured type.
32    ///
33    /// Context-specific tags are used to distinguish between component types
34    /// with the same underlying tag within the context of a given structured
35    /// type, and component types in two different structured types may have
36    /// the same tag and different meanings.
37    ContextSpecific = CLASS_CONTEXT_SPECIFIC,
38
39    /// `PRIVATE`: types whose meaning is specific to a given enterprise.
40    Private = CLASS_PRIVATE,
41}
42
43impl fmt::Display for Class {
44    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45        f.write_str(match self {
46            Class::Universal => "UNIVERSAL",
47            Class::Application => "APPLICATION",
48            Class::ContextSpecific => "CONTEXT-SPECIFIC",
49            Class::Private => "PRIVATE",
50        })
51    }
52}
53
54impl Class {
55    /// Returns class as 2 most-significant bits (mask 0b11000000)
56    #[must_use]
57    pub const fn bits(&self) -> u8 {
58        *self as u8
59    }
60
61    /// Returns class extracted from 2 most-significant bits (mask 0b11000000)
62    #[must_use]
63    pub const fn from_bits(bits: u8) -> Self {
64        match (bits >> 6) & 0b11 {
65            0b00 => Class::Universal,
66            0b01 => Class::Application,
67            0b10 => Class::ContextSpecific,
68            0b11 => Class::Private,
69            _ => unreachable!(),
70        }
71    }
72}
73impl From<u8> for Class {
74    fn from(value: u8) -> Self {
75        Class::from_bits(value)
76    }
77}