1use std::{fmt, io};
6use crate::decode::{DecodeError, Source};
7
8
9#[derive(Clone, Copy, Eq, PartialEq)]
33pub struct Tag([u8; 4]);
34
35impl Tag {
38 const CLASS_MASK: u8 = 0xc0;
40
41 const CONSTRUCTED_MASK: u8 = 0x20;
45
46 const SINGLEBYTE_DATA_MASK: u8 = 0x1f;
50
51 const MULTIBYTE_DATA_MASK: u8 = 0x7f;
55
56 const LAST_OCTET_MASK: u8 = 0x80;
60
61 const MAX_VAL_SPAN_3_OCTETS: u32 = 0x001f_ffff;
63
64 const MAX_VAL_SPAN_2_OCTETS: u32 = 0x3fff;
66
67 const MAX_VAL_SPAN_1_OCTET: u32 = 0x7f;
69
70 const MAX_VAL_FOURTH_OCTET: u32 = 0x1e;
72
73 const UNIVERSAL: u8 = 0x00;
75
76 const APPLICATION: u8 = 0x40;
78
79 const CONTEXT_SPECIFIC: u8 = 0x80;
81
82 const PRIVATE: u8 = 0xc0;
84
85 pub const END_OF_VALUE: Self = Tag([0, 0, 0, 0]);
89
90 pub const BOOLEAN: Self = Tag([1, 0, 0, 0]);
96
97 pub const INTEGER: Self = Tag([2, 0, 0, 0]);
99
100 pub const BIT_STRING: Self = Tag([3, 0, 0, 0]);
102
103 pub const OCTET_STRING: Self = Tag([4, 0, 0, 0]);
105
106 pub const NULL: Self = Tag([5, 0, 0, 0]);
108
109 pub const OID: Self = Tag([6, 0, 0, 0]);
111
112 pub const OBJECT_DESCRIPTOR: Self = Tag([7, 0, 0, 0]);
114
115 pub const EXTERNAL: Self = Tag([8, 0, 0, 0]);
117
118 pub const REAL: Self = Tag([9, 0, 0, 0]);
120
121 pub const ENUMERATED: Self = Tag([10, 0, 0, 0]);
123
124 pub const EMBEDDED_PDV: Self = Tag([11, 0, 0, 0]);
126
127 pub const UTF8_STRING: Self = Tag([12, 0, 0, 0]);
129
130 pub const RELATIVE_OID: Self = Tag([13, 0, 0, 0]);
132
133 pub const TIME: Self = Tag([14, 0, 0, 0]);
135
136 pub const SEQUENCE: Self = Tag([16, 0, 0, 0]);
138
139 pub const SET: Self = Tag([17, 0, 0, 0]);
141
142 pub const NUMERIC_STRING: Self = Tag([18, 0, 0, 0]);
144
145 pub const PRINTABLE_STRING: Self = Tag([19, 0, 0, 0]);
147
148 pub const TELETEX_STRING: Self = Tag([20, 0, 0, 0]);
150
151 pub const VIDEOTEX_STRING: Self = Tag([21, 0, 0, 0]);
153
154 pub const IA5_STRING: Self = Tag([22, 0, 0, 0]);
156
157 pub const UTC_TIME: Self = Tag([23, 0, 0, 0]);
159
160 pub const GENERALIZED_TIME: Self = Tag([24, 0, 0, 0]);
162
163 pub const GRAPHIC_STRING: Self = Tag([25, 0, 0, 0]);
165
166 pub const VISIBLE_STRING: Self = Tag([26, 0, 0, 0]);
168
169 pub const GENERAL_STRING: Self = Tag([27, 0, 0, 0]);
171
172 pub const UNIVERSAL_STRING: Self = Tag([28, 0, 0, 0]);
174
175 pub const CHARACTER_STRING: Self = Tag([29, 0, 0, 0]);
177
178 pub const BMP_STRING: Self = Tag([30, 0, 0, 0]);
180
181 pub const DATE: Self = Tag([31, 0, 0, 0]);
183
184 pub const TIME_OF_DAY: Self = Tag([32, 0, 0, 0]);
186
187 pub const DATE_TIME: Self = Tag([33, 0, 0, 0]);
189
190 pub const DURATION: Self = Tag([34, 0, 0, 0]);
192
193 pub const OID_IRI: Self = Tag([35, 0, 0, 0]);
195
196 pub const RELATIVE_OID_IRI: Self = Tag([36, 0, 0, 0]);
198
199 pub const CTX_0: Self = Tag([Tag::CONTEXT_SPECIFIC, 0, 0, 0]);
205
206 pub const CTX_1: Self = Tag([Tag::CONTEXT_SPECIFIC | 1, 0, 0, 0]);
208
209 pub const CTX_2: Self = Tag([Tag::CONTEXT_SPECIFIC | 2, 0, 0, 0]);
211
212 pub const CTX_3: Self = Tag([Tag::CONTEXT_SPECIFIC | 3, 0, 0, 0]);
214
215 pub const CTX_4: Self = Tag([Tag::CONTEXT_SPECIFIC | 4, 0, 0, 0]);
217
218 pub const CTX_5: Self = Tag([Tag::CONTEXT_SPECIFIC | 5, 0, 0, 0]);
220
221 pub const CTX_6: Self = Tag([Tag::CONTEXT_SPECIFIC | 6, 0, 0, 0]);
223}
224
225impl Tag {
226 #[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 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 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 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 pub fn universal(number: u32) -> Self {
288 Tag::new(Tag::UNIVERSAL, number)
289 }
290
291 pub fn application(number: u32) -> Self {
298 Tag::new(Tag::APPLICATION, number)
299 }
300
301 pub fn ctx(number: u32) -> Self {
308 Tag::new(Tag::CONTEXT_SPECIFIC, number)
309 }
310
311 pub fn private(number: u32) -> Self {
318 Tag::new(Tag::PRIVATE, number)
319 }
320
321 pub fn is_universal(self) -> bool {
323 self.0[0] & Self::CLASS_MASK == Self::UNIVERSAL
324 }
325
326 pub fn is_application(self) -> bool {
328 self.0[0] & Self::CLASS_MASK == Self::APPLICATION
329 }
330
331 pub fn is_context_specific(self) -> bool {
333 self.0[0] & Self::CLASS_MASK == Self::CONTEXT_SPECIFIC
334 }
335
336 pub fn is_private(self) -> bool {
338 self.0[0] & Self::CLASS_MASK == Self::PRIVATE
339 }
340
341 pub fn number(self) -> u32 {
343 if (Tag::SINGLEBYTE_DATA_MASK & self.0[0])
344 != Tag::SINGLEBYTE_DATA_MASK
345 {
346 u32::from(Tag::SINGLEBYTE_DATA_MASK & self.0[0])
348 } else if Tag::LAST_OCTET_MASK & self.0[1] == 0 {
349 u32::from(Tag::MULTIBYTE_DATA_MASK & self.0[1])
351 } else if Tag::LAST_OCTET_MASK & self.0[2] == 0 {
352 (u32::from(Tag::MULTIBYTE_DATA_MASK & self.0[1]) << 7)
355 | u32::from(Tag::MULTIBYTE_DATA_MASK & self.0[2])
356 } else {
357 (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 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 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 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 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 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 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 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 #[allow(clippy::trivially_copy_pass_by_ref)] 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 #[allow(clippy::trivially_copy_pass_by_ref)] 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#[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 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 assert!(!decoded.1);
573 assert_eq!(decoded.0, expected);
575 assert_eq!(tag.number(), i);
577 assert_eq!(tag, expected);
579
580 }
581 }
582 }
583
584 #[test]
585 fn test_double_octets_tags() {
586 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 assert!(!decoded.1);
612 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 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 assert!(!decoded.1);
651 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 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 assert!(!decoded.1);
690 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}