1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5#[repr(u8)]
6pub enum Class {
7 Universal = 0,
8 Application = 1,
9 Context = 2,
10 Private = 3,
11}
12
13impl Class {
14 pub fn from_byte(b: u8) -> Self {
15 match b >> 6 {
16 0 => Self::Universal,
17 1 => Self::Application,
18 2 => Self::Context,
19 3 => Self::Private,
20 _ => unreachable!(),
21 }
22 }
23}
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
27pub struct Tag {
28 pub class: Class,
29 pub constructed: bool,
30 pub number: u32,
31}
32
33impl Tag {
34 pub const fn universal(number: u32) -> Self {
35 Self {
36 class: Class::Universal,
37 constructed: false,
38 number,
39 }
40 }
41
42 pub const fn sequence() -> Self {
43 Self {
44 class: Class::Universal,
45 constructed: true,
46 number: SEQUENCE,
47 }
48 }
49
50 pub const fn set() -> Self {
51 Self {
52 class: Class::Universal,
53 constructed: true,
54 number: SET,
55 }
56 }
57
58 pub const fn context(number: u32) -> Self {
59 Self {
60 class: Class::Context,
61 constructed: false,
62 number,
63 }
64 }
65
66 pub const fn context_constructed(number: u32) -> Self {
67 Self {
68 class: Class::Context,
69 constructed: true,
70 number,
71 }
72 }
73
74 pub const fn application(number: u32) -> Self {
75 Self {
76 class: Class::Application,
77 constructed: true,
78 number,
79 }
80 }
81
82 pub const fn application_primitive(number: u32) -> Self {
83 Self {
84 class: Class::Application,
85 constructed: false,
86 number,
87 }
88 }
89
90 pub fn with_constructed(self, constructed: bool) -> Self {
91 Self {
92 constructed,
93 ..self
94 }
95 }
96
97 pub fn encode(&self) -> Vec<u8> {
99 let mut first = (self.class as u8) << 6;
100 if self.constructed {
101 first |= 0x20;
102 }
103
104 if self.number < 31 {
105 first |= self.number as u8;
106 vec![first]
107 } else {
108 first |= 0x1F;
109 let mut buf = [0u8; 5];
111 let mut pos = buf.len();
112 let mut n = self.number;
113 loop {
114 pos -= 1;
115 buf[pos] = (n & 0x7F) as u8;
116 n >>= 7;
117 if n == 0 {
118 break;
119 }
120 }
121 let end = buf.len() - 1;
123 for b in &mut buf[pos..end] {
124 *b |= 0x80;
125 }
126 let mut result = Vec::with_capacity(1 + buf.len() - pos);
127 result.push(first);
128 result.extend_from_slice(&buf[pos..]);
129 result
130 }
131 }
132}
133
134pub const BOOLEAN: u32 = 0x01;
136pub const INTEGER: u32 = 0x02;
137pub const OCTET_STRING: u32 = 0x04;
138pub const NULL: u32 = 0x05;
139pub const ENUMERATED: u32 = 0x0A;
140pub const SEQUENCE: u32 = 0x10;
141pub const SET: u32 = 0x11;