use crate::*;
use alloc::borrow::Cow;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use core::convert::TryFrom;
mod iterator;
mod sequence_of;
mod vec;
pub use iterator::*;
pub use sequence_of::*;
#[cfg_attr(feature = "std", doc = r#"```"#)]
#[cfg_attr(not(feature = "std"), doc = r#"```rust,compile_fail"#)]
#[cfg_attr(feature = "std", doc = r#"```"#)]
#[cfg_attr(not(feature = "std"), doc = r#"```rust,compile_fail"#)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Sequence<'a> {
pub content: Cow<'a, [u8]>,
}
impl<'a> Sequence<'a> {
pub const fn new(content: Cow<'a, [u8]>) -> Self {
Sequence { content }
}
#[inline]
pub fn into_content(self) -> Cow<'a, [u8]> {
self.content
}
pub fn and_then<U, F, E>(self, op: F) -> ParseResult<'a, U, E>
where
F: FnOnce(Cow<'a, [u8]>) -> ParseResult<'a, U, E>,
{
op(self.content)
}
pub fn from_ber_and_then<U, F, E>(bytes: &'a [u8], op: F) -> ParseResult<'a, U, E>
where
F: FnOnce(&'a [u8]) -> ParseResult<'a, U, E>,
E: From<Error>,
{
let (rem, seq) = Sequence::from_ber(bytes).map_err(Err::convert)?;
let data = match seq.content {
Cow::Borrowed(b) => b,
Cow::Owned(_) => unreachable!(),
};
let (_, res) = op(data)?;
Ok((rem, res))
}
pub fn from_der_and_then<U, F, E>(bytes: &'a [u8], op: F) -> ParseResult<'a, U, E>
where
F: FnOnce(&'a [u8]) -> ParseResult<'a, U, E>,
E: From<Error>,
{
let (rem, seq) = Sequence::from_der(bytes).map_err(Err::convert)?;
let data = match seq.content {
Cow::Borrowed(b) => b,
Cow::Owned(_) => unreachable!(),
};
let (_, res) = op(data)?;
Ok((rem, res))
}
pub fn parse<F, T, E>(&'a self, mut f: F) -> ParseResult<'a, T, E>
where
F: FnMut(&'a [u8]) -> ParseResult<'a, T, E>,
{
let input: &[u8] = &self.content;
f(input)
}
pub fn parse_into<F, T, E>(self, mut f: F) -> ParseResult<'a, T, E>
where
F: FnMut(&'a [u8]) -> ParseResult<'a, T, E>,
E: From<Error>,
{
match self.content {
Cow::Borrowed(b) => f(b),
_ => Err(Err::Error(Error::LifetimeError.into())),
}
}
pub fn ber_iter<T, E>(&'a self) -> SequenceIterator<'a, T, BerParser, E>
where
T: FromBer<'a, E>,
{
SequenceIterator::new(&self.content)
}
pub fn der_iter<T, E>(&'a self) -> SequenceIterator<'a, T, DerParser, E>
where
T: FromDer<'a, E>,
{
SequenceIterator::new(&self.content)
}
pub fn ber_sequence_of<T, E>(&'a self) -> Result<Vec<T>, E>
where
T: FromBer<'a, E>,
E: From<Error>,
{
self.ber_iter().collect()
}
pub fn der_sequence_of<T, E>(&'a self) -> Result<Vec<T>, E>
where
T: FromDer<'a, E>,
E: From<Error>,
{
self.der_iter().collect()
}
pub fn into_ber_sequence_of<T, U, E>(self) -> Result<Vec<T>, E>
where
for<'b> T: FromBer<'b, E>,
E: From<Error>,
T: ToStatic<Owned = T>,
{
match self.content {
Cow::Borrowed(bytes) => SequenceIterator::<T, BerParser, E>::new(bytes).collect(),
Cow::Owned(data) => {
let v1 = SequenceIterator::<T, BerParser, E>::new(&data)
.collect::<Result<Vec<T>, E>>()?;
let v2 = v1.iter().map(|t| t.to_static()).collect::<Vec<_>>();
Ok(v2)
}
}
}
pub fn into_der_sequence_of<T, U, E>(self) -> Result<Vec<T>, E>
where
for<'b> T: FromDer<'b, E>,
E: From<Error>,
T: ToStatic<Owned = T>,
{
match self.content {
Cow::Borrowed(bytes) => SequenceIterator::<T, DerParser, E>::new(bytes).collect(),
Cow::Owned(data) => {
let v1 = SequenceIterator::<T, DerParser, E>::new(&data)
.collect::<Result<Vec<T>, E>>()?;
let v2 = v1.iter().map(|t| t.to_static()).collect::<Vec<_>>();
Ok(v2)
}
}
}
pub fn into_der_sequence_of_ref<T, E>(self) -> Result<Vec<T>, E>
where
T: FromDer<'a, E>,
E: From<Error>,
{
match self.content {
Cow::Borrowed(bytes) => SequenceIterator::<T, DerParser, E>::new(bytes).collect(),
Cow::Owned(_) => Err(Error::LifetimeError.into()),
}
}
}
impl ToStatic for Sequence<'_> {
type Owned = Sequence<'static>;
fn to_static(&self) -> Self::Owned {
Sequence {
content: Cow::Owned(self.content.to_vec()),
}
}
}
impl<T, U> ToStatic for Vec<T>
where
T: ToStatic<Owned = U>,
U: 'static,
{
type Owned = Vec<U>;
fn to_static(&self) -> Self::Owned {
self.iter().map(|t| t.to_static()).collect()
}
}
impl AsRef<[u8]> for Sequence<'_> {
fn as_ref(&self) -> &[u8] {
&self.content
}
}
impl<'a> TryFrom<Any<'a>> for Sequence<'a> {
type Error = Error;
fn try_from(any: Any<'a>) -> Result<Sequence<'a>> {
TryFrom::try_from(&any)
}
}
impl<'a, 'b> TryFrom<&'b Any<'a>> for Sequence<'a> {
type Error = Error;
fn try_from(any: &'b Any<'a>) -> Result<Sequence<'a>> {
any.tag().assert_eq(Self::TAG)?;
any.header.assert_constructed()?;
Ok(Sequence {
content: Cow::Borrowed(any.data),
})
}
}
impl CheckDerConstraints for Sequence<'_> {
fn check_constraints(_any: &Any) -> Result<()> {
Ok(())
}
}
impl DerAutoDerive for Sequence<'_> {}
impl Tagged for Sequence<'_> {
const TAG: Tag = Tag::Sequence;
}
#[cfg(feature = "std")]
impl ToDer for Sequence<'_> {
fn to_der_len(&self) -> Result<usize> {
let sz = self.content.len();
if sz < 127 {
Ok(2 + sz)
} else {
let n = Length::Definite(sz).to_der_len()?;
Ok(1 + n + sz)
}
}
fn write_der_header(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
let header = Header::new(
Class::Universal,
true,
Self::TAG,
Length::Definite(self.content.len()),
);
header.write_der_header(writer)
}
fn write_der_content(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
writer.write(&self.content).map_err(Into::into)
}
}
#[cfg(feature = "std")]
impl Sequence<'_> {
pub fn from_iter_to_der<T, IT>(it: IT) -> SerializeResult<Self>
where
IT: Iterator<Item = T>,
T: ToDer,
T: Tagged,
{
let mut v = Vec::new();
for item in it {
let item_v = <T as ToDer>::to_der_vec(&item)?;
v.extend_from_slice(&item_v);
}
Ok(Sequence {
content: Cow::Owned(v),
})
}
}