pub fn parse_ber_container<'a, O, F, E>(
    f: F
) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], O, E>where
    F: FnMut(&'a [u8], Header<'a>) -> IResult<&'a [u8], O, E>,
    E: ParseError<&'a [u8]> + From<BerError>,
Expand description

Parse a BER object and apply provided function to content

Given a parser for content, read BER object header and apply parser to return the remaining bytes and the parser result.

The remaining bytes point after the content: any bytes that are part of the content but not parsed are ignored. The nom combinator all_consuming can be used to ensure all the content is parsed.

This function is mostly intended for constructed objects, but can be used for any valid BER object.

Examples

Parsing a defined sequence with different types:

pub struct MyObject<'a> {
    a: u32,
    b: &'a [u8],
}

/// Read a DER-encoded object:
/// SEQUENCE {
///     a INTEGER (0..4294967295),
///     b OCTETSTRING
/// }
fn parse_myobject(i: &[u8]) -> BerResult<MyObject> {
    parse_ber_container(
        |i: &[u8], hdr: Header| {
            if hdr.tag() != Tag::Sequence {
                return Err(nom::Err::Error(BerError::BerTypeError.into()));
            }
            let (i, a) = parse_ber_u32(i)?;
            let (i, obj) = parse_ber_octetstring(i)?;
            let b = obj.as_slice().unwrap();
            Ok((i, MyObject{ a, b }))
        }
    )(i)
}

let (rem, v) = parse_myobject(&bytes).expect("parsing failed");