extern crate alloc;
use crate::alloc::string::ToString;
use core::{borrow::Borrow, f64};
use xml_no_std::{
ParserConfig, attribute::Attribute, common::XmlVersion, name::OwnedName, namespace::Namespace,
reader::XmlEvent,
};
use crate::{Decode, error::*, types::*, xer::BOOLEAN_TRUE_TAG};
use self::fields::Field;
use super::{
BOOLEAN_FALSE_TAG, MINUS_INFINITY_TAG, MINUS_INFINITY_VALUE, NAN_TAG, NAN_VALUE,
PLUS_INFINITY_TAG, PLUS_INFINITY_VALUE,
};
const OPTIONAL_ITEM_NOT_PRESENT: &str = "§_NOT_PRESENT_§";
macro_rules! error {
($kind:ident, $($arg:tt)*) => {
DecodeError::from(XerDecodeErrorKind::$kind {
details: alloc::format!($($arg)*)
})
};
($kind:ident) => {
DecodeError::from(XerDecodeErrorKind::$kind { })
};
}
macro_rules! tag {
($event:ident, $this:ident, $tag:expr) => {
match $this.next_element() {
Some(XmlEvent::$event { name, .. }) => {
if name.local_name.as_str() == $tag {
Ok(())
} else {
Err(DecodeError::from(XerDecodeErrorKind::XmlTypeMismatch {
needed: $tag,
found: alloc::format!("{name:?}"),
}))
}
}
Some(elem) => Err(DecodeError::from(XerDecodeErrorKind::XmlTypeMismatch {
needed: $tag,
found: alloc::format!("{elem:?}"),
})),
None => Err(error!(EndOfXmlInput)),
}
};
($event:ident, $this:ident) => {
match $this.next_element() {
Some(XmlEvent::$event { .. }) => Ok(()),
Some(elem) => Err(DecodeError::from(XerDecodeErrorKind::XmlTypeMismatch {
needed: "StartElement or EndElement",
found: alloc::format!("{elem:?}"),
})),
None => Err(error!(EndOfXmlInput)),
}
};
}
macro_rules! decode_string {
($this:ident, $tryfrom:path, $tag:path, $needed:literal) => {{
tag!(StartElement, $this)?;
let value = match $this.next_element() {
Some(XmlEvent::Characters(value)) => $tryfrom(value).map_err(|e| {
DecodeError::string_conversion_failed(
$tag,
alloc::format!("Error transforming string: {e:?}"),
crate::Codec::Xer,
)
}),
Some(elem) => Err(DecodeError::from(XerDecodeErrorKind::XmlTypeMismatch {
needed: $needed,
found: alloc::format!("{elem:?}"),
})),
None => Err(error!(EndOfXmlInput)),
};
tag!(EndElement, $this)?;
value
}};
}
macro_rules! decode_time {
($this:ident, $decode_fn:path) => {{
tag!(StartElement, $this)?;
let value = match $this.next_element() {
Some(XmlEvent::Characters(value)) => $decode_fn(value),
Some(elem) => Err(DecodeError::from(XerDecodeErrorKind::XmlTypeMismatch {
needed: "Time value",
found: alloc::format!("{elem:?}"),
})),
None => Err(error!(EndOfXmlInput)),
};
tag!(EndElement, $this)?;
value
}};
}
macro_rules! value_or_empty {
($this:ident, $parser:ident, $expected:expr) => {{
let value = match $this.peek() {
Some(XmlEvent::Characters(s)) => $parser(s),
Some(XmlEvent::EndElement { .. }) => return Ok(<_>::default()),
Some(elem) => {
return Err(DecodeError::from(XerDecodeErrorKind::XmlTypeMismatch {
needed: $expected,
found: alloc::format!("{elem:?}"),
}));
}
_ => return Err(DecodeError::from(XerDecodeErrorKind::EndOfXmlInput {})),
};
let _ = $this.next_element();
value
}};
}
#[derive(Debug)]
struct XerElement {
events: alloc::collections::VecDeque<XmlEvent>,
}
impl XerElement {
pub fn next(&mut self) -> Option<XmlEvent> {
self.events.pop_front()
}
pub fn peek(&self) -> Option<&XmlEvent> {
self.events.front()
}
#[cfg(test)]
pub fn len(&self) -> usize {
self.events.len()
}
}
impl<I: IntoIterator<Item = XmlEvent>> From<I> for XerElement {
fn from(value: I) -> Self {
XerElement {
events: value.into_iter().collect(),
}
}
}
pub struct Decoder {
stack: alloc::vec::Vec<XerElement>,
in_list: bool,
}
impl Decoder {
pub fn new(input: &[u8]) -> Result<Self, <Decoder as crate::de::Decoder>::Error> {
let mut reader = ParserConfig::default().create_reader(input.iter());
let next = reader.next().map_err(|e| error!(XmlParser, "{e:?}"))?;
check_prolog(&next)?;
let mut elements = alloc::collections::VecDeque::new();
'read_xml: loop {
let next = reader.next().map_err(|e| error!(XmlParser, "{e:?}"))?;
if next == XmlEvent::EndDocument {
break 'read_xml;
}
elements.push_back(next);
}
elements.try_into()
}
fn next_element(&mut self) -> Option<XmlEvent> {
if let Some(mut elem) = self.stack.pop() {
let event = elem.next();
if !elem.events.is_empty() {
self.stack.push(elem);
}
event
} else {
None
}
}
#[cfg(test)]
fn len(&self) -> usize {
self.stack.iter().fold(0, |acc, evt| acc + evt.len())
}
fn peek(&self) -> Option<&XmlEvent> {
self.stack.last().and_then(XerElement::peek)
}
fn sort_by_field_tag_order(
&mut self,
field_indices: &[(usize, Field)],
) -> Result<(), DecodeError> {
let field_names = field_indices.iter().map(|(_, f)| f.name).collect();
self.sort_by_field_name_order(field_names)
}
fn sort_by_field_name_order(
&mut self,
field_names: alloc::vec::Vec<&str>,
) -> Result<(), DecodeError> {
let stack = core::mem::take(&mut self.stack);
let mut reordered = stack.into_iter().try_fold(
alloc::collections::BTreeMap::<usize, XerElement>::new(),
|mut acc, elem| {
let index = match elem.peek() {
Some(XmlEvent::StartElement { name, .. }) => field_names
.iter()
.enumerate()
.find_map(|(i, f)| (*f == name.local_name.as_str()).then_some(i))
.ok_or_else(|| {
XerDecodeErrorKind::XmlTag {
needed: name.local_name.clone(),
found: "nothing".into(),
}
.into()
}),
e => Err(error!(XmlParser, "Expected opening tag, found {e:?}")),
};
index.map(|i| {
acc.insert(i, elem);
acc
})
},
)?;
for i in (0..field_names.len()).rev() {
self.stack.push(reordered.remove(&i).unwrap_or(XerElement {
events: alloc::vec![XmlEvent::Characters(OPTIONAL_ITEM_NOT_PRESENT.into())].into(),
}));
}
Ok(())
}
fn into_list_decoder(mut self) -> Self {
self.in_list = true;
self
}
fn from_stack_elems<E: IntoIterator<Item = XmlEvent>, I: IntoIterator<Item = E>>(
elems: I,
) -> Self {
Decoder {
stack: elems.into_iter().map(|i| XerElement::from(i)).collect(),
in_list: false,
}
}
}
impl TryFrom<alloc::collections::VecDeque<XmlEvent>> for Decoder {
type Error = DecodeError;
fn try_from(value: alloc::collections::VecDeque<XmlEvent>) -> Result<Self, Self::Error> {
let (mut stack, mut events, mut tag) =
(alloc::vec![], alloc::collections::VecDeque::new(), None);
let mut level_of_nested_items = 0;
'xml_elements: for evt in value {
match (&tag, evt) {
(_, XmlEvent::Whitespace(_)) => continue 'xml_elements,
(
None,
XmlEvent::StartElement {
name,
attributes,
namespace,
},
) => {
tag = Some(name.clone());
events.push_back(XmlEvent::StartElement {
name,
attributes,
namespace,
});
}
(None, _) => {
continue 'xml_elements;
}
(
Some(t),
XmlEvent::StartElement {
name,
attributes,
namespace,
},
) => {
if &name == t {
level_of_nested_items += 1;
}
events.push_back(XmlEvent::StartElement {
name,
attributes,
namespace,
});
}
(Some(t), XmlEvent::EndElement { name }) => {
if &name == t && level_of_nested_items != 0 {
level_of_nested_items -= 1;
events.push_back(XmlEvent::EndElement { name });
} else if &name == t {
events.push_back(XmlEvent::EndElement { name });
let collected_events: alloc::collections::VecDeque<XmlEvent> =
core::mem::take(&mut events);
stack.push(XerElement {
events: collected_events,
});
tag = None;
} else {
events.push_back(XmlEvent::EndElement { name });
}
}
(Some(_), XmlEvent::EndDocument) => return Err(error!(EndOfXmlInput)),
(Some(_), event) => events.push_back(event),
}
}
Ok(Self {
stack,
in_list: false,
})
}
}
fn check_prolog(prolog: &XmlEvent) -> Result<(), DecodeError> {
if let XmlEvent::StartDocument {
version, encoding, ..
} = prolog
{
if version != &XmlVersion::Version10 || encoding != &alloc::string::String::from("UTF-8") {
Err(error!(
SpecViolation,
r#"§8.2 The XML prolog shall either be empty; or shall consist of [...] <?xml
version="1.0"
encoding="UTF-8"?>"#
))
} else {
Ok(())
}
} else {
Err(error!(XmlParser, "Expected XML prolog, found {:?}", prolog))
}
}
impl crate::Decoder for Decoder {
type Ok = ();
type AnyDecoder<const R: usize, const E: usize> = Decoder;
type Error = DecodeError;
fn codec(&self) -> crate::Codec {
crate::Codec::Xer
}
fn decode_any(&mut self, _tag: Tag) -> Result<crate::types::Any, Self::Error> {
tag!(StartElement, self)?;
let mut events = self
.stack
.pop()
.ok_or_else(|| error!(EndOfXmlInput))?
.events;
events.pop_back();
let mut xml_writer = xml_no_std::EmitterConfig::new()
.write_document_declaration(false)
.create_writer();
for reader_event in events {
match reader_event {
XmlEvent::EndDocument => return Err(XerDecodeErrorKind::EndOfXmlInput {}.into()),
XmlEvent::StartElement {
name,
attributes,
namespace,
} => {
let event = xml_no_std::writer::XmlEvent::StartElement {
name: name.borrow(),
namespace: namespace.borrow(),
attributes: attributes
.iter()
.map(|attr| Attribute::new(attr.name.borrow(), &attr.value))
.collect(),
};
xml_writer
.write(event)
.map_err(|e| XerDecodeErrorKind::InvalidOpenType { inner_err: e })?;
}
XmlEvent::Characters(text) => {
let text = text.borrow();
let event = xml_no_std::writer::XmlEvent::Characters(text);
xml_writer
.write(event)
.map_err(|e| XerDecodeErrorKind::InvalidOpenType { inner_err: e })?;
}
XmlEvent::Comment(text) => {
let text = text.borrow();
let event = xml_no_std::writer::XmlEvent::Comment(text);
xml_writer
.write(event)
.map_err(|e| XerDecodeErrorKind::InvalidOpenType { inner_err: e })?;
}
other => {
if let Some(writer_event) = other.as_writer_event() {
xml_writer
.write(writer_event)
.map_err(|e| XerDecodeErrorKind::InvalidOpenType { inner_err: e })?;
}
}
}
}
Ok(Any::new(xml_writer.into_inner().into_bytes()))
}
fn decode_bit_string(
&mut self,
__tag: Tag,
__constraints: Constraints,
) -> Result<crate::types::BitString, Self::Error> {
tag!(StartElement, self)?;
let value = value_or_empty!(self, parse_bitstring_value, "`1` or `0`");
tag!(EndElement, self)?;
value
}
fn decode_bool(&mut self, __tag: Tag) -> Result<bool, Self::Error> {
if !self.in_list {
tag!(StartElement, self)?;
}
let value = match self.next_element() {
Some(XmlEvent::StartElement { name, .. }) => {
if name.local_name.as_str() == BOOLEAN_TRUE_TAG {
tag!(EndElement, self, BOOLEAN_TRUE_TAG).map(|_| true)
} else if name.local_name.as_str() == BOOLEAN_FALSE_TAG {
tag!(EndElement, self, BOOLEAN_FALSE_TAG).map(|_| false)
} else if self.in_list {
let boolean = match self.next_element() {
Some(XmlEvent::Characters(c)) if c == "0" => false,
Some(XmlEvent::Characters(c)) if c == "1" => true,
Some(XmlEvent::Characters(c)) if c == "false" => false,
Some(XmlEvent::Characters(c)) if c == "true" => true,
_ => {
return Err(DecodeError::from(XerDecodeErrorKind::XmlTypeMismatch {
needed: "`<true/>` or `<false/>`",
found: alloc::format!("{name:?}"),
}));
}
};
tag!(EndElement, self)?;
Ok(boolean)
} else {
Err(DecodeError::from(XerDecodeErrorKind::XmlTypeMismatch {
needed: "`<true/>` or `<false/>`",
found: alloc::format!("{name:?}"),
}))
}
}
Some(XmlEvent::Characters(c)) if c == "0" => Ok(false),
Some(XmlEvent::Characters(c)) if c == "1" => Ok(true),
Some(XmlEvent::Characters(c)) if c == "false" => Ok(false),
Some(XmlEvent::Characters(c)) if c == "true" => Ok(true),
Some(elem) => Err(DecodeError::from(XerDecodeErrorKind::XmlTypeMismatch {
needed: bool::IDENTIFIER.0.unwrap(),
found: alloc::format!("{elem:?}"),
})),
None => Err(error!(EndOfXmlInput)),
};
if !self.in_list {
tag!(EndElement, self)?;
}
value
}
fn decode_enumerated<E: Enumerated>(&mut self, __tag: Tag) -> Result<E, Self::Error> {
if !self.in_list {
tag!(StartElement, self)?;
}
let value = match self.next_element() {
Some(XmlEvent::StartElement {
name: OwnedName { local_name, .. },
..
}) => {
if let Some(e) = E::from_identifier(&local_name) {
tag!(EndElement, self).map(|_| e)
} else {
Err(DecodeError::from(XerDecodeErrorKind::XmlTypeMismatch {
needed: "enumerated value",
found: local_name,
}))
}
}
Some(XmlEvent::Characters(c)) => E::from_identifier(&c).ok_or(DecodeError::from(
XerDecodeErrorKind::XmlTypeMismatch {
needed: "enumerated value",
found: c,
},
)),
Some(elem) => Err(DecodeError::from(XerDecodeErrorKind::XmlTypeMismatch {
needed: "enumerated value",
found: alloc::format!("{elem:?}"),
})),
None => Err(error!(EndOfXmlInput)),
};
if !self.in_list {
tag!(EndElement, self)?;
}
value
}
fn decode_integer<I: crate::types::IntegerType>(
&mut self,
_t: Tag,
_c: Constraints,
) -> Result<I, Self::Error> {
tag!(StartElement, self)?;
let value = match self.next_element() {
Some(XmlEvent::Characters(value)) => {
if let Ok(int) = value.parse::<i128>() {
int.try_into()
.map_err(|_| DecodeError::integer_overflow(I::WIDTH, crate::Codec::Jer))
} else {
Err(DecodeError::from(XerDecodeErrorKind::XmlTypeMismatch {
needed: "integer value",
found: value,
}))
}
}
Some(elem) => Err(DecodeError::from(XerDecodeErrorKind::XmlTypeMismatch {
needed: "integer value",
found: alloc::format!("{elem:?}"),
})),
None => Err(error!(EndOfXmlInput)),
};
tag!(EndElement, self)?;
value
}
fn decode_null(&mut self, _tag: Tag) -> Result<(), Self::Error> {
tag!(StartElement, self)?;
tag!(EndElement, self)?;
Ok(())
}
fn decode_object_identifier(
&mut self,
_tag: Tag,
) -> Result<crate::types::ObjectIdentifier, Self::Error> {
tag!(StartElement, self)?;
let value = match self.next_element() {
Some(XmlEvent::Characters(value)) => parse_object_identifier(&value),
Some(elem) => Err(DecodeError::from(XerDecodeErrorKind::XmlTypeMismatch {
needed: "'.'-separated numeric object identifier arcs",
found: alloc::format!("{elem:?}"),
})),
None => Err(error!(EndOfXmlInput)),
};
tag!(EndElement, self)?;
value
}
fn decode_sequence<const RC: usize, const EC: usize, D, DF, F>(
&mut self,
_: Tag,
_: Option<DF>,
decode_fn: F,
) -> Result<D, Self::Error>
where
D: Constructed<RC, EC>,
F: FnOnce(&mut Self) -> Result<D, Self::Error>,
{
tag!(StartElement, self)?;
let mut field_names = D::FIELDS
.iter()
.map(|f| f.name)
.collect::<alloc::vec::Vec<&str>>();
if let Some(extended_fields) = D::EXTENDED_FIELDS {
field_names.extend(extended_fields.iter().map(|f| f.name));
}
let events = self
.stack
.pop()
.ok_or_else(|| error!(EndOfXmlInput))?
.events;
let mut sequence_decoder = Decoder::try_from(events)?;
sequence_decoder.sort_by_field_name_order(field_names)?;
(decode_fn)(&mut sequence_decoder)
}
fn decode_sequence_of<D: Decode>(
&mut self,
_tag: Tag,
_constraints: Constraints,
) -> Result<alloc::vec::Vec<D>, Self::Error> {
decode_sequence_or_set_items(self)
}
fn decode_set_of<D: crate::Decode + Eq + core::hash::Hash>(
&mut self,
_t: Tag,
_c: Constraints,
) -> Result<SetOf<D>, Self::Error> {
let items = decode_sequence_or_set_items::<D>(self)?;
Ok(SetOf::from_vec(items))
}
fn decode_octet_string<'b, T: From<alloc::vec::Vec<u8>> + From<&'b [u8]>>(
&'b mut self,
_: Tag,
_c: Constraints,
) -> Result<T, Self::Error> {
tag!(StartElement, self)?;
let value = match self.peek() {
Some(XmlEvent::Characters(s)) => parse_octetstring_value(s),
Some(XmlEvent::EndElement { .. }) => return Ok(<T as From<&'b [u8]>>::from(&[])),
Some(elem) => {
return Err(DecodeError::from(XerDecodeErrorKind::XmlTypeMismatch {
needed: "hexadecimal characters",
found: alloc::format!("{elem:?}"),
}));
}
_ => return Err(DecodeError::from(XerDecodeErrorKind::EndOfXmlInput {})),
};
let _ = self.next_element();
tag!(EndElement, self)?;
value.map(T::from)
}
fn decode_utf8_string(
&mut self,
_tag: Tag,
_constraints: Constraints,
) -> Result<crate::types::Utf8String, Self::Error> {
tag!(StartElement, self)?;
let value = match self.next_element() {
Some(XmlEvent::Characters(value)) => Ok(value),
Some(elem) => Err(DecodeError::from(XerDecodeErrorKind::XmlTypeMismatch {
needed: "UTF8 string value",
found: alloc::format!("{elem:?}"),
})),
None => Err(error!(EndOfXmlInput)),
};
tag!(EndElement, self)?;
value
}
fn decode_visible_string(
&mut self,
_tag: Tag,
_constraints: Constraints,
) -> Result<crate::types::VisibleString, Self::Error> {
decode_string!(
self,
crate::types::VisibleString::try_from,
Tag::VISIBLE_STRING,
"VisibleString value"
)
}
fn decode_general_string(
&mut self,
_tag: Tag,
_constraints: Constraints,
) -> Result<crate::types::GeneralString, Self::Error> {
decode_string!(
self,
crate::types::GeneralString::try_from,
Tag::GENERAL_STRING,
"GeneralString value"
)
}
fn decode_ia5_string(
&mut self,
_tag: Tag,
_constraints: Constraints,
) -> Result<crate::types::Ia5String, Self::Error> {
decode_string!(
self,
crate::types::Ia5String::try_from,
Tag::IA5_STRING,
"IA5String value"
)
}
fn decode_graphic_string(
&mut self,
_tag: Tag,
_constraints: Constraints,
) -> Result<crate::types::GraphicString, Self::Error> {
decode_string!(
self,
crate::types::GraphicString::try_from,
Tag::GRAPHIC_STRING,
"GraphicString value"
)
}
fn decode_printable_string(
&mut self,
_tag: Tag,
_constraints: Constraints,
) -> Result<crate::types::PrintableString, Self::Error> {
decode_string!(
self,
crate::types::PrintableString::try_from,
Tag::PRINTABLE_STRING,
"PrintableString value"
)
}
fn decode_numeric_string(
&mut self,
_tag: Tag,
_constraints: Constraints,
) -> Result<crate::types::NumericString, Self::Error> {
decode_string!(
self,
crate::types::NumericString::try_from,
Tag::NUMERIC_STRING,
"NumericString value"
)
}
fn decode_teletex_string(
&mut self,
_tag: Tag,
_constraints: Constraints,
) -> Result<crate::types::TeletexString, Self::Error> {
todo!()
}
fn decode_bmp_string(
&mut self,
_tag: Tag,
_constraints: Constraints,
) -> Result<crate::types::BmpString, Self::Error> {
decode_string!(
self,
crate::types::BmpString::try_from,
Tag::BMP_STRING,
"BMP String value"
)
}
fn decode_explicit_prefix<D: Decode>(&mut self, _tag: Tag) -> Result<D, Self::Error> {
D::decode(self)
}
fn decode_utc_time(&mut self, _tag: Tag) -> Result<crate::types::UtcTime, Self::Error> {
decode_time!(self, crate::ber::de::Decoder::parse_any_utc_time_string)
}
fn decode_generalized_time(
&mut self,
_tag: Tag,
) -> Result<crate::types::GeneralizedTime, Self::Error> {
decode_time!(
self,
crate::ber::de::Decoder::parse_any_generalized_time_string
)
}
fn decode_set<const RC: usize, const EC: usize, FIELDS, SET, D, F>(
&mut self,
_t: Tag,
decode_fn: D,
field_fn: F,
) -> Result<SET, Self::Error>
where
SET: crate::Decode + Constructed<RC, EC>,
FIELDS: crate::Decode,
D: Fn(&mut Self::AnyDecoder<RC, EC>, usize, Tag) -> Result<FIELDS, Self::Error>,
F: FnOnce(alloc::vec::Vec<FIELDS>) -> Result<SET, Self::Error>,
{
tag!(StartElement, self)?;
let events = self
.stack
.pop()
.ok_or_else(|| error!(EndOfXmlInput))?
.events;
let mut field_indices = SET::FIELDS
.iter()
.enumerate()
.collect::<alloc::vec::Vec<_>>();
let mut fields = alloc::vec![];
field_indices
.sort_by(|(_, a), (_, b)| a.tag_tree.smallest_tag().cmp(&b.tag_tree.smallest_tag()));
let mut sequence_decoder = Decoder::try_from(events)?;
sequence_decoder.sort_by_field_tag_order(&field_indices)?;
for (index, field) in field_indices {
fields.push((decode_fn)(&mut sequence_decoder, index, field.tag)?);
}
for (index, field) in SET::EXTENDED_FIELDS
.iter()
.flat_map(|fields| fields.iter())
.enumerate()
{
fields.push((decode_fn)(
&mut sequence_decoder,
index + SET::FIELDS.len(),
field.tag,
)?);
}
(field_fn)(fields)
}
fn decode_choice<D>(&mut self, _constraints: Constraints) -> Result<D, Self::Error>
where
D: crate::types::DecodeChoice,
{
if !self.in_list {
tag!(StartElement, self)?;
}
match self.peek() {
Some(XmlEvent::StartElement { name, .. }) => {
let tag = D::IDENTIFIERS
.iter()
.enumerate()
.find(|(_, id)| id.eq_ignore_ascii_case(&name.local_name))
.and_then(|(i, _)| {
variants::Variants::from_slice(
&[D::VARIANTS, D::EXTENDED_VARIANTS.unwrap_or(&[])].concat(),
)
.get(i)
.cloned()
})
.unwrap_or(Tag::EOC);
let events = self
.stack
.pop()
.ok_or_else(|| error!(EndOfXmlInput))?
.events;
let mut variant_decoder = Decoder::try_from(events)?;
D::from_tag(&mut variant_decoder, tag)
}
elem => Err(DecodeError::from(XerDecodeErrorKind::XmlTypeMismatch {
needed: "Start element of choice option",
found: alloc::format!("{elem:?}"),
})),
}
}
fn decode_optional<D: Decode>(&mut self) -> Result<Option<D>, Self::Error> {
match self.peek() {
Some(XmlEvent::Characters(c)) if c == OPTIONAL_ITEM_NOT_PRESENT => {
let _ = self.next_element();
return Ok(None);
}
_ => (),
}
D::decode(self).map(Some)
}
fn decode_optional_with_tag<D: Decode>(&mut self, _tag: Tag) -> Result<Option<D>, Self::Error> {
self.decode_optional()
}
fn decode_optional_with_constraints<D: Decode>(
&mut self,
_constraints: Constraints,
) -> Result<Option<D>, Self::Error> {
self.decode_optional()
}
fn decode_optional_with_tag_and_constraints<D: Decode>(
&mut self,
_tag: Tag,
_constraints: Constraints,
) -> Result<Option<D>, Self::Error> {
self.decode_optional()
}
fn decode_extension_addition_with_constraints<D>(
&mut self,
_constraints: Constraints,
) -> Result<Option<D>, Self::Error>
where
D: Decode,
{
self.decode_optional()
}
fn decode_extension_addition_group<
const RC: usize,
const EC: usize,
D: crate::Decode + Constructed<RC, EC>,
>(
&mut self,
) -> Result<Option<D>, Self::Error> {
self.decode_optional()
}
fn decode_real<R: crate::types::RealType>(
&mut self,
_tag: Tag,
_constraints: Constraints,
) -> Result<R, Self::Error> {
tag!(StartElement, self)?;
let value = match self.next_element() {
Some(XmlEvent::Characters(value)) => match value.as_str().parse::<f64>() {
Ok(real) => R::try_from_float(real).ok_or_else(|| {
DecodeError::integer_overflow(R::BYTE_WIDTH as u32, crate::Codec::Xer)
}),
Err(_) if value.as_str() == PLUS_INFINITY_VALUE => Ok(R::INFINITY),
Err(_) if value.as_str() == MINUS_INFINITY_VALUE => Ok(R::NEG_INFINITY),
Err(_) if value.as_str() == NAN_VALUE => Ok(R::NAN),
_ => {
return Err(DecodeError::from(XerDecodeErrorKind::XmlTypeMismatch {
needed: "integer value",
found: value,
}));
}
},
Some(XmlEvent::StartElement { name, .. }) => {
tag!(EndElement, self)?;
match name.local_name.as_str() {
PLUS_INFINITY_TAG => Ok(R::INFINITY),
MINUS_INFINITY_TAG => Ok(R::NEG_INFINITY),
NAN_TAG => Ok(R::NAN),
_ => Err(DecodeError::from(XerDecodeErrorKind::XmlTypeMismatch {
needed: "PLUS-INFINITY, MINUS-INFINITY or NOT-A-NUMBER",
found: name.local_name,
})),
}
}
Some(elem) => Err(DecodeError::from(XerDecodeErrorKind::XmlTypeMismatch {
needed: "integer value",
found: alloc::format!("{elem:?}"),
})),
None => Err(error!(EndOfXmlInput)),
};
tag!(EndElement, self)?;
value
}
fn decode_optional_with_explicit_prefix<D: Decode>(
&mut self,
_tag: Tag,
) -> Result<Option<D>, Self::Error> {
self.decode_optional()
}
fn decode_date(&mut self, _tag: Tag) -> Result<Date, Self::Error> {
decode_time!(
self,
crate::ber::de::Decoder::parse_any_generalized_time_string
)
.map(|dt| dt.date_naive())
}
fn decode_extension_addition_with_explicit_tag_and_constraints<D>(
&mut self,
_tag: Tag,
_constraints: Constraints,
) -> Result<Option<D>, Self::Error>
where
D: Decode,
{
self.decode_extension_addition()
}
fn decode_extension_addition_with_tag_and_constraints<D>(
&mut self,
_tag: Tag,
_constraints: Constraints,
) -> Result<Option<D>, Self::Error>
where
D: Decode,
{
self.decode_extension_addition()
}
}
fn parse_bitstring_value(val: &str) -> Result<BitString, DecodeError> {
if !val
.chars()
.all(|c| c == '1' || c == '0' || c.is_whitespace())
{
return Err(error!(
SpecViolation,
r#"§12.11 An "xmlbstring" shall consist of an arbitrary number (possibly zero) of zeros, ones or white-space"#
));
}
Ok(BitString::from_iter(val.chars().filter_map(|c| {
(c == '1').then_some(true).or((c == '0').then_some(false))
})))
}
fn parse_octetstring_value(val: &str) -> Result<alloc::vec::Vec<u8>, DecodeError> {
(0..val.len())
.step_by(2)
.map(|i| u8::from_str_radix(&val[i..i + 2], 16))
.collect::<Result<alloc::vec::Vec<_>, _>>()
.map_err(|e| XerDecodeErrorKind::InvalidXerOctetstring { parse_int_err: e }.into())
}
fn parse_object_identifier(val: &str) -> Result<ObjectIdentifier, DecodeError> {
let arcs = val
.split('.')
.try_fold(alloc::vec::Vec::<u32>::new(), |mut acc, curr| {
curr.parse()
.map(|i| {
acc.push(i);
acc
})
.map_err(|_| {
DecodeError::from(XerDecodeErrorKind::InvalidInput {
details: "Invalid Object Identifier value.",
})
})
})?;
ObjectIdentifier::new(arcs).ok_or_else(|| {
XerDecodeErrorKind::InvalidInput {
details: "Invalid Object Identifier value.",
}
.into()
})
}
fn decode_sequence_or_set_items<D: Decode>(
decoder: &mut Decoder,
) -> Result<alloc::vec::Vec<D>, DecodeError> {
let identifier = match decoder.next_element() {
Some(XmlEvent::StartElement { name, .. }) => Ok(name),
elem => Err(DecodeError::from(XerDecodeErrorKind::XmlTypeMismatch {
needed: "StartElement of SEQUENCE OF",
found: alloc::format!("{elem:?}"),
})),
}?;
let mut inner_decoder: Decoder = if let Some(XmlEvent::Characters(c)) = decoder.peek() {
let mut elems = alloc::vec![alloc::vec![XmlEvent::EndElement {
name: identifier.clone()
}]];
elems.extend(c.split_ascii_whitespace().map(|item| {
alloc::vec![
XmlEvent::StartElement {
name: OwnedName {
local_name: D::IDENTIFIER.0.unwrap_or("dummy").to_string(),
namespace: None,
prefix: None,
},
attributes: alloc::vec::Vec::new(),
namespace: Namespace::empty(),
},
XmlEvent::Characters(item.to_string()),
XmlEvent::EndElement {
name: OwnedName {
local_name: D::IDENTIFIER.0.unwrap_or("dummy").to_string(),
namespace: None,
prefix: None,
},
},
]
}));
let _ = decoder.stack.pop();
Decoder::from_stack_elems(elems)
} else {
decoder
.stack
.pop()
.ok_or_else(|| error!(EndOfXmlInput))?
.events
.try_into()?
}
.into_list_decoder();
let mut items = alloc::vec::Vec::new();
let mut level_of_nesting = 0;
loop {
match inner_decoder.peek() {
Some(XmlEvent::StartElement { name, .. }) if name == &identifier => {
level_of_nesting += 1;
items.push(D::decode(&mut inner_decoder)?)
}
Some(XmlEvent::EndElement { name }) if name == &identifier && level_of_nesting == 0 => {
break;
}
Some(XmlEvent::EndElement { name }) if name == &identifier => {
level_of_nesting -= 1;
inner_decoder.next_element();
}
None => break,
_ => items.push(D::decode(&mut inner_decoder)?),
}
}
items.reverse();
Ok(items)
}
#[cfg(test)]
mod tests {
use super::Decoder;
use crate::{AsnType, Decode, Decoder as _, types::*};
use bitvec::order::Msb0;
macro_rules! decode_test_1 {
($suite:ident, $method:ident, $xml:literal, $expected:expr) => {
#[test]
fn $suite() {
let mut decoder = Decoder::new($xml.as_bytes()).unwrap();
assert_eq!(
crate::Decoder::$method(&mut decoder, Tag::CHOICE).unwrap(),
$expected
)
}
};
}
macro_rules! decode_test_2 {
($suite:ident, $method:path, $xml:literal, $expected:expr) => {
#[test]
fn $suite() {
let mut decoder = Decoder::new($xml.as_bytes()).unwrap();
assert_eq!(
$method(&mut decoder, Tag::CHOICE, Constraints::NONE).unwrap(),
$expected
)
}
};
}
#[test]
fn creates_decoder() {
Decoder::new(
r#"<?xml version="1.0" encoding="UTF-8"?>
<Actual>
<errorCode>
<local>1</local>
</errorCode>
<parameter>
<BOOLEAN><false/></BOOLEAN>
</parameter>
</Actual>"#
.as_bytes(),
)
.unwrap();
}
decode_test_1!(
boolean_true,
decode_bool,
"<BOOLEAN><true/></BOOLEAN>",
true
);
decode_test_1!(
boolean_false,
decode_bool,
"<BOOLEAN><false/></BOOLEAN>",
false
);
decode_test_2!(
bit_string,
crate::Decoder::decode_bit_string,
"<BIT_STRING>1010</BIT_STRING>",
bitvec::bitvec![u8, Msb0; 1, 0, 1, 0]
);
decode_test_2!(
bit_string_ws,
crate::Decoder::decode_bit_string,
"<BIT_STRING> 1 0 1 0 </BIT_STRING>",
bitvec::bitvec![u8, Msb0; 1, 0, 1, 0]
);
decode_test_2!(
bit_string_empty,
crate::Decoder::decode_bit_string,
"<BIT_STRING/>",
bitvec::bitvec![u8, Msb0;]
);
#[derive(AsnType, Decode, Debug, PartialEq)]
#[rasn(automatic_tags)]
#[rasn(crate_root = "crate")]
struct TestTypeA {
wine: bool,
grappa: BitString,
}
#[derive(AsnType, Decode, Debug, PartialEq)]
#[rasn(automatic_tags)]
#[rasn(crate_root = "crate")]
struct TestTypeParent {
sinmin: bool,
nested: TestTypeA,
}
#[test]
fn sequence() {
let mut decoder = Decoder::new(
"<TestTypeA><grappa>1010</grappa><wine><false/></wine></TestTypeA>".as_bytes(),
)
.unwrap();
assert_eq!(
TestTypeA::decode(&mut decoder).unwrap(),
TestTypeA {
wine: false,
grappa: bitvec::bitvec![u8, Msb0; 1, 0, 1, 0]
}
)
}
#[test]
fn sequence_nested() {
let mut decoder = Decoder::new(
"<TestTypeParent><nested><grappa>1 11 1 </grappa><wine><false/></wine></nested><sinmin><true/></sinmin></TestTypeParent>".as_bytes(),
)
.unwrap();
assert_eq!(
TestTypeParent::decode(&mut decoder).unwrap(),
TestTypeParent {
nested: TestTypeA {
wine: false,
grappa: bitvec::bitvec![u8, Msb0; 1, 1, 1, 1]
},
sinmin: true
}
)
}
#[derive(AsnType, Clone, Debug, Decode, PartialEq)]
#[rasn(crate_root = "crate", automatic_tags, set)]
struct TestSetA {
wine: bool,
grappa: BitString,
}
#[test]
fn set() {
let mut decoder = Decoder::new(
"<TestTypeA><grappa>1010</grappa><wine><false/></wine></TestTypeA>".as_bytes(),
)
.unwrap();
assert_eq!(
TestSetA::decode(&mut decoder).unwrap(),
TestSetA {
wine: false,
grappa: bitvec::bitvec![u8, Msb0; 1, 0, 1, 0]
}
)
}
decode_test_2!(
positive_int,
crate::Decoder::decode_integer::<i128>,
"<INTEGER>1283749501626451264</INTEGER>",
1283749501626451264_i128
);
decode_test_2!(
negative_int,
crate::Decoder::decode_integer::<i32>,
"<INTEGER>-124142</INTEGER>",
-124142_i32
);
#[derive(AsnType, Decode, Debug, PartialEq, Clone, Copy)]
#[rasn(enumerated)]
#[rasn(automatic_tags)]
#[rasn(crate_root = "crate")]
enum TestEnum {
#[rasn(identifier = "option-A")]
OptionA,
#[rasn(identifier = "option-B")]
OptionB,
}
#[test]
fn enumerated() {
let mut decoder = Decoder::new("<TestEnum><option-B/></TestEnum>".as_bytes()).unwrap();
assert_eq!(TestEnum::decode(&mut decoder).unwrap(), TestEnum::OptionB);
assert_eq!(decoder.len(), 0);
let mut decoder = Decoder::new("<TestEnum>option-B</TestEnum>".as_bytes()).unwrap();
assert_eq!(TestEnum::decode(&mut decoder).unwrap(), TestEnum::OptionB);
assert_eq!(decoder.len(), 0);
}
#[derive(AsnType, Debug, Decode, PartialEq)]
#[rasn(automatic_tags)]
#[rasn(delegate)]
#[rasn(crate_root = "crate")]
struct SeqOfType(SequenceOf<Integer>);
#[test]
fn sequence_of() {
let mut decoder = Decoder::new(
r#"<SeqOfType>
<INTEGER>-1</INTEGER>
<INTEGER>-5</INTEGER>
<INTEGER>0</INTEGER>
<INTEGER>55</INTEGER>
<INTEGER>212424214</INTEGER>
</SeqOfType>"#
.as_bytes(),
)
.unwrap();
assert_eq!(
SeqOfType::decode(&mut decoder).unwrap(),
SeqOfType(vec![
Integer::from(-1),
Integer::from(-5),
Integer::from(0),
Integer::from(55),
Integer::from(212424214)
])
)
}
#[derive(AsnType, Debug, Decode, PartialEq)]
#[rasn(automatic_tags)]
#[rasn(delegate)]
#[rasn(crate_root = "crate")]
struct NestedSeqOf(SequenceOf<SeqOfType>);
#[test]
fn nested_sequence_of() {
let mut decoder = Decoder::new(
r#"<NestedSeqOf>
<SeqOfType>
<INTEGER>-1</INTEGER>
<INTEGER>-5</INTEGER>
<INTEGER>0</INTEGER>
<INTEGER>55</INTEGER>
<INTEGER>212424214</INTEGER>
</SeqOfType>
<SeqOfType>
<INTEGER>1</INTEGER>
<INTEGER>5</INTEGER>
<INTEGER>0</INTEGER>
<INTEGER>55</INTEGER>
<INTEGER>212424214</INTEGER>
</SeqOfType>
</NestedSeqOf>"#
.as_bytes(),
)
.unwrap();
assert_eq!(
NestedSeqOf::decode(&mut decoder).unwrap(),
NestedSeqOf(vec![
SeqOfType(vec![
Integer::from(-1),
Integer::from(-5),
Integer::from(0),
Integer::from(55),
Integer::from(212424214)
]),
SeqOfType(vec![
Integer::from(1),
Integer::from(5),
Integer::from(0),
Integer::from(55),
Integer::from(212424214)
])
])
)
}
#[derive(AsnType, Debug, Decode, PartialEq)]
#[rasn(automatic_tags)]
#[rasn(delegate)]
#[rasn(crate_root = "crate")]
struct SetOfType(crate::types::SetOf<Integer>);
#[test]
fn set_of() {
let mut decoder = Decoder::new(
r#"<SeqOfType>
<INTEGER>-1</INTEGER>
<INTEGER>-5</INTEGER>
<INTEGER>0</INTEGER>
<INTEGER>55</INTEGER>
<INTEGER>212424214</INTEGER>
</SeqOfType>"#
.as_bytes(),
)
.unwrap();
let expected = SetOf::from_vec(
[
Integer::from(-1),
Integer::from(-5),
Integer::from(0),
Integer::from(55),
Integer::from(212424214),
]
.into_iter()
.collect::<Vec<_>>(),
);
assert_eq!(
SetOfType::decode(&mut decoder).unwrap(),
SetOfType(expected)
)
}
#[test]
fn generalized_time() {
let mut decoder =
Decoder::new(r#"<TimeType>20001231235959.999+0000</TimeType>"#.as_bytes()).unwrap();
assert_eq!(
crate::types::GeneralizedTime::decode(&mut decoder).unwrap(),
GeneralizedTime::from(
chrono::NaiveDate::from_ymd_opt(2000, 12, 31)
.unwrap()
.and_hms_milli_opt(23, 59, 59, 999)
.unwrap()
.and_utc()
)
)
}
#[test]
fn utc_time() {
let mut decoder = Decoder::new(r#"<TimeType>991231235900Z</TimeType>"#.as_bytes()).unwrap();
assert_eq!(
crate::types::UtcTime::decode(&mut decoder).unwrap(),
UtcTime::from(
chrono::NaiveDate::from_ymd_opt(1999, 12, 31)
.unwrap()
.and_hms_opt(23, 59, 0)
.unwrap()
.and_utc()
)
)
}
#[derive(AsnType, Debug, Decode, PartialEq)]
#[rasn(automatic_tags)]
#[rasn(choice)]
#[rasn(crate_root = "crate")]
enum ChoiceType {
#[rasn(identifier = "int")]
Int(u8),
#[rasn(identifier = "bool")]
Bool(bool),
}
#[test]
fn choice() {
let mut decoder = Decoder::new(
r#"<ChoiceType>
<int>5</int>
</ChoiceType>"#
.as_bytes(),
)
.unwrap();
assert_eq!(
ChoiceType::decode(&mut decoder).unwrap(),
ChoiceType::Int(5)
)
}
#[test]
fn sequence_of_choices() {
let mut decoder = Decoder::new(
r#"
<SEQUENCE_OF>
<int>5</int>
<bool><false/></bool>
</SEQUENCE_OF>"#
.as_bytes(),
)
.unwrap();
assert_eq!(
SequenceOf::<ChoiceType>::decode(&mut decoder).unwrap(),
vec![ChoiceType::Int(5), ChoiceType::Bool(false)]
)
}
#[derive(AsnType, Debug, Decode, PartialEq)]
#[rasn(automatic_tags)]
#[rasn(crate_root = "crate")]
struct OptionalTest {
wine: Option<bool>,
grappa: BitString,
}
#[test]
fn optional_present() {
let mut decoder = Decoder::new(
"<TestTypeA><grappa>1010</grappa><wine><false/></wine></TestTypeA>".as_bytes(),
)
.unwrap();
assert_eq!(
OptionalTest::decode(&mut decoder).unwrap(),
OptionalTest {
wine: Some(false),
grappa: bitvec::bitvec![u8, Msb0; 1, 0, 1, 0]
}
);
}
#[test]
fn optional_absent() {
let mut decoder =
Decoder::new("<TestTypeA><grappa>1010</grappa></TestTypeA>".as_bytes()).unwrap();
assert_eq!(
OptionalTest::decode(&mut decoder).unwrap(),
OptionalTest {
wine: None,
grappa: bitvec::bitvec![u8, Msb0; 1, 0, 1, 0]
}
);
}
#[derive(AsnType, Debug, Decode, PartialEq)]
#[rasn(automatic_tags)]
#[rasn(crate_root = "crate")]
struct AnyTest {
grappa: Any,
}
#[test]
fn decodes_any() {
let mut decoder = Decoder::new(
"<AnyTest><grappa><Actual><Hello>7</Hello><Text>Text</Text></Actual></grappa></AnyTest>".as_bytes(),
)
.unwrap();
assert_eq!(
"<Actual><Hello>7</Hello><Text>Text</Text></Actual>".as_bytes(),
AnyTest::decode(&mut decoder).unwrap().grappa.as_bytes()
)
}
#[test]
fn decodes_object_identifier() {
let mut decoder =
Decoder::new("<OBJECT_IDENTIFIER>1.0.8571.2.1</OBJECT_IDENTIFIER>".as_bytes()).unwrap();
assert_eq!(
ObjectIdentifier::decode(&mut decoder).unwrap(),
ObjectIdentifier::new(&[1, 0, 8571, 2, 1]).unwrap()
)
}
#[test]
fn mapem() {
use crate::Encode;
#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq)]
#[rasn(delegate, crate_root = "crate", size("1..=63"))]
pub struct DescriptiveName(pub Ia5String);
#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq)]
#[rasn(automatic_tags, crate_root = "crate")]
#[non_exhaustive]
pub struct IntersectionGeometry {
pub name: Option<DescriptiveName>,
}
impl IntersectionGeometry {
pub fn new(name: Option<DescriptiveName>) -> Self {
Self { name }
}
}
#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq)]
#[rasn(delegate, crate_root = "crate", size("1..=32"))]
pub struct IntersectionGeometryList(pub SequenceOf<IntersectionGeometry>);
#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq)]
#[rasn(automatic_tags, crate_root = "crate")]
#[allow(clippy::upper_case_acronyms)]
pub struct MAPEM {
pub map: MapData,
}
#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq)]
#[rasn(automatic_tags, crate_root = "crate")]
#[non_exhaustive]
pub struct MapData {
pub intersections: Option<IntersectionGeometryList>,
}
impl MapData {
pub fn new(intersections: Option<IntersectionGeometryList>) -> Self {
Self { intersections }
}
}
let encoded = r#"<?xml version="1.0"?><MAPEM><map><intersections><IntersectionGeometry><name>MAP_ITS_00\19\19.3</name></IntersectionGeometry></intersections></map></MAPEM>"#;
assert_eq!(
MAPEM {
map: MapData::new(Some(IntersectionGeometryList(vec![
IntersectionGeometry::new(Some(DescriptiveName(
Ia5String::from_iso646_bytes(r#"MAP_ITS_00\19\19.3"#.as_bytes()).unwrap()
)))
])))
},
crate::xer::decode::<MAPEM>(encoded.as_bytes()).unwrap()
);
}
#[derive(AsnType, Debug, Clone, Decode, PartialEq)]
#[rasn(automatic_tags, crate_root = "crate")]
#[rasn(delegate, size("1..=8", extensible))]
pub struct ZoneIds(pub SequenceOf<Zid>);
#[derive(AsnType, Debug, Clone, Decode, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[rasn(automatic_tags, crate_root = "crate")]
#[rasn(delegate, value("1..=32", extensible))]
pub struct Zid(pub Integer);
#[derive(AsnType, Debug, Clone, Decode, PartialEq)]
#[rasn(automatic_tags, crate_root = "crate")]
#[non_exhaustive]
pub struct GicPart {
#[rasn(identifier = "detectionZoneIds")]
pub detection_zone_ids: Option<ZoneIds>,
#[rasn(identifier = "relevanceZoneIds")]
pub relevance_zone_ids: Option<ZoneIds>,
pub direction: Option<u32>,
}
#[test]
fn simple_type_sequence_of() {
let mut encoded = r#"<ZoneIds>2 5</ZoneIds>"#;
assert_eq!(
ZoneIds(vec![Zid(2.into()), Zid(5.into())]),
crate::xer::decode::<ZoneIds>(encoded.as_bytes()).unwrap()
);
encoded = r#"<ZoneIds>2</ZoneIds>"#;
assert_eq!(
ZoneIds(vec![Zid(2.into())]),
crate::xer::decode::<ZoneIds>(encoded.as_bytes()).unwrap()
);
encoded = r#"<GicPart>
<detectionZoneIds>2</detectionZoneIds>
<relevanceZoneIds>1</relevanceZoneIds>
<direction>0</direction>
</GicPart>"#;
assert_eq!(
GicPart {
detection_zone_ids: Some(ZoneIds(alloc::vec![Zid(2.into())])),
relevance_zone_ids: Some(ZoneIds(alloc::vec![Zid(1.into())])),
direction: Some(0),
},
crate::xer::decode::<GicPart>(encoded.as_bytes()).unwrap()
);
}
#[test]
fn decodes_with_and_without_default() {
#[derive(AsnType, Debug, Decode, PartialEq)]
#[rasn(automatic_tags)]
#[rasn(crate_root = "crate")]
struct DefaultSequence {
#[rasn(identifier = "bool-df", default = "bool_default")]
bool_with_default: bool,
recursion: Vec<DefaultSequence>,
}
fn bool_default() -> bool {
bool::default()
}
assert_eq!(
crate::xer::decode::<DefaultSequence>(
r#"
<DefaultSequence>
<recursion>
<DefaultSequence>
<bool-df>
<false />
</bool-df>
<recursion />
</DefaultSequence>
<DefaultSequence>
<recursion />
</DefaultSequence>
</recursion>
</DefaultSequence>
"#
.as_bytes()
)
.unwrap(),
DefaultSequence {
bool_with_default: false,
recursion: vec![
DefaultSequence {
bool_with_default: false,
recursion: vec![]
},
DefaultSequence {
bool_with_default: false,
recursion: vec![]
}
]
}
)
}
#[test]
fn decodes_extended_boolean_notation() {
assert_eq!(
crate::xer::decode::<SequenceOf<bool>>(
r#"
<SEQUENCE_OF>
<true />
<false />
<BOOLEAN>0</BOOLEAN>
<BOOLEAN>1</BOOLEAN>
<BOOLEAN>true</BOOLEAN>
<BOOLEAN>false</BOOLEAN>
</SEQUENCE_OF>
"#
.as_bytes()
)
.unwrap(),
vec![true, false, false, true, true, false]
)
}
#[test]
fn decodes_nested_extended_boolean_notation() {
#[derive(AsnType, Debug, Decode, PartialEq)]
#[rasn(automatic_tags)]
#[rasn(crate_root = "crate")]
struct Boolean {
val: bool,
}
assert_eq!(
crate::xer::decode::<SequenceOf<Boolean>>(
r#"
<SEQUENCE_OF>
<Boolean><val><true /></val></Boolean>
<Boolean><val><false /></val></Boolean>
<Boolean><val>0</val></Boolean>
<Boolean><val>1</val></Boolean>
<Boolean><val>true</val></Boolean>
<Boolean><val>false</val></Boolean>
</SEQUENCE_OF>
"#
.as_bytes()
)
.unwrap(),
vec![
Boolean { val: true },
Boolean { val: false },
Boolean { val: false },
Boolean { val: true },
Boolean { val: true },
Boolean { val: false }
]
)
}
}