1use super::{Class, Header, Length, Tag};
2use crate::ber::ber_read_element_content_as;
3use crate::ber::bitstring_to_u64;
4use crate::ber::integer::*;
5use crate::ber::MAX_RECURSION;
6use crate::error::BerError;
7use crate::oid::Oid;
8use alloc::borrow::ToOwned;
9use alloc::boxed::Box;
10use alloc::vec::Vec;
11use asn1_rs::ASN1DateTime;
12use asn1_rs::Any;
13#[cfg(feature = "as_bitvec")]
14use bitvec::{order::Msb0, slice::BitSlice};
15use core::convert::TryFrom;
16use core::ops::Index;
17
18#[derive(Debug, Clone, PartialEq)]
26pub struct BerObject<'a> {
27 pub header: Header<'a>,
28 pub content: BerObjectContent<'a>,
29}
30
31#[derive(Debug, Clone, PartialEq)]
33#[allow(clippy::upper_case_acronyms)]
34pub enum BerObjectContent<'a> {
35 EndOfContent,
37 Boolean(bool),
39 Integer(&'a [u8]),
46 BitString(u8, BitStringObject<'a>),
48 OctetString(&'a [u8]),
50 Null,
52 Enum(u64),
54 OID(Oid<'a>),
56 RelativeOID(Oid<'a>),
58 NumericString(&'a str),
60 VisibleString(&'a str),
62 PrintableString(&'a str),
64 IA5String(&'a str),
66 UTF8String(&'a str),
68 T61String(&'a str),
70 VideotexString(&'a str),
72
73 BmpString(&'a [u8]),
78 UniversalString(&'a [u8]),
80
81 Sequence(Vec<BerObject<'a>>),
83 Set(Vec<BerObject<'a>>),
85
86 UTCTime(ASN1DateTime),
88 GeneralizedTime(ASN1DateTime),
90
91 ObjectDescriptor(&'a str),
93 GraphicString(&'a str),
95 GeneralString(&'a str),
97
98 Optional(Option<Box<BerObject<'a>>>),
100 Tagged(Class, Tag, Box<BerObject<'a>>),
102
103 Unknown(Any<'a>),
105}
106
107impl<'a> BerObject<'a> {
108 #[inline]
113 pub const fn from_header_and_content<'o>(
114 header: Header<'o>,
115 content: BerObjectContent<'o>,
116 ) -> BerObject<'o> {
117 BerObject { header, content }
118 }
119
120 pub const fn from_obj(c: BerObjectContent) -> BerObject {
123 let class = Class::Universal;
124 let tag = c.tag();
125 let constructed = matches!(tag, Tag::Sequence | Tag::Set);
126 let header = Header::new(class, constructed, tag, Length::Definite(0));
127 BerObject { header, content: c }
128 }
129
130 pub const fn from_int_slice(i: &'a [u8]) -> BerObject<'a> {
132 let header = Header::new(Class::Universal, false, Tag::Integer, Length::Definite(0));
133 BerObject {
134 header,
135 content: BerObjectContent::Integer(i),
136 }
137 }
138
139 pub fn set_raw_tag(self, raw_tag: Option<&'a [u8]>) -> BerObject<'a> {
141 let header = self.header.with_raw_tag(raw_tag.map(|x| x.into()));
142 BerObject { header, ..self }
143 }
144
145 pub const fn from_seq(l: Vec<BerObject>) -> BerObject {
147 BerObject::from_obj(BerObjectContent::Sequence(l))
148 }
149
150 pub const fn from_set(l: Vec<BerObject>) -> BerObject {
152 BerObject::from_obj(BerObjectContent::Set(l))
153 }
154
155 pub fn as_i64(&self) -> Result<i64, BerError> {
170 self.content.as_i64()
171 }
172
173 pub fn as_i32(&self) -> Result<i32, BerError> {
188 self.content.as_i32()
189 }
190
191 pub fn as_u64(&self) -> Result<u64, BerError> {
206 self.content.as_u64()
207 }
208
209 pub fn as_u32(&self) -> Result<u32, BerError> {
225 self.content.as_u32()
226 }
227
228 pub fn as_bool(&self) -> Result<bool, BerError> {
231 self.content.as_bool()
232 }
233
234 pub fn as_oid(&self) -> Result<&Oid<'a>, BerError> {
237 self.content.as_oid()
238 }
239
240 pub fn as_oid_val(&self) -> Result<Oid<'a>, BerError> {
243 self.content.as_oid_val()
244 }
245
246 pub fn as_optional(&self) -> Result<Option<&BerObject<'a>>, BerError> {
249 self.content.as_optional()
250 }
251
252 pub fn as_tagged(&self) -> Result<(Class, Tag, &BerObject<'a>), BerError> {
255 self.content.as_tagged()
256 }
257
258 pub fn as_bitstring_ref(&self) -> Result<&BitStringObject, BerError> {
264 self.content.as_bitstring_ref()
265 }
266
267 pub fn as_bitstring(&self) -> Result<BitStringObject<'a>, BerError> {
270 self.content.as_bitstring()
271 }
272
273 #[cfg(feature = "as_bitvec")]
275 pub fn as_bitslice(&self) -> Result<&BitSlice<u8, Msb0>, BerError> {
276 self.content.as_bitslice()
277 }
278
279 pub fn as_sequence(&self) -> Result<&Vec<BerObject<'a>>, BerError> {
282 self.content.as_sequence()
283 }
284
285 pub fn as_set(&self) -> Result<&Vec<BerObject<'a>>, BerError> {
288 self.content.as_set()
289 }
290
291 pub fn as_slice(&self) -> Result<&'a [u8], BerError> {
296 self.content.as_slice()
297 }
298
299 pub fn as_str(&self) -> Result<&'a str, BerError> {
305 self.content.as_str()
306 }
307
308 #[inline]
310 pub const fn class(&self) -> Class {
311 self.header.class()
312 }
313
314 #[inline]
316 pub const fn tag(&self) -> Tag {
317 self.header.tag()
318 }
319
320 #[inline]
322 pub const fn length(&self) -> Length {
323 self.header.length()
324 }
325
326 #[inline]
328 pub const fn is_universal(&self) -> bool {
329 self.header.is_universal()
330 }
331 #[inline]
333 pub const fn is_application(&self) -> bool {
334 self.header.is_application()
335 }
336 #[inline]
338 pub const fn is_contextspecific(&self) -> bool {
339 self.header.is_contextspecific()
340 }
341 #[inline]
343 pub fn is_private(&self) -> bool {
344 self.header.is_private()
345 }
346
347 #[inline]
349 pub const fn is_primitive(&self) -> bool {
350 self.header.is_primitive()
351 }
352 #[inline]
354 pub const fn is_constructed(&self) -> bool {
355 self.header.is_constructed()
356 }
357
358 #[inline]
360 pub const fn assert_class(&self, class: Class) -> Result<(), BerError> {
361 self.header.assert_class(class)
362 }
363
364 #[inline]
366 pub const fn assert_tag(&self, tag: Tag) -> Result<(), BerError> {
367 self.header.assert_tag(tag)
368 }
369
370 #[inline]
372 pub const fn assert_constructed(&self) -> Result<(), BerError> {
373 self.header.assert_constructed()
374 }
375
376 #[inline]
378 pub const fn assert_primitive(&self) -> Result<(), BerError> {
379 self.header.assert_primitive()
380 }
381}
382
383impl<'a> From<Oid<'a>> for BerObject<'a> {
385 fn from(oid: Oid<'a>) -> BerObject<'a> {
386 BerObject::from_obj(BerObjectContent::OID(oid))
387 }
388}
389
390impl<'a> From<BerObjectContent<'a>> for BerObject<'a> {
392 fn from(obj: BerObjectContent<'a>) -> BerObject<'a> {
393 BerObject::from_obj(obj)
394 }
395}
396
397impl<'a> BerObjectContent<'a> {
398 pub fn as_i64(&self) -> Result<i64, BerError> {
413 if let BerObjectContent::Integer(bytes) = self {
414 let result = if is_highest_bit_set(bytes) {
415 <i64>::from_be_bytes(decode_array_int8(bytes)?)
416 } else {
417 <u64>::from_be_bytes(decode_array_uint8(bytes)?) as i64
418 };
419 Ok(result)
420 } else {
421 Err(BerError::BerValueError)
422 }
423 }
424
425 pub fn as_i32(&self) -> Result<i32, BerError> {
440 if let BerObjectContent::Integer(bytes) = self {
441 let result = if is_highest_bit_set(bytes) {
442 <i32>::from_be_bytes(decode_array_int4(bytes)?)
443 } else {
444 <u32>::from_be_bytes(decode_array_uint4(bytes)?) as i32
445 };
446 Ok(result)
447 } else {
448 Err(BerError::BerValueError)
449 }
450 }
451
452 pub fn as_u64(&self) -> Result<u64, BerError> {
467 match self {
468 BerObjectContent::Integer(i) => {
469 let result = <u64>::from_be_bytes(decode_array_uint8(i)?);
470 Ok(result)
471 }
472 BerObjectContent::BitString(ignored_bits, data) => {
473 bitstring_to_u64(*ignored_bits as usize, data)
474 }
475 BerObjectContent::Enum(i) => Ok(*i),
476 _ => Err(BerError::BerTypeError),
477 }
478 }
479
480 pub fn as_u32(&self) -> Result<u32, BerError> {
496 match self {
497 BerObjectContent::Integer(i) => {
498 let result = <u32>::from_be_bytes(decode_array_uint4(i)?);
499 Ok(result)
500 }
501 BerObjectContent::BitString(ignored_bits, data) => {
502 bitstring_to_u64(*ignored_bits as usize, data).and_then(|x| {
503 if x > u64::from(u32::MAX) {
504 Err(BerError::IntegerTooLarge)
505 } else {
506 Ok(x as u32)
507 }
508 })
509 }
510 BerObjectContent::Enum(i) => {
511 if *i > u64::from(u32::MAX) {
512 Err(BerError::IntegerTooLarge)
513 } else {
514 Ok(*i as u32)
515 }
516 }
517 _ => Err(BerError::BerTypeError),
518 }
519 }
520
521 pub fn as_bool(&self) -> Result<bool, BerError> {
522 match *self {
523 BerObjectContent::Boolean(b) => Ok(b),
524 _ => Err(BerError::BerTypeError),
525 }
526 }
527
528 pub fn as_oid(&self) -> Result<&Oid<'a>, BerError> {
529 match *self {
530 BerObjectContent::OID(ref o) => Ok(o),
531 BerObjectContent::RelativeOID(ref o) => Ok(o),
532 _ => Err(BerError::BerTypeError),
533 }
534 }
535
536 pub fn as_oid_val(&self) -> Result<Oid<'a>, BerError> {
537 self.as_oid().cloned()
538 }
539
540 pub fn as_optional(&self) -> Result<Option<&BerObject<'a>>, BerError> {
541 match *self {
542 BerObjectContent::Optional(Some(ref o)) => Ok(Some(o)),
543 BerObjectContent::Optional(None) => Ok(None),
544 _ => Err(BerError::BerTypeError),
545 }
546 }
547
548 pub fn as_tagged(&self) -> Result<(Class, Tag, &BerObject<'a>), BerError> {
549 match *self {
550 BerObjectContent::Tagged(class, tag, ref o) => Ok((class, tag, o.as_ref())),
551 _ => Err(BerError::BerTypeError),
552 }
553 }
554
555 pub fn as_bitstring_ref(&self) -> Result<&BitStringObject, BerError> {
556 match *self {
557 BerObjectContent::BitString(_, ref b) => Ok(b),
558 _ => Err(BerError::BerTypeError),
559 }
560 }
561
562 pub fn as_bitstring(&self) -> Result<BitStringObject<'a>, BerError> {
563 match *self {
564 BerObjectContent::BitString(_, ref b) => Ok(b.to_owned()),
565 _ => Err(BerError::BerTypeError),
566 }
567 }
568
569 #[cfg(feature = "as_bitvec")]
571 pub fn as_bitslice(&self) -> Result<&BitSlice<u8, Msb0>, BerError> {
572 self.as_slice().and_then(|s| {
573 BitSlice::<_, Msb0>::try_from_slice(s).map_err(|_| BerError::BerValueError)
574 })
575 }
576
577 pub fn as_sequence(&self) -> Result<&Vec<BerObject<'a>>, BerError> {
578 match *self {
579 BerObjectContent::Sequence(ref s) => Ok(s),
580 _ => Err(BerError::BerTypeError),
581 }
582 }
583
584 pub fn as_set(&self) -> Result<&Vec<BerObject<'a>>, BerError> {
585 match *self {
586 BerObjectContent::Set(ref s) => Ok(s),
587 _ => Err(BerError::BerTypeError),
588 }
589 }
590
591 #[rustfmt::skip]
592 pub fn as_slice(&self) -> Result<&'a [u8],BerError> {
593 match *self {
594 BerObjectContent::NumericString(s) |
595 BerObjectContent::VisibleString(s) |
596 BerObjectContent::PrintableString(s) |
597 BerObjectContent::GeneralString(s) |
598 BerObjectContent::ObjectDescriptor(s) |
599 BerObjectContent::GraphicString(s) |
600 BerObjectContent::T61String(s) |
601 BerObjectContent::VideotexString(s) |
602 BerObjectContent::UTF8String(s) |
603 BerObjectContent::IA5String(s) => Ok(s.as_ref()),
604 BerObjectContent::Integer(s) |
605 BerObjectContent::BitString(_,BitStringObject{data:s}) |
606 BerObjectContent::OctetString(s) |
607 BerObjectContent::BmpString(s) |
608 BerObjectContent::UniversalString(s) => Ok(s),
609 BerObjectContent::Unknown(ref any) => Ok(any.data),
610 _ => Err(BerError::BerTypeError),
611 }
612 }
613
614 #[rustfmt::skip]
615 pub fn as_str(&self) -> Result<&'a str,BerError> {
616 match *self {
617 BerObjectContent::NumericString(s) |
618 BerObjectContent::VisibleString(s) |
619 BerObjectContent::PrintableString(s) |
620 BerObjectContent::GeneralString(s) |
621 BerObjectContent::ObjectDescriptor(s) |
622 BerObjectContent::GraphicString(s) |
623 BerObjectContent::T61String(s) |
624 BerObjectContent::VideotexString(s) |
625 BerObjectContent::UTF8String(s) |
626 BerObjectContent::IA5String(s) => Ok(s),
627 _ => Err(BerError::BerTypeError),
628 }
629 }
630
631 #[rustfmt::skip]
632 const fn tag(&self) -> Tag {
633 match self {
634 BerObjectContent::EndOfContent => Tag::EndOfContent,
635 BerObjectContent::Boolean(_) => Tag::Boolean,
636 BerObjectContent::Integer(_) => Tag::Integer,
637 BerObjectContent::BitString(_,_) => Tag::BitString,
638 BerObjectContent::OctetString(_) => Tag::OctetString,
639 BerObjectContent::Null => Tag::Null,
640 BerObjectContent::Enum(_) => Tag::Enumerated,
641 BerObjectContent::OID(_) => Tag::Oid,
642 BerObjectContent::NumericString(_) => Tag::NumericString,
643 BerObjectContent::VisibleString(_) => Tag::VisibleString,
644 BerObjectContent::PrintableString(_) => Tag::PrintableString,
645 BerObjectContent::IA5String(_) => Tag::Ia5String,
646 BerObjectContent::UTF8String(_) => Tag::Utf8String,
647 BerObjectContent::RelativeOID(_) => Tag::RelativeOid,
648 BerObjectContent::T61String(_) => Tag::T61String,
649 BerObjectContent::VideotexString(_) => Tag::VideotexString,
650 BerObjectContent::BmpString(_) => Tag::BmpString,
651 BerObjectContent::UniversalString(_) => Tag::UniversalString,
652 BerObjectContent::Sequence(_) => Tag::Sequence,
653 BerObjectContent::Set(_) => Tag::Set,
654 BerObjectContent::UTCTime(_) => Tag::UtcTime,
655 BerObjectContent::GeneralizedTime(_) => Tag::GeneralizedTime,
656 BerObjectContent::ObjectDescriptor(_) => Tag::ObjectDescriptor,
657 BerObjectContent::GraphicString(_) => Tag::GraphicString,
658 BerObjectContent::GeneralString(_) => Tag::GeneralString,
659 BerObjectContent::Tagged(_,x,_) => *x,
660 BerObjectContent::Unknown(any) => any.tag(),
661 BerObjectContent::Optional(Some(obj)) => obj.content.tag(),
662 BerObjectContent::Optional(None) => Tag(0x00), }
664 }
665}
666
667#[cfg(feature = "bigint")]
668#[cfg_attr(docsrs, doc(cfg(feature = "bigint")))]
669use num_bigint::{BigInt, BigUint};
670
671#[cfg(feature = "bigint")]
672#[cfg_attr(docsrs, doc(cfg(feature = "bigint")))]
673impl BerObject<'_> {
674 pub fn as_bigint(&self) -> Result<BigInt, BerError> {
690 match self.content {
691 BerObjectContent::Integer(s) => Ok(BigInt::from_signed_bytes_be(s)),
692 _ => Err(BerError::BerValueError),
693 }
694 }
695
696 pub fn as_biguint(&self) -> Result<BigUint, BerError> {
712 match self.content {
713 BerObjectContent::Integer(s) => {
714 if is_highest_bit_set(s) {
715 return Err(BerError::IntegerNegative);
716 }
717 Ok(BigUint::from_bytes_be(s))
718 }
719 _ => Err(BerError::BerValueError),
720 }
721 }
722}
723
724impl<'a> TryFrom<Any<'a>> for BerObject<'a> {
725 type Error = asn1_rs::Error;
726
727 fn try_from(any: Any<'a>) -> Result<Self, Self::Error> {
728 let (header, data) = (any.header, any.data);
729 let (_, content) = ber_read_element_content_as(
730 data,
731 header.tag(),
732 header.length(),
733 header.constructed(),
734 MAX_RECURSION,
735 )?;
736 let obj = BerObject::from_header_and_content(header, content);
737 Ok(obj)
738 }
739}
740
741impl<'a, 'b> TryFrom<&'b Any<'a>> for BerObject<'a> {
742 type Error = asn1_rs::Error;
743
744 fn try_from(any: &'b Any<'a>) -> Result<Self, Self::Error> {
745 let (header, data) = (any.header.clone(), any.data);
746 let (_, content) = ber_read_element_content_as(
747 data,
748 header.tag(),
749 header.length(),
750 header.constructed(),
751 MAX_RECURSION,
752 )?;
753 let obj = BerObject::from_header_and_content(header, content);
754 Ok(obj)
755 }
756}
757
758impl<'a> IntoIterator for BerObject<'a> {
760 type Item = BerObject<'a>;
761 type IntoIter = BerObjectIntoIterator<'a>;
762
763 fn into_iter(self) -> Self::IntoIter {
764 BerObjectIntoIterator { val: self, idx: 0 }
769 }
770}
771
772#[derive(Debug)]
773pub struct BerObjectIntoIterator<'a> {
774 val: BerObject<'a>,
775 idx: usize,
776}
777
778impl<'a> Iterator for BerObjectIntoIterator<'a> {
779 type Item = BerObject<'a>;
780 fn next(&mut self) -> Option<BerObject<'a>> {
781 let res = match self.val.content {
787 BerObjectContent::Sequence(ref v) if self.idx < v.len() => Some(v[self.idx].clone()),
788 BerObjectContent::Set(ref v) if self.idx < v.len() => Some(v[self.idx].clone()),
789 _ => {
790 if self.idx == 0 {
791 Some(self.val.clone())
792 } else {
793 None
794 }
795 }
796 };
797 self.idx += 1;
798 res
799 }
800}
801
802#[derive(Debug)]
811pub struct BerObjectRefIterator<'a> {
812 obj: &'a BerObject<'a>,
813 idx: usize,
814}
815
816impl<'a> Iterator for BerObjectRefIterator<'a> {
817 type Item = &'a BerObject<'a>;
818 fn next(&mut self) -> Option<&'a BerObject<'a>> {
819 let res = match (self.obj).content {
820 BerObjectContent::Sequence(ref v) if self.idx < v.len() => Some(&v[self.idx]),
821 BerObjectContent::Set(ref v) if self.idx < v.len() => Some(&v[self.idx]),
822 _ => None,
823 };
824 self.idx += 1;
825 res
826 }
827}
828
829impl<'a> BerObject<'a> {
830 pub fn ref_iter(&'a self) -> BerObjectRefIterator<'a> {
831 BerObjectRefIterator { obj: self, idx: 0 }
832 }
833}
834
835impl<'a> Index<usize> for BerObject<'a> {
836 type Output = BerObject<'a>;
837
838 fn index(&self, idx: usize) -> &BerObject<'a> {
839 match (self).content {
840 BerObjectContent::Sequence(ref v) if idx < v.len() => &v[idx],
841 BerObjectContent::Set(ref v) if idx < v.len() => &v[idx],
842 _ => panic!("Try to index BerObjectContent which is not constructed"),
843 }
844 }
850}
851
852#[derive(Clone, Debug, PartialEq)]
854pub struct BitStringObject<'a> {
855 pub data: &'a [u8],
856}
857
858impl BitStringObject<'_> {
859 pub fn is_set(&self, bitnum: usize) -> bool {
861 let byte_pos = bitnum / 8;
862 if byte_pos >= self.data.len() {
863 return false;
864 }
865 let b = 7 - (bitnum % 8);
866 (self.data[byte_pos] & (1 << b)) != 0
867 }
868
869 #[cfg(feature = "as_bitvec")]
871 pub fn as_bitslice(&self) -> Option<&BitSlice<u8, Msb0>> {
872 BitSlice::<_, Msb0>::try_from_slice(self.data).ok()
873 }
874}
875
876impl AsRef<[u8]> for BitStringObject<'_> {
877 fn as_ref(&self) -> &[u8] {
878 self.data
879 }
880}
881
882#[cfg(test)]
883mod tests {
884 use asn1_rs::{Any, FromDer};
885 use core::convert::TryFrom;
886
887 use crate::ber::*;
888 use crate::oid::*;
889
890 #[test]
891 fn ber_from_any() {
892 let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
893
894 let (rem, any) = Any::from_der(bytes).expect("parsing failed");
895 assert!(rem.is_empty());
896 let obj = BerObject::try_from(any).expect("try_from(any) failed");
897 assert_eq!(obj.as_u32(), Ok(0x10001_u32));
898 }
899
900 #[test]
901 fn test_der_as_u64() {
902 let der_obj = BerObject::from_int_slice(b"\x01\x00\x02");
903 assert_eq!(der_obj.as_u64(), Ok(0x10002));
904 }
905
906 #[test]
907 fn test_ber_as_u64_bitstring() {
908 let (_, ber_obj) = parse_ber_bitstring(b"\x03\x04\x06\x6e\x5d\xc0").unwrap();
909 assert_eq!(ber_obj.as_u64(), Ok(0b011011100101110111));
910
911 let (_, ber_obj_with_nonzero_padding) =
912 parse_ber_bitstring(b"\x03\x04\x06\x6e\x5d\xe0").unwrap();
913 assert_eq!(
914 ber_obj_with_nonzero_padding.as_u64(),
915 Ok(0b011011100101110111)
916 );
917 }
918
919 #[test]
920 fn test_der_seq_iter() {
921 let der_obj = BerObject::from_obj(BerObjectContent::Sequence(vec![
922 BerObject::from_int_slice(b"\x01\x00\x01"),
923 BerObject::from_int_slice(b"\x01\x00\x00"),
924 ]));
925 let expected_values = vec![
926 BerObject::from_int_slice(b"\x01\x00\x01"),
927 BerObject::from_int_slice(b"\x01\x00\x00"),
928 ];
929
930 for (idx, v) in der_obj.ref_iter().enumerate() {
931 assert_eq!((*v), expected_values[idx]);
933 }
934 }
935
936 #[test]
937 fn test_der_from_oid() {
938 let obj: BerObject = Oid::from(&[1, 2]).unwrap().into();
939 let expected = BerObject::from_obj(BerObjectContent::OID(Oid::from(&[1, 2]).unwrap()));
940
941 assert_eq!(obj, expected);
942 }
943
944 #[test]
945 fn test_der_bitstringobject() {
946 let obj = BitStringObject {
947 data: &[0x0f, 0x00, 0x40],
948 };
949 assert!(!obj.is_set(0));
950 assert!(obj.is_set(7));
951 assert!(!obj.is_set(9));
952 assert!(obj.is_set(17));
953 }
954
955 #[cfg(feature = "as_bitvec")]
956 #[test]
957 fn test_der_bitslice() {
958 use std::string::String;
959 let obj = BitStringObject {
960 data: &[0x0f, 0x00, 0x40],
961 };
962 let slice = obj.as_bitslice().expect("as_bitslice");
963 assert_eq!(slice.get(0).as_deref(), Some(&false));
964 assert_eq!(slice.get(7).as_deref(), Some(&true));
965 assert_eq!(slice.get(9).as_deref(), Some(&false));
966 assert_eq!(slice.get(17).as_deref(), Some(&true));
967 let s = slice.iter().fold(String::with_capacity(24), |mut acc, b| {
968 acc += if *b { "1" } else { "0" };
969 acc
970 });
971 assert_eq!(&s, "000011110000000001000000");
972 }
973
974 #[test]
975 fn test_der_bistringobject_asref() {
976 fn assert_equal<T: AsRef<[u8]>>(s: T, b: &[u8]) {
977 assert_eq!(s.as_ref(), b);
978 }
979 let b: &[u8] = &[0x0f, 0x00, 0x40];
980 let obj = BitStringObject { data: b };
981 assert_equal(obj, b);
982 }
983
984 #[cfg(feature = "bigint")]
985 #[test]
986 fn test_der_to_bigint() {
987 let obj = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01"));
988 let expected = ::num_bigint::BigInt::from(0x10001);
989
990 assert_eq!(obj.as_bigint(), Ok(expected));
991 }
992
993 #[cfg(feature = "bigint")]
994 #[test]
995 fn test_der_to_biguint() {
996 let obj = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01"));
997 let expected = ::num_bigint::BigUint::from(0x10001_u32);
998
999 assert_eq!(obj.as_biguint(), Ok(expected));
1000 }
1001}