use crate::{
Asn1DerError, DerObject, Sink, error::ErrorChain, der,
typed::{ DerTypeView, DerDecodable, DerEncodable }
};
#[cfg(not(any(feature = "no_std", feature = "no_panic")))]
use crate::rust::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) => Ok(self.0 = next),
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)]
pub fn len(&self) -> usize {
let (mut pos, mut ctr) = (0usize, 0usize);
while let Ok(_) = self.subobject_at(&mut pos) {
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(not(any(feature = "no_std", feature = "no_panic")))]
pub struct SequenceVec<T>(pub Vec<T>);
#[cfg(not(any(feature = "no_std", feature = "no_panic")))]
impl<T> Deref for SequenceVec<T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[cfg(not(any(feature = "no_std", feature = "no_panic")))]
impl<T> DerefMut for SequenceVec<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[cfg(not(any(feature = "no_std", 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 objects = (0..sequence.len()).try_fold(Vec::new(), |mut vec, i| {
let subobject: T = sequence.get_as(i).propagate(e!("Failed to load subelement"))?;
vec.push(subobject);
Ok(vec)
})?;
Ok(Self(objects))
}
}
#[cfg(not(any(feature = "no_std", 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"))
}
}