1use super::{
2 error::{Error, ExpectedTag},
3 io::{Reader, Writer},
4};
5
6#[derive(Debug, Clone, PartialEq, Eq)]
14#[cfg_attr(feature = "defmt", derive(defmt::Format))]
15#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
16#[repr(u8)]
17pub enum ApplicationTagNumber {
18 Null = 0,
19 Boolean = 1,
20 UnsignedInt = 2,
21 SignedInt = 3,
22 Real = 4,
23 Double = 5,
24 OctetString = 6,
25 CharacterString = 7,
26 BitString = 8,
27 Enumerated = 9,
28 Date = 10,
29 Time = 11,
30 ObjectId = 12,
31 Reserve1 = 13,
32 Reserve2 = 14,
33 Reserve3 = 15,
34}
35
36impl From<u8> for ApplicationTagNumber {
37 fn from(tag_number: u8) -> Self {
38 match tag_number {
39 0 => Self::Null,
40 1 => Self::Boolean,
41 2 => Self::UnsignedInt,
42 3 => Self::SignedInt,
43 4 => Self::Real,
44 5 => Self::Double,
45 6 => Self::OctetString,
46 7 => Self::CharacterString,
47 8 => Self::BitString,
48 9 => Self::Enumerated,
49 10 => Self::Date,
50 11 => Self::Time,
51 12 => Self::ObjectId,
52 13 => Self::Reserve1,
53 14 => Self::Reserve2,
54 15 => Self::Reserve3,
55 _ => unreachable!(), }
57 }
58}
59
60#[derive(Debug, Clone, PartialEq, Eq)]
61#[cfg_attr(feature = "defmt", derive(defmt::Format))]
62#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
63pub enum TagNumber {
64 Application(ApplicationTagNumber),
65 ContextSpecific(u8),
66 ContextSpecificOpening(u8),
67 ContextSpecificClosing(u8),
68}
69
70#[derive(Debug, Clone)]
71#[cfg_attr(feature = "defmt", derive(defmt::Format))]
72#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
73pub struct Tag {
74 pub number: TagNumber,
75 pub value: u32,
76}
77
78impl Tag {
79 pub fn new(number: TagNumber, value: u32) -> Self {
80 Self { number, value }
81 }
82
83 pub fn encode(&self, writer: &mut Writer) {
84 let mut buf: [u8; 10] = [0; 10];
85 let mut len = 1;
86
87 match &self.number {
88 TagNumber::Application(num) => {
89 buf[0] |= (num.clone() as u8) << 4;
90 }
91 TagNumber::ContextSpecificOpening(num) => {
92 let num = *num;
93 buf[0] |= 0b1000; if num <= 14 {
96 buf[0] |= num << 4;
97 } else {
98 buf[0] |= 0xF0;
99 buf[1] = num;
100 len += 1;
101 }
102
103 buf[0] |= 6;
105 }
106 TagNumber::ContextSpecificClosing(num) => {
107 let num = *num;
108 buf[0] |= 0b1000; if num <= 14 {
111 buf[0] |= num << 4;
112 } else {
113 buf[0] |= 0xF0;
114 buf[1] = num;
115 len += 1;
116 }
117
118 buf[0] |= 7;
120 }
121 TagNumber::ContextSpecific(num) => {
122 let num = *num;
123 buf[0] |= 0b1000; if num <= 14 {
126 buf[0] |= num << 4;
127 } else {
128 buf[0] |= 0xF0;
129 buf[1] = num;
130 len += 1;
131 }
132 }
133 }
134
135 if self.value <= 4 {
136 buf[0] |= self.value as u8;
137 } else {
138 buf[0] |= 5;
139
140 if self.value <= 253 {
141 buf[len] = self.value as u8;
142 len += 1;
143 } else if self.value < u16::MAX as u32 {
144 buf[len] = self.value as u8;
145 len += 1;
146 let tmp = u16::to_be_bytes(self.value as u16);
147 buf[len..len + tmp.len()].copy_from_slice(&tmp);
148 len += tmp.len();
149 } else {
150 buf[len] = self.value as u8;
151 len += 1;
152 let tmp = u32::to_be_bytes(self.value);
153 buf[len..len + tmp.len()].copy_from_slice(&tmp);
154 len += tmp.len();
155 }
156 }
157
158 writer.extend_from_slice(&buf[..len]);
159 }
160
161 pub fn decode(reader: &mut Reader, buf: &[u8]) -> Result<Self, Error> {
162 let (number, byte0) = decode_tag_number(reader, buf)?;
163
164 let value = if is_extended_value(byte0) {
165 let byte = reader.read_byte(buf)?;
166 match byte {
167 255 => {
169 let bytes = reader.read_bytes(buf)?;
170 let value = u32::from_be_bytes(bytes);
171 Self { number, value }
172 }
173 254 => {
175 let bytes = reader.read_bytes(buf)?;
176 let value = u16::from_be_bytes(bytes) as u32;
177 Self { number, value }
178 }
179 _ => Self {
181 number,
182 value: byte.into(),
183 },
184 }
185 } else if is_opening_tag(byte0) | is_closing_tag(byte0) {
186 Self { number, value: 0 }
187 } else {
188 let value = (byte0 & 0x07).into();
189 Self { number, value }
190 };
191
192 Ok(value)
193 }
194
195 pub fn decode_expected(
196 reader: &mut Reader,
197 buf: &[u8],
198 expected: TagNumber,
199 context: &'static str,
200 ) -> Result<Self, Error> {
201 let tag = Self::decode(reader, buf)?;
202 if tag.number == expected {
203 Ok(tag)
204 } else {
205 Err(Error::ExpectedTag(ExpectedTag {
206 context,
207 expected,
208 actual: tag.number,
209 }))
210 }
211 }
212
213 pub fn expect_value(&self, context: &'static str, value: u32) -> Result<(), Error> {
214 if self.value != value {
215 Err(Error::TagValueInvalid((context, self.clone(), value)))
216 } else {
217 Ok(())
218 }
219 }
220
221 pub fn expect_number(&self, context: &'static str, tag_number: TagNumber) -> Result<(), Error> {
222 if self.number == tag_number {
223 Ok(())
224 } else {
225 Err(Error::ExpectedTag(ExpectedTag {
226 actual: self.number.clone(),
227 expected: tag_number,
228 context,
229 }))
230 }
231 }
232}
233
234fn decode_tag_number(reader: &mut Reader, buf: &[u8]) -> Result<(TagNumber, u8), Error> {
236 let byte0 = reader.read_byte(buf)?;
237
238 let value = if is_context_specific(byte0) {
239 if is_extended_tag_number(byte0) {
241 let num = reader.read_byte(buf)?;
242 (TagNumber::ContextSpecific(num), byte0)
243 } else {
244 let num = byte0 >> 4;
245 if is_opening_tag(byte0) {
246 (TagNumber::ContextSpecificOpening(num), 0)
247 } else if is_closing_tag(byte0) {
248 (TagNumber::ContextSpecificClosing(num), 0)
249 } else {
250 (TagNumber::ContextSpecific(num), byte0)
251 }
252 }
253 } else {
254 let num = (byte0 >> 4).into();
256 (TagNumber::Application(num), byte0)
257 };
258
259 Ok(value)
260}
261
262fn is_extended_tag_number(byte0: u8) -> bool {
263 byte0 & 0xF0 == 0xF0
264}
265
266fn is_extended_value(byte0: u8) -> bool {
267 byte0 & 0x07 == 0x05
268}
269
270fn is_context_specific(byte0: u8) -> bool {
271 byte0 & 0x08 == 0x08
272}
273
274fn is_opening_tag(byte0: u8) -> bool {
275 byte0 & 0x07 == 0x06
276}
277
278fn is_closing_tag(byte0: u8) -> bool {
279 byte0 & 0x07 == 0x07
280}