use core::marker::PhantomData;
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, vec::Vec};
use crate::der::decoder::Decoder;
use crate::error::{Error, Result};
use crate::traits::{Decode, Encode};
use crate::{Encoding, Length, Tag};
pub struct SequenceOf<'a, T> {
owner: Option<Box<[u8]>>,
full_content: &'a [u8],
remaining: &'a [u8],
encoding: Encoding,
length: usize,
consumed: usize,
_phantom: PhantomData<T>,
}
impl<'a, T> core::fmt::Debug for SequenceOf<'a, T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("SequenceOf")
.field("full_content", &self.full_content)
.field("remaining", &self.remaining)
.field("encoding", &self.encoding)
.field("length", &self.length)
.field("consumed", &self.consumed)
.finish()
}
}
impl<'a, T> SequenceOf<'a, T>
where
T: Decode<'a>,
{
pub(crate) fn new(content: &'a [u8], encoding: Encoding) -> Result<Self> {
let length = Self::count_elements(content, encoding)?;
Ok(Self {
owner: None,
full_content: content,
remaining: content,
encoding,
length,
consumed: 0,
_phantom: PhantomData,
})
}
fn count_elements(content: &'a [u8], encoding: Encoding) -> Result<usize> {
let mut decoder = Decoder::new(content, encoding);
let mut count = 0;
while !decoder.is_empty() {
decoder.read_tag()?;
let length = decoder.read_length()?;
match length {
Length::Definite(len) => {
decoder.read_bytes(len)?;
}
Length::Indefinite => {
decoder.read_indefinite_content()?;
}
}
count += 1;
}
Ok(count)
}
pub fn len(&self) -> usize {
self.length - self.consumed
}
pub fn is_empty(&self) -> bool {
self.consumed >= self.length
}
pub fn collect_vec(self) -> Result<Vec<T>> {
let mut result = Vec::with_capacity(self.length);
for element in self {
result.push(element);
}
Ok(result)
}
pub fn reset(&mut self) {
self.remaining = self.full_content;
self.consumed = 0;
}
pub fn content_bytes(&self) -> &'a [u8] {
self.full_content
}
}
impl<T> SequenceOf<'static, T>
where
T: Decode<'static> + Encode,
{
pub fn from_vec(elements: Vec<T>) -> Result<SequenceOf<'static, T>> {
use crate::tag::TAG_SEQUENCE;
use crate::Encoder;
let tag = Tag::universal_constructed(TAG_SEQUENCE);
let mut encoder = Encoder::new(Encoding::Der);
encoder.write_tag(tag)?;
let mut content_encoder = Encoder::new(Encoding::Der);
for element in &elements {
content_encoder.encode(element)?;
}
let content = content_encoder.finish()?;
encoder.write_length(content.len())?;
encoder.write_bytes(&content);
let boxed: Box<[u8]> = encoder.finish()?.into_boxed_slice();
let (content_offset, content_len) = {
let mut tmp = crate::Decoder::new(&boxed, Encoding::Der);
let read_tag = tmp.read_tag()?;
if read_tag != tag {
return Err(crate::Error::UnexpectedTag {
expected: tag,
actual: read_tag,
position: 0,
});
}
let len = match tmp.read_length()? {
crate::Length::Definite(n) => n,
crate::Length::Indefinite => {
return Err(crate::Error::IndefiniteLengthInDer { position: 0 });
}
};
(tmp.position(), len)
};
let content_slice: &'static [u8] =
unsafe { core::slice::from_raw_parts(boxed.as_ptr().add(content_offset), content_len) };
let element_count = Self::count_elements(content_slice, Encoding::Der)?;
Ok(SequenceOf {
owner: Some(boxed),
full_content: content_slice,
remaining: content_slice,
encoding: Encoding::Der,
length: element_count,
consumed: 0,
_phantom: PhantomData,
})
}
pub fn try_from_iter<I>(iter: I) -> Result<SequenceOf<'static, T>>
where
I: IntoIterator<Item = T>,
{
Self::from_vec(iter.into_iter().collect())
}
}
impl<'a, T> Clone for SequenceOf<'a, T> {
fn clone(&self) -> Self {
match &self.owner {
None => {
SequenceOf {
owner: None,
full_content: self.full_content,
remaining: self.remaining,
encoding: self.encoding,
length: self.length,
consumed: self.consumed,
_phantom: PhantomData,
}
}
Some(old_box) => {
let new_box = old_box.clone();
let old_base = old_box.as_ptr() as usize;
let full_content_offset = self.full_content.as_ptr() as usize - old_base;
let remaining_offset = self.remaining.as_ptr() as usize - old_base;
let new_full_content: &'static [u8] = unsafe {
core::slice::from_raw_parts(
new_box.as_ptr().add(full_content_offset),
self.full_content.len(),
)
};
let new_remaining: &'static [u8] = unsafe {
core::slice::from_raw_parts(
new_box.as_ptr().add(remaining_offset),
self.remaining.len(),
)
};
SequenceOf {
owner: Some(new_box),
full_content: new_full_content,
remaining: new_remaining,
encoding: self.encoding,
length: self.length,
consumed: self.consumed,
_phantom: PhantomData,
}
}
}
}
}
impl<'a, T> Iterator for SequenceOf<'a, T>
where
T: Decode<'a>,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.consumed >= self.length {
return None;
}
let mut decoder = Decoder::new(self.remaining, self.encoding);
let element = match T::decode(&mut decoder) {
Ok(el) => el,
Err(_) => return None,
};
self.remaining = decoder.remaining();
self.consumed += 1;
Some(element)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.length - self.consumed;
(remaining, Some(remaining))
}
}
impl<'a, T> ExactSizeIterator for SequenceOf<'a, T>
where
T: Decode<'a>,
{
fn len(&self) -> usize {
self.length - self.consumed
}
}
impl<'a, T> Decode<'a> for SequenceOf<'a, T>
where
T: Decode<'a>,
{
fn decode(decoder: &mut Decoder<'a>) -> Result<Self> {
use crate::tag::TAG_SEQUENCE;
let tag = Tag::universal_constructed(TAG_SEQUENCE);
let read_tag = decoder.read_tag()?;
if read_tag != tag {
return Err(Error::UnexpectedTag {
expected: tag,
actual: read_tag,
position: decoder.position(),
});
}
let length = decoder.read_length()?;
let content = match length {
crate::Length::Definite(len) => decoder.read_bytes(len)?,
crate::Length::Indefinite => {
return Err(Error::IndefiniteLengthInDer {
position: decoder.position(),
});
}
};
SequenceOf::new(content, decoder.encoding())
}
}
impl<'a, T> Encode for SequenceOf<'a, T>
where
T: Decode<'a> + Encode,
{
fn encode(&self, encoder: &mut crate::Encoder) -> Result<()> {
use crate::tag::TAG_SEQUENCE;
let tag = Tag::universal_constructed(TAG_SEQUENCE);
encoder.write_tag(tag)?;
encoder.write_length(self.full_content.len())?;
encoder.write_bytes(self.full_content);
Ok(())
}
fn encoded_len(&self) -> Result<usize> {
let content_len = self.full_content.len();
let tag_len = 1;
let length_len = crate::Length::Definite(content_len).encoded_len()?;
Ok(tag_len + length_len + content_len)
}
}
impl<'a, T> crate::traits::Tagged for SequenceOf<'a, T> {
fn tag() -> Tag {
use crate::tag::TAG_SEQUENCE;
Tag::universal_constructed(TAG_SEQUENCE)
}
}
impl<'a, T> PartialEq for SequenceOf<'a, T>
where
T: Decode<'a> + PartialEq,
{
fn eq(&self, other: &Self) -> bool {
if self.len() != other.len() {
return false;
}
let mut it1 = self.clone();
let mut it2 = other.clone();
while let (Some(v1), Some(v2)) = (it1.next(), it2.next()) {
if v1 != v2 {
return false;
}
}
true
}
}
impl<'a, T> Eq for SequenceOf<'a, T> where T: Decode<'a> + Eq {}
pub type SetOf<'a, T> = SequenceOf<'a, T>;
#[cfg(test)]
mod tests {
use super::*;
use crate::types::primitive::Integer;
#[test]
fn test_sequenceof_from_vec() {
let elements = vec![
Integer::from(1),
Integer::from(2),
Integer::from(3),
Integer::from(42),
Integer::from(100),
];
let seq = SequenceOf::from_vec(elements.clone()).unwrap();
assert_eq!(seq.len(), 5);
assert!(!seq.is_empty());
let collected: Vec<_> = seq.collect_vec().unwrap();
assert_eq!(collected.len(), 5);
assert_eq!(collected[0], Integer::from(1));
assert_eq!(collected[1], Integer::from(2));
assert_eq!(collected[2], Integer::from(3));
assert_eq!(collected[3], Integer::from(42));
assert_eq!(collected[4], Integer::from(100));
}
#[test]
fn test_sequenceof_from_iter() {
let seq = SequenceOf::try_from_iter((1..=5).map(Integer::from)).unwrap();
assert_eq!(seq.len(), 5);
let values: Vec<_> = seq.map(|i| i.as_i64().unwrap()).collect();
assert_eq!(values, vec![1, 2, 3, 4, 5]);
}
#[test]
fn test_sequenceof_empty() {
let seq = SequenceOf::<Integer>::from_vec(vec![]).unwrap();
assert_eq!(seq.len(), 0);
assert!(seq.is_empty());
let collected = seq.collect_vec().unwrap();
assert_eq!(collected.len(), 0);
}
#[test]
fn test_sequenceof_iteration_multiple_times() {
let elements = vec![Integer::from(10), Integer::from(20), Integer::from(30)];
let mut seq = SequenceOf::from_vec(elements).unwrap();
let first: Vec<_> = seq.clone().collect_vec().unwrap();
assert_eq!(first.len(), 3);
seq.reset();
let second: Vec<_> = seq.collect_vec().unwrap();
assert_eq!(second, first);
}
#[test]
fn test_sequenceof_size_hint() {
let seq = SequenceOf::try_from_iter((1..=10).map(Integer::from)).unwrap();
assert_eq!(seq.len(), 10);
assert_eq!(seq.size_hint(), (10, Some(10)));
let mut iter = seq;
iter.next(); assert_eq!(iter.size_hint(), (9, Some(9)));
assert_eq!(iter.len(), 9); }
#[test]
fn test_sequenceof_partial_iteration() {
let seq = SequenceOf::try_from_iter((1..=5).map(Integer::from)).unwrap();
let mut iter = seq;
assert_eq!(iter.next().unwrap().as_i64().unwrap(), 1);
assert_eq!(iter.next().unwrap().as_i64().unwrap(), 2);
assert_eq!(iter.len(), 3); }
#[test]
fn test_sequenceof_encode_decode_roundtrip() {
use crate::{Decoder, Encoder, Encoding};
let original = vec![Integer::from(7), Integer::from(14), Integer::from(21)];
let seq = SequenceOf::from_vec(original.clone()).unwrap();
let mut encoder = Encoder::new(Encoding::Der);
encoder.encode(&seq).unwrap();
let encoded = encoder.finish().unwrap();
let mut decoder = Decoder::new(&encoded, Encoding::Der);
let decoded: SequenceOf<Integer> = decoder.decode().unwrap();
let decoded_vec = decoded.collect_vec().unwrap();
assert_eq!(decoded_vec, original);
}
#[test]
fn test_sequenceof_equality() {
let seq1 = SequenceOf::from_vec(vec![Integer::from(1), Integer::from(2)]).unwrap();
let seq2 = SequenceOf::from_vec(vec![Integer::from(1), Integer::from(2)]).unwrap();
let seq3 = SequenceOf::from_vec(vec![Integer::from(1), Integer::from(3)]).unwrap();
assert_eq!(seq1, seq2);
assert_ne!(seq1, seq3);
}
#[test]
fn test_sequenceof_content_bytes() {
use crate::{Decoder, Encoder, Encoding};
let elements = vec![Integer::from(1), Integer::from(2), Integer::from(3)];
let seq = SequenceOf::from_vec(elements).unwrap();
let mut encoder = Encoder::new(Encoding::Der);
encoder.encode(&seq).unwrap();
let full_tlv = encoder.finish().unwrap();
let mut decoder = Decoder::new(&full_tlv, Encoding::Der);
let parsed: SequenceOf<Integer> = decoder.decode().unwrap();
let content = parsed.content_bytes();
assert!(!content.is_empty());
assert_eq!(
&full_tlv[2..],
content,
"content_bytes must match TLV content"
);
let mut reconstructed = Vec::new();
reconstructed.push(0x30u8); reconstructed.push(content.len() as u8); reconstructed.extend_from_slice(content);
assert_eq!(reconstructed, full_tlv);
}
}