1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
use super::{Error, Explicit, Implicit, TaggedParser};
use crate::{Class, FromBer, FromDer, ParseResult, Tag};
use core::marker::PhantomData;
/// A builder for parsing tagged values (`IMPLICIT` or `EXPLICIT`)
///
/// # Examples
///
/// ```
/// use asn1_rs::{Class, Tag, TaggedParserBuilder};
///
/// let parser = TaggedParserBuilder::explicit()
/// .with_class(Class::ContextSpecific)
/// .with_tag(Tag(0))
/// .der_parser::<u32>();
///
/// let input = &[0xa0, 0x03, 0x02, 0x01, 0x02];
/// let (rem, tagged) = parser(input).expect("parsing failed");
///
/// assert!(rem.is_empty());
/// assert_eq!(tagged.tag(), Tag(0));
/// assert_eq!(tagged.as_ref(), &2);
/// ```
#[derive(Clone, Copy, Debug)]
pub struct TaggedParserBuilder<TagKind, E = Error> {
class: Class,
tag: Tag,
tag_kind: PhantomData<TagKind>,
_e: PhantomData<E>,
}
impl<TagKind, E> TaggedParserBuilder<TagKind, E> {
/// Create a default `TaggedParserBuilder` builder
///
/// `TagKind` must be specified as either [`Explicit`] or [`Implicit`]
///
/// ```
/// use asn1_rs::{Explicit, TaggedParserBuilder};
///
/// let builder = TaggedParserBuilder::<Explicit>::new();
/// ```
pub const fn new() -> Self {
TaggedParserBuilder {
class: Class::Universal,
tag: Tag(0),
tag_kind: PhantomData,
_e: PhantomData,
}
}
/// Set the expected `Class` for the builder
pub const fn with_class(self, class: Class) -> Self {
Self { class, ..self }
}
/// Set the expected `Tag` for the builder
pub const fn with_tag(self, tag: Tag) -> Self {
Self { tag, ..self }
}
}
impl<E> TaggedParserBuilder<Explicit, E> {
/// Create a `TagParser` builder for `EXPLICIT` tagged values
pub const fn explicit() -> Self {
TaggedParserBuilder::new()
}
}
impl<E> TaggedParserBuilder<Implicit, E> {
/// Create a `TagParser` builder for `IMPLICIT` tagged values
pub const fn implicit() -> Self {
TaggedParserBuilder::new()
}
}
impl<TagKind, E> TaggedParserBuilder<TagKind, E> {
/// Create the BER parser from the builder parameters
///
/// This method will consume the builder and return a parser (to be used as a function).
pub fn ber_parser<'a, T>(
self,
) -> impl Fn(&'a [u8]) -> ParseResult<'a, TaggedParser<'a, TagKind, T, E>, E>
where
TaggedParser<'a, TagKind, T, E>: FromBer<'a, E>,
E: From<Error>,
{
move |bytes: &[u8]| TaggedParser::<TagKind, T, E>::parse_ber(self.class, self.tag, bytes)
}
}
impl<TagKind, E> TaggedParserBuilder<TagKind, E> {
/// Create the DER parser from the builder parameters
///
/// This method will consume the builder and return a parser (to be used as a function).
pub fn der_parser<'a, T>(
self,
) -> impl Fn(&'a [u8]) -> ParseResult<'a, TaggedParser<'a, TagKind, T, E>, E>
where
TaggedParser<'a, TagKind, T, E>: FromDer<'a, E>,
E: From<Error>,
{
move |bytes: &[u8]| TaggedParser::<TagKind, T, E>::parse_der(self.class, self.tag, bytes)
}
}