1 //! The identifier octets of a BER encoded value. 2 //! 3 //! This is a private module. Its public items are re-exported by the parent. 4 5 use std::{fmt, io}; 6 use crate::decode; 7 8 9 //------------ Tag ----------------------------------------------------------- 10 11 /// The tag of a BER encoded value. 12 /// 13 /// Each BER encoded value starts with a sequence of one or more octets called 14 /// the _identifier octets._ They encode both the tag of the value as well as 15 /// whether the value uses primitive or constructed encoding. The `Tag` type 16 /// represents the tag only. The distinction between primitive and constructed 17 /// encoding is captured by the decoder types [`Primitive`] and 18 /// [`Constructed`] instead. 19 /// 20 /// The tag in turn consists of two parts: the class and the number – the 21 /// `Tag` type includes both of them. 22 /// 23 /// # Limitations 24 /// 25 /// We can only decode up to four identifier octets. That is, we only support tag 26 /// numbers between 0 and 1fffff. 27 /// 28 /// [`Primitive`]: decode/struct.Primitive.html 29 /// [`Constructed`]: decode/struct.Constructed.html 30 // 31 // For the moment, the tag is stored with the constructed bit always cleared. 32 #[derive(Clone, Copy, Eq, PartialEq)] 33 pub struct Tag([u8; 4]); 34 35 /// # Constants for Often Used Tag Values 36 /// 37 impl Tag { 38 /// The mask for checking the class. 39 const CLASS_MASK: u8 = 0xc0; 40 41 /// The mask for checking whether the value is a primitive 42 /// 43 /// A value of 0 indicates primitive. 44 const CONSTRUCTED_MASK: u8 = 0x20; 45 46 /// The mask for the fourth octet data (bits 24-32). 47 /// 48 /// (5 bits – 0b0001_1111). 49 const SINGLEBYTE_DATA_MASK: u8 = 0x1f; 50 51 /// The mask for octet data. 52 /// 53 /// (7 bits – 0b0111_1111). 54 const MULTIBYTE_DATA_MASK: u8 = 0x7f; 55 56 /// The mask for the last octet with identifier data 57 /// 58 /// (1 bit – 0b1000_0000, it is cleared in the last octet). 59 const LAST_OCTET_MASK: u8 = 0x80; 60 61 /// The largest tag number possible with three octets. 62 const MAX_VAL_SPAN_3_OCTETS: u32 = 0x001f_ffff; 63 64 /// The largest tag number possible with two octets. 65 const MAX_VAL_SPAN_2_OCTETS: u32 = 0x3fff; 66 67 /// The largest tag number possible with one octet. 68 const MAX_VAL_SPAN_1_OCTET: u32 = 0x7f; 69 70 /// The largest tag number possible with the fourth octet. 71 const MAX_VAL_FOURTH_OCTET: u32 = 0x1e; 72 73 /// The tag value representing for the ‘universal’ class. 74 const UNIVERSAL: u8 = 0x00; 75 76 /// The tag value representing the ‘application’ class. 77 const APPLICATION: u8 = 0x40; 78 79 /// The tag value representing the ‘context-specific’ class. 80 const CONTEXT_SPECIFIC: u8 = 0x80; 81 82 /// The tag value representing the `private` class. 83 const PRIVATE: u8 = 0xc0; 84 85 /// The tag marking the end-of-value in an indefinite length value. 86 /// 87 /// This is UNIVERSAL 0. 88 pub const END_OF_VALUE: Self = Tag([0, 0, 0, 0]); 89 90 //--- Universal Tags 91 // 92 // See clause 8.4 of X.690. 93 94 /// The tag for the BOOLEAN type, UNIVERSAL 1. 95 pub const BOOLEAN: Self = Tag([1, 0, 0, 0]); 96 97 /// The tag for the INTEGER type, UNIVERSAL 2. 98 pub const INTEGER: Self = Tag([2, 0, 0, 0]); 99 100 /// The tag for the BIT STRING type, UNIVERSAL 3. 101 pub const BIT_STRING: Self = Tag([3, 0, 0, 0]); 102 103 /// The tag for the OCTET STRING type, UNIVERSAL 4. 104 pub const OCTET_STRING: Self = Tag([4, 0, 0, 0]); 105 106 /// The tag for the NULL type, UNIVERSAL 5. 107 pub const NULL: Self = Tag([5, 0, 0, 0]); 108 109 /// The tag for the OBJECT IDENTIFIER type, UNIVERSAL 6. 110 pub const OID: Self = Tag([6, 0, 0, 0]); 111 112 /// The tag for the ObjectDescriptor type, UNIVERSAL 7. 113 pub const OBJECT_DESCRIPTOR: Self = Tag([7, 0, 0, 0]); 114 115 /// The tag for the EXTERNAL and Instance-of types, UNIVERSAL 8. 116 pub const EXTERNAL: Self = Tag([8, 0, 0, 0]); 117 118 /// The tag for the REAL type, UNIVERSAL 9. 119 pub const REAL: Self = Tag([9, 0, 0, 0]); 120 121 /// The tag for the ENUMERATED type, UNIVERAL 10. 122 pub const ENUMERATED: Self = Tag([10, 0, 0, 0]); 123 124 /// The tag for the EMBEDDED PDV type, UNIVERAL 11. 125 pub const EMBEDDED_PDV: Self = Tag([11, 0, 0, 0]); 126 127 /// The tag for the UTF8String type, UNIVERSAL 12 128 pub const UTF8_STRING: Self = Tag([12, 0, 0, 0]); 129 130 /// The tag for the RELATIVE-OID type, UNIVERAL 13. 131 pub const RELATIVE_OID: Self = Tag([13, 0, 0, 0]); 132 133 /// The tag for the SEQUENCE and SEQUENCE OF types, UNIVERSAL 16. 134 pub const SEQUENCE: Self = Tag([16, 0, 0, 0]); 135 136 /// The tag for the SET and SET OF types, UNIVERSAL 17. 137 pub const SET: Self = Tag([17, 0, 0, 0]); 138 139 /// The tag for the NumericString type, UNIVERSAL 18. 140 pub const NUMERIC_STRING: Self = Tag([18, 0, 0, 0]); 141 142 /// The tag for the PrintableString type, UNIVERSAL 19. 143 pub const PRINTABLE_STRING: Self = Tag([19, 0, 0, 0]); 144 145 /// The tag for the TeletexString type, UNIVERSAL 20. 146 pub const TELETEX_STRING: Self = Tag([20, 0, 0, 0]); 147 148 /// The tag for the VideotexString type, UNIVERSAL 21. 149 pub const VIDEOTEX_STRING: Self = Tag([21, 0, 0, 0]); 150 151 /// The tag for the IA5String type, UNIVERSAL 22. 152 pub const IA5_STRING: Self = Tag([22, 0, 0, 0]); 153 154 /// The tag for the UTCTime type, UNIVERSAL 23. 155 pub const UTC_TIME: Self = Tag([23, 0, 0, 0]); 156 157 /// The tag for the GeneralizedType type, UNIVERAL 24. 158 pub const GENERALIZED_TIME: Self = Tag([24, 0, 0, 0]); 159 160 /// The tag for the GraphicString type, UNIVERSAL 25. 161 pub const GRAPHIC_STRING: Self = Tag([25, 0, 0, 0]); 162 163 /// The tag for the VisibleString type, UNIVERSAL 26. 164 pub const VISIBLE_STRING: Self = Tag([26, 0, 0, 0]); 165 166 /// The tag for the GeneralString type, UNIVERSAL 27. 167 pub const GENERAL_STRING: Self = Tag([27, 0, 0, 0]); 168 169 /// The tag for the UniversalString type, UNIVERSAL 28. 170 pub const UNIVERSAL_STRING: Self = Tag([28, 0, 0, 0]); 171 172 /// The tag for the BMPString type, UNIVERSAL 29. 173 pub const BMP_STRING: Self = Tag([29, 0, 0, 0]); 174 175 //--- The first few context-specific tags. 176 // 177 // These will be removed once we can have `ctx` be a const fn. 178 179 /// The tag context specific tag [0]. 180 pub const CTX_0: Self = Tag([Tag::CONTEXT_SPECIFIC, 0, 0, 0]); 181 182 /// The tag context specific tag [1]. 183 pub const CTX_1: Self = Tag([Tag::CONTEXT_SPECIFIC | 1, 0, 0, 0]); 184 185 /// The tag context specific tag [2]. 186 pub const CTX_2: Self = Tag([Tag::CONTEXT_SPECIFIC | 2, 0, 0, 0]); 187 188 /// The tag context specific tag [3]. 189 pub const CTX_3: Self = Tag([Tag::CONTEXT_SPECIFIC | 3, 0, 0, 0]); 190 191 /// The tag context specific tag [4]. 192 pub const CTX_4: Self = Tag([Tag::CONTEXT_SPECIFIC | 4, 0, 0, 0]); 193 194 /// The tag context specific tag [5]. 195 pub const CTX_5: Self = Tag([Tag::CONTEXT_SPECIFIC | 5, 0, 0, 0]); 196 197 /// The tag context specific tag [6]. 198 pub const CTX_6: Self = Tag([Tag::CONTEXT_SPECIFIC | 6, 0, 0, 0]); 199 } 200 201 impl Tag { 202 /// Encodes a number into the identifier representation. 203 /// 204 /// There are two forms: 205 /// * low tag number (for tag numbers between 0 and 30): 206 /// One octet. Bits 8 and 7 specify the class, bit 6 indicates whether 207 /// the encoding is primitive (0), and bits 5-1 give the tag number. 208 /// * high tag number (for tag numbers 31 and greater): 209 /// Two or more octets. First octet is as in low-tag-number form, 210 /// except that bits 5-1 all have value 1. Second and following octets 211 /// give the tag number, base 128, most significant digit first, with 212 /// as few digits as possible, and with the bit 8 of each octet except 213 /// the last set to 1. 214 // 215 /// # Panics 216 /// 217 /// This function panics if the tag number is greater than 218 /// `Self::MAX_VAL_SPAN_3_OCTETS`. 219 #[inline] new(class_mask: u8, number: u32) -> Self220 fn new(class_mask: u8, number: u32) -> Self { 221 assert!(number <= Tag::MAX_VAL_SPAN_3_OCTETS); 222 if number <= Tag::MAX_VAL_FOURTH_OCTET { 223 Tag([class_mask | number as u8, 0, 0, 0]) 224 } else if number <= Tag::MAX_VAL_SPAN_1_OCTET { 225 // Fit the number in the third octets 226 let number = number as u8; 227 Tag([class_mask | Tag::SINGLEBYTE_DATA_MASK, number, 0, 0]) 228 } else if number <= Tag::MAX_VAL_SPAN_2_OCTETS { 229 // Fit the number in the second and the third octets 230 let first_part = { 231 Tag::MULTIBYTE_DATA_MASK & ((number >> 7) as u8) 232 | Tag::LAST_OCTET_MASK 233 }; 234 let second_part = Tag::MULTIBYTE_DATA_MASK & (number as u8); 235 Tag([ 236 class_mask | Tag::SINGLEBYTE_DATA_MASK, first_part, 237 second_part, 0 238 ]) 239 } else { 240 // Fit the number in the first, second and the third octets 241 let first_part = { 242 Tag::MULTIBYTE_DATA_MASK & ((number >> 14) as u8) 243 | Tag::LAST_OCTET_MASK 244 }; 245 let second_part = { 246 Tag::MULTIBYTE_DATA_MASK & ((number >> 7) as u8) 247 | Tag::LAST_OCTET_MASK 248 }; 249 let third_part = Tag::MULTIBYTE_DATA_MASK & (number as u8); 250 Tag([ 251 class_mask | Tag::SINGLEBYTE_DATA_MASK, first_part, 252 second_part, third_part 253 ]) 254 } 255 } 256 257 /// Creates a new tag in the universal class with the given tag number. 258 /// 259 /// # Panics 260 /// 261 /// Currently, this function panics if the tag number is greater than 262 /// `MAX_VAL_SPAN_3_OCTETS`. universal(number: u32) -> Self263 pub fn universal(number: u32) -> Self { 264 Tag::new(Tag::UNIVERSAL, number) 265 } 266 267 /// Creates a new tag in the application class with the given tag number. 268 /// 269 /// # Panics 270 /// 271 /// Currently, this function panics if the tag number is greater than 272 /// `MAX_VAL_SPAN_3_OCTETS`. application(number: u32) -> Self273 pub fn application(number: u32) -> Self { 274 Tag::new(Tag::APPLICATION, number) 275 } 276 277 /// Creates a new tag in the context specific class. 278 /// 279 /// # Panics 280 /// 281 /// Currently, this function panics if the provided tag number is greater 282 /// than `MAX_VAL_SPAN_3_OCTETS`. ctx(number: u32) -> Self283 pub fn ctx(number: u32) -> Self { 284 Tag::new(Tag::CONTEXT_SPECIFIC, number) 285 } 286 287 /// Creates a new tag in the private class with the given tag number. 288 /// 289 /// # Panics 290 /// 291 /// Currently, this function panics if the provided tag number is greater 292 /// than `MAX_VAL_SPAN_3_OCTETS`. private(number: u32) -> Self293 pub fn private(number: u32) -> Self { 294 Tag::new(Tag::PRIVATE, number) 295 } 296 297 /// Returns whether the tag is of the universal class. is_universal(self) -> bool298 pub fn is_universal(self) -> bool { 299 self.0[0] & Self::CLASS_MASK == Self::UNIVERSAL 300 } 301 302 /// Returns whether the tag is of the application class. is_application(self) -> bool303 pub fn is_application(self) -> bool { 304 self.0[0] & Self::CLASS_MASK == Self::APPLICATION 305 } 306 307 /// Returns whether the tag is of the context specific class. is_context_specific(self) -> bool308 pub fn is_context_specific(self) -> bool { 309 self.0[0] & Self::CLASS_MASK == Self::CONTEXT_SPECIFIC 310 } 311 312 /// Returns whether the tag is of the private class. is_private(self) -> bool313 pub fn is_private(self) -> bool { 314 self.0[0] & Self::CLASS_MASK == Self::PRIVATE 315 } 316 317 /// Returns the number of the tag. number(self) -> u32318 pub fn number(self) -> u32 { 319 if (Tag::SINGLEBYTE_DATA_MASK & self.0[0]) != Tag::SINGLEBYTE_DATA_MASK { 320 // It's a single byte identifier 321 u32::from(Tag::SINGLEBYTE_DATA_MASK & self.0[0]) 322 } else if Tag::LAST_OCTET_MASK & self.0[1] == 0 { 323 // It's a multibyte that starts and ends in the third octet 324 u32::from(Tag::MULTIBYTE_DATA_MASK & self.0[1]) 325 } else if Tag::LAST_OCTET_MASK & self.0[2] == 0 { 326 // It's a multibyte that starts in the second octet and ends in 327 // the third octet 328 u32::from(Tag::MULTIBYTE_DATA_MASK & self.0[1]) << 7 329 | u32::from(Tag::MULTIBYTE_DATA_MASK & self.0[2]) 330 } else { 331 // It's a multibyte that spans the first three octets 332 u32::from(Tag::MULTIBYTE_DATA_MASK & self.0[1]) << 14 333 | u32::from(Tag::MULTIBYTE_DATA_MASK & self.0[2]) << 7 334 | u32::from(Tag::MULTIBYTE_DATA_MASK & self.0[3]) 335 } 336 } 337 338 /// Takes a tag from the beginning of a source. 339 /// 340 /// Upon success, returns both the tag and whether the value is 341 /// constructed. If there are no more octets available in the source, 342 /// an error is returned. take_from<S: decode::Source>( source: &mut S, ) -> Result<(Self, bool), S::Err>343 pub fn take_from<S: decode::Source>( 344 source: &mut S, 345 ) -> Result<(Self, bool), S::Err> { 346 let byte = source.take_u8()?; 347 // clear constructed bit 348 let mut data = [byte & !Tag::CONSTRUCTED_MASK, 0, 0, 0]; 349 let constructed = byte & Tag::CONSTRUCTED_MASK != 0; 350 if (data[0] & Tag::SINGLEBYTE_DATA_MASK) == Tag::SINGLEBYTE_DATA_MASK { 351 for i in 1..=3 { 352 data[i] = source.take_u8()?; 353 if data[i] & Tag::LAST_OCTET_MASK == 0 { 354 return Ok((Tag(data), constructed)); 355 } 356 } 357 } else { 358 return Ok((Tag(data), constructed)); 359 } 360 xerr!(Err(decode::Error::Unimplemented.into())) 361 } 362 363 /// Takes a tag from the beginning of a resource if it matches this tag. 364 /// 365 /// If there is no more data available in the source or if the tag is 366 /// something else, returns `Ok(None)`. If the tag matches `self`, returns 367 /// whether the value is constructed. take_from_if<S: decode::Source>( self, source: &mut S, ) -> Result<Option<bool>, S::Err>368 pub fn take_from_if<S: decode::Source>( 369 self, 370 source: &mut S, 371 ) -> Result<Option<bool>, S::Err> { 372 if source.request(1)? == 0 { 373 return Ok(None) 374 } 375 let byte = source.slice()[0]; 376 // clear constructed bit 377 let mut data = [byte & !Tag::CONSTRUCTED_MASK, 0, 0, 0]; 378 if (data[0] & Tag::SINGLEBYTE_DATA_MASK) == Tag::SINGLEBYTE_DATA_MASK { 379 let mut i = 1; 380 loop { 381 if source.request(i + 1)? == 0 { 382 // Not enough data for a complete tag. 383 xerr!(return Err(decode::Error::Malformed.into())) 384 } 385 data[i] = source.slice()[i]; 386 if data[i] & Tag::LAST_OCTET_MASK == 0 { 387 break 388 } 389 // We don’t support tags larger than 4 bytes. 390 if i == 3 { 391 xerr!(return Err(decode::Error::Unimplemented.into())) 392 } 393 i += 1; 394 } 395 } 396 let (tag, compressed) = (Tag(data), byte & Tag::CONSTRUCTED_MASK != 0); 397 if tag == self { 398 source.advance(tag.encoded_len())?; 399 Ok(Some(compressed)) 400 } 401 else { 402 Ok(None) 403 } 404 } 405 406 /// Returns the number of octets of the encoded form of the tag. 407 #[allow(clippy::trivially_copy_pass_by_ref)] // for possible multi-byte tags encoded_len(&self) -> usize408 pub fn encoded_len(&self) -> usize { 409 if (Tag::SINGLEBYTE_DATA_MASK & self.0[0]) != Tag::SINGLEBYTE_DATA_MASK { 410 1 411 } else if Tag::LAST_OCTET_MASK & self.0[1] == 0 { 412 2 413 } else if Tag::LAST_OCTET_MASK & self.0[2] == 0 { 414 3 415 } else { 416 4 417 } 418 } 419 420 /// Encodes the tag into a target. 421 /// 422 /// If `constructed` is `true`, the encoded tag will signal a value in 423 /// constructed encoding and primitive encoding otherwise. 424 #[allow(clippy::trivially_copy_pass_by_ref)] // for possible multi-byte tags write_encoded<W: io::Write>( &self, constructed: bool, target: &mut W ) -> Result<(), io::Error>425 pub fn write_encoded<W: io::Write>( 426 &self, 427 constructed: bool, 428 target: &mut W 429 ) -> Result<(), io::Error> { 430 let mut buf = self.0; 431 if constructed { 432 buf[0] |= Tag::CONSTRUCTED_MASK 433 } 434 target.write_all(&buf[..self.encoded_len()]) 435 } 436 } 437 438 impl fmt::Display for Tag { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result439 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 440 match *self { 441 Tag::BOOLEAN => write!(f, "BOOLEAN"), 442 Tag::INTEGER => write!(f, "INTEGER"), 443 Tag::BIT_STRING => write!(f, "BIT STRING"), 444 Tag::OCTET_STRING => write!(f, "OCTET STRING"), 445 Tag::NULL => write!(f, "NULL"), 446 Tag::OID => write!(f, "OBJECT IDENTIFIER"), 447 Tag::OBJECT_DESCRIPTOR => write!(f, "ObjectDescriptor"), 448 Tag::EXTERNAL => write!(f, "EXTERNAL"), 449 Tag::REAL => write!(f, "REAL"), 450 Tag::ENUMERATED => write!(f, "ENUMERATED"), 451 Tag::EMBEDDED_PDV => write!(f, "EMBEDDED PDV"), 452 Tag::UTF8_STRING => write!(f, "UTF8String"), 453 Tag::RELATIVE_OID => write!(f, "RELATIVE-OID"), 454 Tag::SEQUENCE => write!(f, "SEQUENCE"), 455 Tag::SET => write!(f, "SET"), 456 Tag::NUMERIC_STRING => write!(f, "NumericString"), 457 Tag::PRINTABLE_STRING => write!(f, "PrintableString"), 458 Tag::TELETEX_STRING => write!(f, "TeletexString"), 459 Tag::VIDEOTEX_STRING => write!(f, "VideotexString"), 460 Tag::IA5_STRING => write!(f, "IA5String"), 461 Tag::UTC_TIME => write!(f, "UTCTime"), 462 Tag::GENERALIZED_TIME => write!(f, "GeneralizedTime"), 463 Tag::GRAPHIC_STRING => write!(f, "GraphicString"), 464 Tag::VISIBLE_STRING => write!(f, "VisibleString"), 465 Tag::GENERAL_STRING => write!(f, "GeneralString"), 466 Tag::UNIVERSAL_STRING => write!(f, "UniversalString"), 467 Tag::BMP_STRING => write!(f, "BMPString"), 468 tag => { 469 match tag.0[0] & Tag::CLASS_MASK { 470 Tag::UNIVERSAL => write!(f, "[UNIVERSAL ")?, 471 Tag::APPLICATION => write!(f, "[APPLICATION ")?, 472 Tag::CONTEXT_SPECIFIC => write!(f, "[")?, 473 Tag::PRIVATE => write!(f, "[PRIVATE ")?, 474 _ => unreachable!() 475 } 476 write!(f, "{}]", tag.number()) 477 } 478 } 479 } 480 } 481 482 impl fmt::Debug for Tag { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result483 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 484 write!(f, "Tag({})", self) 485 } 486 } 487 488 //============ Tests ========================================================= 489 490 #[cfg(test)] 491 mod test { 492 use super::*; 493 494 const TYPES: &[u8] = &[Tag::UNIVERSAL, Tag::APPLICATION, Tag::CONTEXT_SPECIFIC, Tag::PRIVATE]; 495 496 #[test] test_single_octet_tags()497 fn test_single_octet_tags() { 498 // Test edge cases. 499 let range: Vec<u32> = (0..5).chain( 500 Tag::MAX_VAL_FOURTH_OCTET-5..Tag::MAX_VAL_FOURTH_OCTET 501 ).collect(); 502 for &typ in TYPES { 503 for i in range.clone() { 504 let tag = Tag::new(typ, i); 505 let expected = Tag([typ | i as u8, 0, 0, 0]); 506 let decoded = Tag::take_from(&mut &tag.0[..]).unwrap(); 507 assert_eq!(tag.take_from_if(&mut &tag.0[..]), Ok(Some(false))); 508 // The value is not constructed. 509 assert_eq!(decoded.1, false); 510 // The tag is the same 511 assert_eq!(decoded.0, expected); 512 // We get the same number back. 513 assert_eq!(tag.number(), i); 514 // The representation is correct. 515 assert_eq!(tag, expected); 516 517 } 518 } 519 } 520 521 #[test] test_double_octets_tags()522 fn test_double_octets_tags() { 523 // Test edge cases. 524 let range: Vec<u32> = ( 525 Tag::MAX_VAL_FOURTH_OCTET+1..Tag::MAX_VAL_FOURTH_OCTET+5 526 ).chain( 527 Tag::MAX_VAL_SPAN_1_OCTET-5..Tag::MAX_VAL_SPAN_1_OCTET 528 ).collect(); 529 for &typ in TYPES { 530 for i in range.clone() { 531 let tag = Tag::new(typ, i); 532 let expected = Tag([ 533 Tag::SINGLEBYTE_DATA_MASK | typ, i as u8, 0, 0 534 ]); 535 let decoded = Tag::take_from(&mut &tag.0[..]).unwrap(); 536 assert_eq!(tag.take_from_if(&mut &tag.0[..]), Ok(Some(false))); 537 // The value is not constructed. 538 assert_eq!(decoded.1, false); 539 // The tag is the same 540 assert_eq!(decoded.0, expected); 541 assert_eq!(tag.number(), i); 542 assert_eq!(tag, expected); 543 } 544 } 545 } 546 547 #[test] test_three_octets_tags()548 fn test_three_octets_tags() { 549 // Test edge cases. 550 let range: Vec<u32> = ( 551 Tag::MAX_VAL_SPAN_1_OCTET+1..Tag::MAX_VAL_SPAN_1_OCTET + 5 552 ).chain( 553 Tag::MAX_VAL_SPAN_2_OCTETS-5..Tag::MAX_VAL_SPAN_2_OCTETS 554 ).collect(); 555 for &typ in TYPES { 556 for i in range.clone() { 557 let tag = Tag::new(typ, i); 558 let expected = Tag([ 559 Tag::SINGLEBYTE_DATA_MASK | typ, 560 (i >> 7) as u8 | Tag::LAST_OCTET_MASK, 561 i as u8 & !Tag::LAST_OCTET_MASK, 562 0 563 ]); 564 let decoded = Tag::take_from(&mut &tag.0[..]).unwrap(); 565 assert_eq!(tag.take_from_if(&mut &tag.0[..]), Ok(Some(false))); 566 // The value is not constructed. 567 assert_eq!(decoded.1, false); 568 // The tag is the same 569 assert_eq!(decoded.0, expected); 570 assert_eq!(tag.number(), i); 571 assert_eq!(tag, expected); 572 } 573 } 574 } 575 576 #[test] test_four_octets_tags()577 fn test_four_octets_tags() { 578 // Test edge cases. 579 let range: Vec<u32> = ( 580 Tag::MAX_VAL_SPAN_2_OCTETS+1..Tag::MAX_VAL_SPAN_2_OCTETS + 5 581 ).chain( 582 Tag::MAX_VAL_SPAN_3_OCTETS-5..Tag::MAX_VAL_SPAN_3_OCTETS 583 ).collect(); 584 for &typ in TYPES { 585 for i in range.clone() { 586 let tag = Tag::new(typ, i); 587 let expected = Tag([ 588 Tag::SINGLEBYTE_DATA_MASK | typ, 589 (i >> 14) as u8 | Tag::LAST_OCTET_MASK, 590 (i >> 7) as u8 | Tag::LAST_OCTET_MASK, 591 i as u8 & !Tag::LAST_OCTET_MASK 592 ]); 593 let decoded = Tag::take_from(&mut &tag.0[..]).unwrap(); 594 assert_eq!(tag.take_from_if(&mut &tag.0[..]), Ok(Some(false))); 595 // The value is not constructed. 596 assert_eq!(decoded.1, false); 597 // The tag is the same 598 assert_eq!(decoded.0, expected); 599 assert_eq!(tag.number(), i); 600 assert_eq!(tag, expected); 601 } 602 } 603 } 604 605 #[test] test_tags_failures()606 fn test_tags_failures() { 607 let large_tag = [ 608 0b1111_1111, 0b1000_0000, 0b1000_0000, 0b1000_0000, 0b1000_0000 609 ]; 610 assert_eq!( 611 Tag::take_from(&mut &large_tag[..]), 612 Err(decode::Error::Unimplemented) 613 ); 614 let short_tag = [0b1111_1111, 0b1000_0000]; 615 assert_eq!( 616 Tag::take_from(&mut &short_tag[..]), 617 Err(decode::Error::Malformed) 618 ); 619 } 620 } 621