#![allow(unused_imports)]
#![allow(dead_code)]
use std::fmt;
use std::convert::Infallible;
use bytes::Bytes;
use smallvec::SmallVec;
use crate::captured::Captured;
use crate::int::{Integer, Unsigned};
use crate::length::Length;
use crate::mode::Mode;
use crate::tag::Tag;
use super::error::{ContentError, DecodeError};
use super::source::{
CaptureSource, IntoSource, LimitedSource, Pos, SliceSource, Source,
};
pub enum Content<'a, S: 'a> {
Primitive(Primitive<'a, S>),
Constructed(Constructed<'a, S>)
}
impl<'a, S: Source + 'a> Content<'a, S> {
fn exhausted(self) -> Result<(), DecodeError<S::Error>> {
match self {
Content::Primitive(inner) => inner.exhausted(),
Content::Constructed(mut inner) => inner.exhausted()
}
}
pub fn mode(&self) -> Mode {
match *self {
Content::Primitive(ref inner) => inner.mode(),
Content::Constructed(ref inner) => inner.mode()
}
}
pub fn is_primitive(&self) -> bool {
match *self {
Content::Primitive(_) => true,
Content::Constructed(_) => false,
}
}
pub fn is_constructed(&self) -> bool {
match *self {
Content::Primitive(_) => false,
Content::Constructed(_) => true,
}
}
pub fn as_primitive(
&mut self
) -> Result<&mut Primitive<'a, S>, DecodeError<S::Error>> {
match *self {
Content::Primitive(ref mut inner) => Ok(inner),
Content::Constructed(ref inner) => {
Err(inner.content_err("expected primitive value"))
}
}
}
pub fn as_constructed(
&mut self
) -> Result<&mut Constructed<'a, S>, DecodeError<S::Error>> {
match *self {
Content::Primitive(ref inner) => {
Err(inner.content_err("expected constructed value"))
}
Content::Constructed(ref mut inner) => Ok(inner),
}
}
pub fn content_err(
&self, err: impl Into<ContentError>,
) -> DecodeError<S::Error> {
match *self {
Content::Primitive(ref inner) => inner.content_err(err),
Content::Constructed(ref inner) => inner.content_err(err),
}
}
}
#[allow(clippy::wrong_self_convention)]
impl<'a, S: Source + 'a> Content<'a, S> {
pub fn to_u8(&mut self) -> Result<u8, DecodeError<S::Error>> {
if let Content::Primitive(ref mut prim) = *self {
prim.to_u8()
}
else {
Err(self.content_err("expected integer (0..255)"))
}
}
pub fn skip_u8_if(
&mut self, expected: u8,
) -> Result<(), DecodeError<S::Error>> {
let res = self.to_u8()?;
if res == expected {
Ok(())
}
else {
Err(self.content_err(ExpectedIntValue(expected)))
}
}
pub fn to_u16(&mut self) -> Result<u16, DecodeError<S::Error>> {
if let Content::Primitive(ref mut prim) = *self {
prim.to_u16()
}
else {
Err(self.content_err("expected integer (0..65535)"))
}
}
pub fn to_u32(&mut self) -> Result<u32, DecodeError<S::Error>> {
if let Content::Primitive(ref mut prim) = *self {
prim.to_u32()
}
else {
Err(self.content_err("expected integer (0..4294967295)"))
}
}
pub fn to_u64(&mut self) -> Result<u64, DecodeError<S::Error>> {
if let Content::Primitive(ref mut prim) = *self {
prim.to_u64()
}
else {
Err(self.content_err("expected integer (0..2**64-1)"))
}
}
pub fn to_null(&mut self) -> Result<(), DecodeError<S::Error>> {
if let Content::Primitive(ref mut prim) = *self {
prim.to_null()
}
else {
Err(self.content_err("expected NULL"))
}
}
}
pub struct Primitive<'a, S: 'a> {
source: &'a mut LimitedSource<S>,
mode: Mode,
start: Pos,
}
impl<'a, S: 'a> Primitive<'a, S> {
fn new(source: &'a mut LimitedSource<S>, mode: Mode) -> Self
where S: Source {
Primitive { start: source.pos(), source, mode }
}
pub fn mode(&self) -> Mode {
self.mode
}
pub fn set_mode(&mut self, mode: Mode) {
self.mode = mode
}
}
impl<'a, S: Source + 'a> Primitive<'a, S> {
pub fn content_err(
&self, err: impl Into<ContentError>,
) -> DecodeError<S::Error> {
DecodeError::content(err, self.start)
}
}
#[allow(clippy::wrong_self_convention)]
impl<'a, S: Source + 'a> Primitive<'a, S> {
pub fn to_bool(&mut self) -> Result<bool, DecodeError<S::Error>> {
let res = self.take_u8()?;
if self.mode != Mode::Ber {
match res {
0 => Ok(false),
0xFF => Ok(true),
_ => {
Err(self.content_err("invalid boolean"))
}
}
}
else {
Ok(res != 0)
}
}
pub fn to_i8(&mut self) -> Result<i8, DecodeError<S::Error>> {
Integer::i8_from_primitive(self)
}
pub fn to_i16(&mut self) -> Result<i16, DecodeError<S::Error>> {
Integer::i16_from_primitive(self)
}
pub fn to_i32(&mut self) -> Result<i32, DecodeError<S::Error>> {
Integer::i32_from_primitive(self)
}
pub fn to_i64(&mut self) -> Result<i64, DecodeError<S::Error>> {
Integer::i64_from_primitive(self)
}
pub fn to_i128(&mut self) -> Result<i128, DecodeError<S::Error>> {
Integer::i128_from_primitive(self)
}
pub fn to_u8(&mut self) -> Result<u8, DecodeError<S::Error>> {
Unsigned::u8_from_primitive(self)
}
pub fn to_u16(&mut self) -> Result<u16, DecodeError<S::Error>> {
Unsigned::u16_from_primitive(self)
}
pub fn to_u32(&mut self) -> Result<u32, DecodeError<S::Error>> {
Unsigned::u32_from_primitive(self)
}
pub fn to_u64(&mut self) -> Result<u64, DecodeError<S::Error>> {
Unsigned::u64_from_primitive(self)
}
pub fn to_u128(&mut self) -> Result<u64, DecodeError<S::Error>> {
Unsigned::u64_from_primitive(self)
}
pub fn to_null(&mut self) -> Result<(), DecodeError<S::Error>> {
if self.remaining() > 0 {
Err(self.content_err("invalid NULL value"))
}
else {
Ok(())
}
}
}
impl<'a, S: Source + 'a> Primitive<'a, S> {
pub fn remaining(&self) -> usize {
self.source.limit().unwrap()
}
pub fn skip_all(&mut self) -> Result<(), DecodeError<S::Error>> {
self.source.skip_all()
}
pub fn take_all(&mut self) -> Result<Bytes, DecodeError<S::Error>> {
self.source.take_all()
}
pub fn slice_all(&mut self) -> Result<&[u8], DecodeError<S::Error>> {
let remaining = self.remaining();
if self.source.request(remaining)? < remaining {
Err(self.source.content_err("unexpected end of data"))
}
else {
Ok(&self.source.slice()[..remaining])
}
}
pub fn with_slice_all<F, T, E>(
&mut self, op: F,
) -> Result<T, DecodeError<S::Error>>
where
F: FnOnce(&[u8]) -> Result<T, E>,
E: Into<ContentError>,
{
let remaining = self.remaining();
if self.source.request(remaining)? < remaining {
return Err(self.source.content_err("unexpected end of data"));
}
let res = op(&self.source.slice()[..remaining]).map_err(|err| {
self.content_err(err)
})?;
self.source.advance(remaining);
Ok(res)
}
fn exhausted(self) -> Result<(), DecodeError<S::Error>> {
self.source.exhausted()
}
}
impl Primitive<'static, ()> {
pub fn decode_slice<F, T>(
data: &[u8],
mode: Mode,
op: F
) -> Result<T, DecodeError<Infallible>>
where
F: FnOnce(
&mut Primitive<SliceSource>
) -> Result<T, DecodeError<Infallible>>
{
let mut lim = LimitedSource::new(data.into_source());
lim.set_limit(Some(data.len()));
let mut prim = Primitive::new(&mut lim, mode);
let res = op(&mut prim)?;
prim.exhausted()?;
Ok(res)
}
}
impl<'a, S: Source + 'a> Source for Primitive<'a, S> {
type Error = S::Error;
fn pos(&self) -> Pos {
self.source.pos()
}
fn request(&mut self, len: usize) -> Result<usize, Self::Error> {
self.source.request(len)
}
fn slice(&self) -> &[u8] {
self.source.slice()
}
fn bytes(&self, start: usize, end: usize) -> Bytes {
self.source.bytes(start, end)
}
fn advance(&mut self, len: usize) {
self.source.advance(len)
}
}
#[derive(Debug)]
pub struct Constructed<'a, S: 'a> {
source: &'a mut LimitedSource<S>,
state: State,
mode: Mode,
start: Pos,
}
impl<'a, S: Source + 'a> Constructed<'a, S> {
fn new(
source: &'a mut LimitedSource<S>,
state: State,
mode: Mode
) -> Self {
Constructed { start: source.pos(), source, state, mode }
}
pub fn decode<I, F, T>(
source: I, mode: Mode, op: F,
) -> Result<T, DecodeError<S::Error>>
where
I: IntoSource<Source = S>,
F: FnOnce(&mut Constructed<S>) -> Result<T, DecodeError<S::Error>>
{
let mut source = LimitedSource::new(source.into_source());
let mut cons = Constructed::new(&mut source, State::Unbounded, mode);
let res = op(&mut cons)?;
cons.exhausted()?;
Ok(res)
}
pub fn mode(&self) -> Mode {
self.mode
}
pub fn set_mode(&mut self, mode: Mode) {
self.mode = mode
}
}
impl<'a, S: Source + 'a> Constructed<'a, S> {
pub fn content_err(
&self, err: impl Into<ContentError>,
) -> DecodeError<S::Error> {
DecodeError::content(err, self.start)
}
}
impl<'a, S: Source + 'a> Constructed<'a, S> {
fn exhausted(&mut self) -> Result<(), DecodeError<S::Error>> {
match self.state {
State::Done => Ok(()),
State::Definite => {
self.source.exhausted()
}
State::Indefinite => {
let (tag, constructed) = Tag::take_from(self.source)?;
if tag != Tag::END_OF_VALUE || constructed
|| !Length::take_from(self.source, self.mode)?.is_zero()
{
Err(self.content_err("unexpected trailing values"))
}
else {
Ok(())
}
}
State::Unbounded => Ok(())
}
}
fn is_exhausted(&self) -> bool {
match self.state {
State::Definite => {
self.source.limit().unwrap() == 0
}
State::Indefinite => false,
State::Done => true,
State::Unbounded => false,
}
}
fn process_next_value<F, T>(
&mut self,
expected: Option<Tag>,
op: F
) -> Result<Option<T>, DecodeError<S::Error>>
where
F: FnOnce(Tag, &mut Content<S>) -> Result<T, DecodeError<S::Error>>
{
if self.is_exhausted() {
return Ok(None)
}
let (tag, constructed) = if let Some(expected) = expected {
(
expected,
match expected.take_from_if(self.source)? {
Some(compressed) => compressed,
None => return Ok(None)
}
)
}
else {
Tag::take_from(self.source)?
};
let length = Length::take_from(self.source, self.mode)?;
if tag == Tag::END_OF_VALUE {
if let State::Indefinite = self.state {
if constructed {
return Err(self.source.content_err(
"constructed end of value"
))
}
if !length.is_zero() {
return Err(self.source.content_err(
"non-empty end of value"
))
}
self.state = State::Done;
return Ok(None)
}
else {
return Err(self.source.content_err(
"unexpected end of value"
))
}
}
match length {
Length::Definite(len) => {
if let Some(limit) = self.source.limit() {
if len > limit {
return Err(self.source.content_err(
"nested value with excessive length"
))
}
}
let old_limit = self.source.limit_further(Some(len));
let res = {
let mut content = if constructed {
if self.mode == Mode::Cer {
return Err(self.source.content_err(
"definite length constructed in CER mode"
))
}
Content::Constructed(
Constructed::new(
self.source, State::Definite, self.mode
)
)
}
else {
Content::Primitive(
Primitive::new(self.source, self.mode)
)
};
let res = op(tag, &mut content)?;
content.exhausted()?;
res
};
self.source.set_limit(old_limit.map(|x| x - len));
Ok(Some(res))
}
Length::Indefinite => {
if !constructed || self.mode == Mode::Der {
return Err(self.source.content_err(
"indefinite length constructed in DER mode"
))
}
let mut content = Content::Constructed(
Constructed::new(
self.source, State::Indefinite, self.mode
)
);
let res = op(tag, &mut content)?;
content.exhausted()?;
Ok(Some(res))
}
}
}
fn mandatory<F, T>(
&mut self, op: F,
) -> Result<T, DecodeError<S::Error>>
where
F: FnOnce(
&mut Constructed<S>
) -> Result<Option<T>, DecodeError<S::Error>>,
{
match op(self)? {
Some(res) => Ok(res),
None => Err(self.source.content_err("missing further values")),
}
}
}
impl<'a, S: Source + 'a> Constructed<'a, S> {
pub fn take_value<F, T>(
&mut self, op: F,
) -> Result<T, DecodeError<S::Error>>
where
F: FnOnce(Tag, &mut Content<S>) -> Result<T, DecodeError<S::Error>>,
{
match self.process_next_value(None, op)? {
Some(res) => Ok(res),
None => Err(self.content_err("missing further values")),
}
}
pub fn take_opt_value<F, T>(
&mut self, op: F,
) -> Result<Option<T>, DecodeError<S::Error>>
where
F: FnOnce(Tag, &mut Content<S>) -> Result<T, DecodeError<S::Error>>,
{
self.process_next_value(None, op)
}
pub fn take_value_if<F, T>(
&mut self,
expected: Tag,
op: F
) -> Result<T, DecodeError<S::Error>>
where F: FnOnce(&mut Content<S>) -> Result<T, DecodeError<S::Error>> {
let res = self.process_next_value(Some(expected), |_, content| {
op(content)
})?;
match res {
Some(res) => Ok(res),
None => Err(self.content_err(ExpectedTag(expected))),
}
}
pub fn take_opt_value_if<F, T>(
&mut self,
expected: Tag,
op: F
) -> Result<Option<T>, DecodeError<S::Error>>
where F: FnOnce(&mut Content<S>) -> Result<T, DecodeError<S::Error>> {
self.process_next_value(Some(expected), |_, content| op(content))
}
pub fn take_constructed<F, T>(
&mut self, op: F
) -> Result<T, DecodeError<S::Error>>
where
F: FnOnce(
Tag, &mut Constructed<S>
) -> Result<T, DecodeError<S::Error>>,
{
self.mandatory(|cons| cons.take_opt_constructed(op))
}
pub fn take_opt_constructed<F, T>(
&mut self,
op: F
) -> Result<Option<T>, DecodeError<S::Error>>
where
F: FnOnce(
Tag, &mut Constructed<S>,
) -> Result<T, DecodeError<S::Error>>
{
self.process_next_value(None, |tag, content| {
op(tag, content.as_constructed()?)
})
}
pub fn take_constructed_if<F, T>(
&mut self,
expected: Tag,
op: F,
) -> Result<T, DecodeError<S::Error>>
where
F: FnOnce(&mut Constructed<S>) -> Result<T, DecodeError<S::Error>>,
{
self.mandatory(|cons| cons.take_opt_constructed_if(expected, op))
}
pub fn take_opt_constructed_if<F, T>(
&mut self,
expected: Tag,
op: F,
) -> Result<Option<T>, DecodeError<S::Error>>
where
F: FnOnce(&mut Constructed<S>) -> Result<T, DecodeError<S::Error>>,
{
self.process_next_value(Some(expected), |_, content| {
op(content.as_constructed()?)
})
}
pub fn take_primitive<F, T>(
&mut self, op: F,
) -> Result<T, DecodeError<S::Error>>
where
F: FnOnce(Tag, &mut Primitive<S>) -> Result<T, DecodeError<S::Error>>,
{
self.mandatory(|cons| cons.take_opt_primitive(op))
}
pub fn take_opt_primitive<F, T>(
&mut self, op: F,
) -> Result<Option<T>, DecodeError<S::Error>>
where
F: FnOnce(Tag, &mut Primitive<S>) -> Result<T, DecodeError<S::Error>>,
{
self.process_next_value(None, |tag, content| {
op(tag, content.as_primitive()?)
})
}
pub fn take_primitive_if<F, T>(
&mut self, expected: Tag, op: F,
) -> Result<T, DecodeError<S::Error>>
where F: FnOnce(&mut Primitive<S>) -> Result<T, DecodeError<S::Error>> {
self.mandatory(|cons| cons.take_opt_primitive_if(expected, op))
}
pub fn take_opt_primitive_if<F, T>(
&mut self, expected: Tag, op: F,
) -> Result<Option<T>, DecodeError<S::Error>>
where F: FnOnce(&mut Primitive<S>) -> Result<T, DecodeError<S::Error>> {
self.process_next_value(Some(expected), |_, content| {
op(content.as_primitive()?)
})
}
pub fn capture<F>(
&mut self, op: F,
) -> Result<Captured, DecodeError<S::Error>>
where
F: FnOnce(
&mut Constructed<CaptureSource<LimitedSource<S>>>
) -> Result<(), DecodeError<S::Error>>
{
let limit = self.source.limit();
let start = self.source.pos();
let mut source = LimitedSource::new(CaptureSource::new(self.source));
source.set_limit(limit);
{
let mut constructed = Constructed::new(
&mut source, self.state, self.mode
);
op(&mut constructed)?;
self.state = constructed.state;
}
Ok(Captured::new(
source.unwrap().into_bytes(), self.mode, start,
))
}
pub fn capture_one(&mut self) -> Result<Captured, DecodeError<S::Error>> {
self.capture(|cons| cons.mandatory(|cons| cons.skip_one()))
}
pub fn capture_all(
&mut self
) -> Result<Captured, DecodeError<S::Error>> {
self.capture(|cons| cons.skip_all())
}
pub fn skip_opt<F>(
&mut self, mut op: F,
) -> Result<Option<()>, DecodeError<S::Error>>
where F: FnMut(Tag, bool, usize) -> Result<(), ContentError> {
if self.is_exhausted() {
return Ok(None)
}
let mut stack = SmallVec::<[Option<Option<usize>>; 4]>::new();
loop {
let (tag, constructed) = Tag::take_from(self.source)?;
let length = Length::take_from(self.source, self.mode)?;
if !constructed {
if tag == Tag::END_OF_VALUE {
if length != Length::Definite(0) {
return Err(self.content_err("non-empty end of value"))
}
match stack.pop() {
Some(None) => { }
None => {
if self.state == State::Indefinite {
self.state = State::Done;
return Ok(None)
}
else {
return Err(self.content_err(
"invalid nested values"
))
}
}
_ => {
return Err(self.content_err(
"invalid nested values"
))
}
}
}
else {
if let Length::Definite(len) = length {
if let Err(err) = op(tag, constructed, stack.len()) {
return Err(self.content_err(err));
}
if self.source.request(len)? < len {
return Err(self.content_err(
"short primitive value"
))
}
self.source.advance(len);
}
else {
return Err(self.content_err(
"primitive value with indefinite length"
))
}
}
}
else if let Length::Definite(len) = length {
if let Err(err) = op(tag, constructed, stack.len()) {
return Err(self.content_err(err));
}
stack.push(Some(match self.source.limit() {
Some(limit) => {
match limit.checked_sub(len) {
Some(len) => Some(len),
None => {
return Err(self.content_err(
"invalid nested values"
));
}
}
}
None => None,
}));
self.source.set_limit(Some(len));
}
else {
if let Err(err) = op(tag, constructed, stack.len()) {
return Err(self.content_err(err));
}
stack.push(None);
continue;
}
loop {
if stack.is_empty() {
return Ok(Some(()))
}
else if self.source.limit() == Some(0) {
match stack.pop() {
Some(Some(limit)) => {
self.source.set_limit(limit)
}
Some(None) => {
return Err(self.content_err("
missing further values"
))
}
None => unreachable!(),
}
}
else {
break;
}
}
}
}
pub fn skip<F>(&mut self, op: F) -> Result<(), DecodeError<S::Error>>
where F: FnMut(Tag, bool, usize) -> Result<(), ContentError> {
self.mandatory(|cons| cons.skip_opt(op))
}
pub fn skip_all(&mut self) -> Result<(), DecodeError<S::Error>> {
while let Some(()) = self.skip_one()? { }
Ok(())
}
pub fn skip_one(&mut self) -> Result<Option<()>, DecodeError<S::Error>> {
if self.is_exhausted() {
Ok(None)
}
else {
self.skip(|_, _, _| Ok(()))?;
Ok(Some(()))
}
}
}
impl<'a, S: Source + 'a> Constructed<'a, S> {
pub fn take_bool(&mut self) -> Result<bool, DecodeError<S::Error>> {
self.take_primitive_if(Tag::BOOLEAN, |prim| prim.to_bool())
}
pub fn take_opt_bool(
&mut self,
) -> Result<Option<bool>, DecodeError<S::Error>> {
self.take_opt_primitive_if(Tag::BOOLEAN, |prim| prim.to_bool())
}
pub fn take_null(&mut self) -> Result<(), DecodeError<S::Error>> {
self.take_primitive_if(Tag::NULL, |_| Ok(())).map(|_| ())
}
pub fn take_opt_null(&mut self) -> Result<(), DecodeError<S::Error>> {
self.take_opt_primitive_if(Tag::NULL, |_| Ok(())).map(|_| ())
}
pub fn take_u8(&mut self) -> Result<u8, DecodeError<S::Error>> {
self.take_primitive_if(Tag::INTEGER, |prim| prim.to_u8())
}
pub fn take_opt_u8(
&mut self,
) -> Result<Option<u8>, DecodeError<S::Error>> {
self.take_opt_primitive_if(Tag::INTEGER, |prim| prim.to_u8())
}
pub fn skip_u8_if(
&mut self, expected: u8,
) -> Result<(), DecodeError<S::Error>> {
self.take_primitive_if(Tag::INTEGER, |prim| {
let got = prim.take_u8()?;
if got != expected {
Err(prim.content_err(ExpectedIntValue(expected)))
}
else {
Ok(())
}
})
}
pub fn skip_opt_u8_if(
&mut self, expected: u8,
) -> Result<(), DecodeError<S::Error>> {
self.take_opt_primitive_if(Tag::INTEGER, |prim| {
let got = prim.take_u8()?;
if got != expected {
Err(prim.content_err(ExpectedIntValue(expected)))
}
else {
Ok(())
}
}).map(|_| ())
}
pub fn take_u16(&mut self) -> Result<u16, DecodeError<S::Error>> {
self.take_primitive_if(Tag::INTEGER, |prim| prim.to_u16())
}
pub fn take_opt_u16(
&mut self,
) -> Result<Option<u16>, DecodeError<S::Error>> {
self.take_opt_primitive_if(Tag::INTEGER, |prim| prim.to_u16())
}
pub fn take_u32(&mut self) -> Result<u32, DecodeError<S::Error>> {
self.take_primitive_if(Tag::INTEGER, |prim| prim.to_u32())
}
pub fn take_opt_u32(
&mut self,
) -> Result<Option<u32>, DecodeError<S::Error>> {
self.take_opt_primitive_if(Tag::INTEGER, |prim| prim.to_u32())
}
pub fn take_u64(&mut self) -> Result<u64, DecodeError<S::Error>> {
self.take_primitive_if(Tag::INTEGER, |prim| prim.to_u64())
}
pub fn take_opt_u64(
&mut self,
) -> Result<Option<u64>, DecodeError<S::Error>> {
self.take_opt_primitive_if(Tag::INTEGER, |prim| prim.to_u64())
}
pub fn take_sequence<F, T>(
&mut self, op: F,
) -> Result<T, DecodeError<S::Error>>
where F: FnOnce(&mut Constructed<S>) -> Result<T, DecodeError<S::Error>> {
self.take_constructed_if(Tag::SEQUENCE, op)
}
pub fn take_opt_sequence<F, T>(
&mut self, op: F,
) -> Result<Option<T>, DecodeError<S::Error>>
where F: FnOnce(&mut Constructed<S>) -> Result<T, DecodeError<S::Error>> {
self.take_opt_constructed_if(Tag::SEQUENCE, op)
}
pub fn take_set<F, T>(
&mut self, op: F,
) -> Result<T, DecodeError<S::Error>>
where F: FnOnce(&mut Constructed<S>) -> Result<T, DecodeError<S::Error>> {
self.take_constructed_if(Tag::SET, op)
}
pub fn take_opt_set<F, T>(
&mut self, op: F
) -> Result<Option<T>, DecodeError<S::Error>>
where F: FnOnce(&mut Constructed<S>) -> Result<T, DecodeError<S::Error>> {
self.take_opt_constructed_if(Tag::SET, op)
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum State {
Definite,
Indefinite,
Done,
Unbounded,
}
#[derive(Clone, Copy, Debug)]
struct ExpectedTag(Tag);
impl fmt::Display for ExpectedTag {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "expected tag {}", self.0)
}
}
impl From<ExpectedTag> for ContentError {
fn from(err: ExpectedTag) -> Self {
ContentError::from_boxed(Box::new(err))
}
}
#[derive(Clone, Copy, Debug)]
struct ExpectedIntValue<T>(T);
impl<T: fmt::Display> fmt::Display for ExpectedIntValue<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "expected integer value {}", self.0)
}
}
impl<T> From<ExpectedIntValue<T>> for ContentError
where T: fmt::Display + Send + Sync + 'static {
fn from(err: ExpectedIntValue<T>) -> Self {
ContentError::from_boxed(Box::new(err))
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn constructed_skip() {
Constructed::decode(
b"\x02\x01\x00\x02\x01\x00".into_source(), Mode::Ber, |cons| {
cons.skip(|_, _, _| Ok(())).unwrap();
cons.skip(|_, _, _| Ok(())).unwrap();
Ok(())
}
).unwrap();
Constructed::decode(
b"\x30\x06\x02\x01\x00\x02\x01\x00\x02\x01\x00".into_source(),
Mode::Ber,
|cons| {
cons.skip(|_, _, _| Ok(())).unwrap();
cons.skip(|_, _, _| Ok(())).unwrap();
Ok(())
}
).unwrap();
Constructed::decode(
b"\x30\x08\
\x30\x06\
\x02\x01\x00\x02\x01\x00\
\x02\x01\x00".into_source(),
Mode::Ber,
|cons| {
cons.skip(|_, _, _| Ok(())).unwrap();
cons.skip(|_, _, _| Ok(())).unwrap();
Ok(())
}
).unwrap();
Constructed::decode(
b"\x30\x0A\
\x30\x80\
\x02\x01\x00\x02\x01\x00\
\0\0".into_source(),
Mode::Ber,
|cons| {
cons.skip(|_, _, _| Ok(())).unwrap();
Ok(())
}
).unwrap();
}
}