use crate::error::ErrorChain;
use crate::typed::{DerDecodable, DerEncodable, DerTypeView};
use crate::{der, Asn1DerError, DerObject, Sink};
#[cfg(all(feature = "std", not(feature = "no_panic")))]
use core::ops::{Deref, DerefMut};
struct CountingSink(pub usize);
impl Sink for CountingSink {
#[cfg_attr(feature = "no_panic", no_panic::no_panic)]
fn write(&mut self, _e: u8) -> Result<(), Asn1DerError> {
match self.0.checked_add(1) {
Some(next) => {
self.0 = next;
Ok(())
}
None => Err(eunsupported!("Cannot write more than `usize::max_value()` bytes")),
}
}
}
#[derive(Copy, Clone)]
pub struct Sequence<'a> {
object: DerObject<'a>,
}
impl<'a> Sequence<'a> {
#[cfg_attr(feature = "no_panic", no_panic::no_panic)]
pub fn new<S: Sink + Into<&'a [u8]>, T: DerEncodable>(objs: &[T], mut sink: S) -> Result<Self, Asn1DerError> {
Self::write(objs, &mut sink).propagate(e!("Failed to construct sequence"))?;
let object = DerObject::decode(sink.into()).propagate(e!("Failed to load constructed sequence"))?;
Ok(Self { object })
}
#[cfg_attr(feature = "no_panic", no_panic::no_panic)]
#[allow(clippy::len_without_is_empty)]
pub fn len(&self) -> usize {
let (mut pos, mut ctr) = (0usize, 0usize);
while self.subobject_at(&mut pos).is_ok() {
ctr = ctr.saturating_add(1);
}
ctr
}
#[cfg_attr(feature = "no_panic", no_panic::no_panic)]
pub fn get(&self, n: usize) -> Result<DerObject<'a>, Asn1DerError> {
let mut pos = 0;
for _ in 0..n {
self.subobject_at(&mut pos).propagate(e!("No subobject for given index"))?;
}
self.subobject_at(&mut pos).propagate(e!("No subobject for given index"))
}
#[cfg_attr(feature = "no_panic", no_panic::no_panic)]
pub fn get_as<T: DerDecodable<'a>>(&self, n: usize) -> Result<T, Asn1DerError> {
let object = self.get(n).propagate(e!("No subobject for given index"))?;
T::load(object).propagate(e!("Failed to load subobject"))
}
#[cfg_attr(feature = "no_panic", no_panic::no_panic)]
fn subobject_at(&self, pos: &mut usize) -> Result<DerObject<'a>, Asn1DerError> {
let sequence_value = self.object.value();
let object = DerObject::decode_at(sequence_value, *pos).propagate(e!("Failed to decode subobject"))?;
let (object_header, object_value) = (object.header(), object.value());
let len = object_header.len().saturating_add(object_value.len());
match pos.checked_add(len) {
Some(next_pos) => *pos = next_pos,
None => Err(einval!("The new object cannot be as long as announced"))?,
}
Ok(object)
}
#[cfg_attr(feature = "no_panic", no_panic::no_panic)]
pub fn write<S: Sink, T: DerEncodable>(objs: &[T], sink: &mut S) -> Result<(), Asn1DerError> {
let mut ctr = CountingSink(0);
objs.iter().try_for_each(|o| o.encode(&mut ctr).propagate(e!("Failed to size subobject")))?;
sink.write(Self::TAG).propagate(e!("Failed to write tag"))?;
der::length::encode(ctr.0, sink).propagate(e!("Failed to encode length"))?;
objs.iter().try_for_each(|o| o.encode(sink).propagate(e!("Failed to encode subobject")))
}
}
impl<'a> DerTypeView<'a> for Sequence<'a> {
const TAG: u8 = b'\x30';
#[cfg_attr(feature = "no_panic", no_panic::no_panic)]
fn object(&self) -> DerObject<'a> {
self.object
}
}
impl<'a> DerDecodable<'a> for Sequence<'a> {
#[cfg_attr(feature = "no_panic", no_panic::no_panic)]
fn load(object: DerObject<'a>) -> Result<Self, Asn1DerError> {
let this = match object.tag() {
Self::TAG => Self { object },
_ => Err(einval!("DER object is not a valid sequence"))?,
};
let (mut pos, total_len) = (0, this.object.value().len());
while pos < total_len {
this.subobject_at(&mut pos).propagate(e!("Invalid subobject in sequence"))?;
}
Ok(this)
}
}
impl<'a> DerEncodable for Sequence<'a> {
#[cfg_attr(feature = "no_panic", no_panic::no_panic)]
fn encode<S: Sink>(&self, sink: &mut S) -> Result<(), Asn1DerError> {
self.object().encode(sink).propagate(e!("Failed to encode sequence"))
}
}
#[cfg(all(feature = "std", not(feature = "no_panic")))]
pub struct SequenceVec<T>(pub Vec<T>);
#[cfg(all(feature = "std", not(feature = "no_panic")))]
impl<T> Deref for SequenceVec<T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[cfg(all(feature = "std", not(feature = "no_panic")))]
impl<T> DerefMut for SequenceVec<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[cfg(all(feature = "std", not(feature = "no_panic")))]
impl<'a, T: DerDecodable<'a>> DerDecodable<'a> for SequenceVec<T> {
fn load(object: DerObject<'a>) -> Result<Self, Asn1DerError> {
let sequence = Sequence::load(object).propagate(e!("Failed to load sequence"))?;
let mut vec = Vec::new();
let (mut pos, total_len) = (0, sequence.object.value().len());
while pos < total_len {
let subobject = sequence.subobject_at(&mut pos).propagate(e!("Failed to load subelement"))?;
let element: T = T::load(subobject).propagate(e!("Failed to load subelement"))?;
vec.push(element);
}
Ok(Self(vec))
}
}
#[cfg(all(feature = "std", not(feature = "no_panic")))]
impl<T: DerEncodable> DerEncodable for SequenceVec<T> {
fn encode<S: Sink>(&self, sink: &mut S) -> Result<(), Asn1DerError> {
Sequence::write(self, sink).propagate(e!("Failed to write sequence"))
}
}