diff --git a/src/asn1_types/optional.rs b/src/asn1_types/optional.rs index a8027ab..4aa31ae 100644 --- a/src/asn1_types/optional.rs +++ b/src/asn1_types/optional.rs @@ -8,14 +8,20 @@ use crate::*; impl<'a, T> FromBer<'a> for Option where T: FromBer<'a>, + T: Tagged, { fn from_ber(bytes: &'a [u8]) -> ParseResult { if bytes.is_empty() { return Ok((bytes, None)); } + if let Ok((_, header)) = Header::from_ber(bytes) { + if T::TAG != header.tag { + // not the expected tag, early return + return Ok((bytes, None)); + } + } match T::from_ber(bytes) { Ok((rem, t)) => Ok((rem, Some(t))), - Err(nom::Err::Error(Error::UnexpectedTag { .. })) => Ok((bytes, None)), Err(e) => Err(e), } } @@ -24,14 +30,20 @@ where impl<'a, T> FromDer<'a> for Option where T: FromDer<'a>, + T: Tagged, { fn from_der(bytes: &'a [u8]) -> ParseResult { if bytes.is_empty() { return Ok((bytes, None)); } + if let Ok((_, header)) = Header::from_der(bytes) { + if T::TAG != header.tag { + // not the expected tag, early return + return Ok((bytes, None)); + } + } match T::from_der(bytes) { Ok((rem, t)) => Ok((rem, Some(t))), - Err(nom::Err::Error(Error::UnexpectedTag { .. })) => Ok((bytes, None)), Err(e) => Err(e), } } diff --git a/tests/issue-27-option-struct-derive.rs b/tests/issue-27-option-struct-derive.rs new file mode 100644 index 0000000..5c6e945 --- /dev/null +++ b/tests/issue-27-option-struct-derive.rs @@ -0,0 +1,71 @@ +use asn1_rs::*; + +#[derive(DerSequence, Debug, PartialEq)] +struct TestBool { + a: u16, + b: Option, + c: u32, +} + +#[test] +fn issue_27_1() { + let x = TestBool { + a: 0x1234, + b: None, + c: 0x5678, + }; + + let expected = &[48, 8, 2, 2, 18, 52, 2, 2, 86, 120]; + + let (_, val) = TestBool::from_der(expected).unwrap(); + assert_eq!(val, x); +} + +#[test] +fn issue_27_2() { + let x = TestBool { + a: 0x1234, + b: Some(true), + c: 0x5678, + }; + + let expected = &[48, 11, 2, 2, 18, 52, 1, 1, 255, 2, 2, 86, 120]; + + let (_, val) = TestBool::from_der(expected).unwrap(); + assert_eq!(val, x); +} + +#[derive(DerSequence, Debug, PartialEq)] +struct TestInt { + a: u16, + b: Option, + c: bool, +} + +#[test] +fn issue_27_3() { + let x = TestInt { + a: 0x1234, + b: None, + c: true, + }; + + let expected = &[48, 7, 2, 2, 18, 52, 1, 1, 255]; + + let (_, val) = TestInt::from_der(expected).unwrap(); + assert_eq!(val, x); +} + +#[test] +fn issue_27_4() { + let x = TestInt { + a: 0x1234, + b: Some(0x5678), + c: true, + }; + + let expected = &[48, 11, 2, 2, 18, 52, 2, 2, 86, 120, 1, 1, 255]; + + let (_, val) = TestInt::from_der(expected).unwrap(); + assert_eq!(val, x); +}