use std::io;
use std::marker::PhantomData;
use crate::captured::Captured;
use crate::length::Length;
use crate::mode::Mode;
use crate::tag::Tag;
pub trait Values {
fn encoded_len(&self, mode: Mode) -> usize;
fn write_encoded<W: io::Write>(
&self,
mode: Mode,
target: &mut W
) -> Result<(), io::Error>;
fn explicit(self, tag: Tag) -> Constructed<Self>
where Self: Sized {
Constructed::new(tag, self)
}
fn to_captured(&self, mode: Mode) -> Captured {
let mut target = Vec::new();
self.write_encoded(mode, &mut target).unwrap();
Captured::new(target.into(), mode, Default::default())
}
}
impl<T: Values> Values for &'_ T {
fn encoded_len(&self, mode: Mode) -> usize {
(*self).encoded_len(mode)
}
fn write_encoded<W: io::Write>(
&self,
mode: Mode,
target: &mut W
) -> Result<(), io::Error> {
(*self).write_encoded(mode, target)
}
}
macro_rules! tupl_impl {
( tuple > ) => { };
( tuple $t:ident $( $ttail:ident )* > $i:tt $( $itail:tt )* ) => {
impl<$t: Values, $( $ttail: Values ),*> Values
for ($t, $( $ttail ),*) {
fn encoded_len(&self, mode: Mode) -> usize {
self.$i.encoded_len(mode)
$(
+ self.$itail.encoded_len(mode)
)*
}
fn write_encoded<W: io::Write>(
&self,
mode: Mode,
target: &mut W
) -> Result<(), io::Error> {
tupl_impl!( write self, mode, target, $i $( $itail )* );
Ok(())
}
}
tupl_impl!(
tuple $($ttail)* > $($itail)*
);
};
( write $self:expr, $mode:expr, $target:expr, ) => { };
( write $self:expr, $mode:expr, $target:expr, $i:tt $($itail:tt)*) => {
tupl_impl!( write $self, $mode, $target, $($itail)* );
$self.$i.write_encoded($mode, $target)?
}
}
tupl_impl!(
tuple T11 T10 T9 T8 T7 T6 T5 T4 T3 T2 T1 T0 > 11 10 9 8 7 6 5 4 3 2 1 0
);
impl<V: Values> Values for Option<V> {
fn encoded_len(&self, mode: Mode) -> usize {
match self {
Some(v) => v.encoded_len(mode),
None => 0
}
}
fn write_encoded<W: io::Write>(
&self,
mode: Mode,
target: &mut W
) -> Result<(), io::Error> {
match self {
Some(v) => v.write_encoded(mode, target),
None => Ok(())
}
}
}
impl<V: Values> Values for [V] {
fn encoded_len(&self, mode: Mode) -> usize {
self.iter().map(|v| v.encoded_len(mode)).sum()
}
fn write_encoded<W: io::Write>(&self, mode: Mode, target: &mut W)
-> Result<(), io::Error>
{
for i in self {
i.write_encoded(mode, target)?;
};
Ok(())
}
}
impl<V: Values> Values for Vec<V> {
fn encoded_len(&self, mode: Mode) -> usize {
self.iter().map(|v| v.encoded_len(mode)).sum()
}
fn write_encoded<W: io::Write>(&self, mode: Mode, target: &mut W)
-> Result<(), io::Error>
{
for i in self {
i.write_encoded(mode, target)?;
};
Ok(())
}
}
pub struct Constructed<V> {
tag: Tag,
inner: V,
}
impl<V> Constructed<V> {
pub fn new(tag: Tag, inner: V) -> Self {
Constructed { tag, inner }
}
}
impl<V: Values> Values for Constructed<V> {
fn encoded_len(&self, mode: Mode) -> usize {
let len = self.inner.encoded_len(mode);
let len = len + match mode {
Mode::Ber | Mode::Der => {
Length::Definite(len).encoded_len()
}
Mode::Cer => {
Length::Indefinite.encoded_len()
+ EndOfValue.encoded_len(mode)
}
};
self.tag.encoded_len() + len
}
fn write_encoded<W: io::Write>(
&self,
mode: Mode,
target: &mut W
) -> Result<(), io::Error> {
self.tag.write_encoded(true, target)?;
match mode {
Mode::Ber | Mode::Der => {
Length::Definite(self.inner.encoded_len(mode))
.write_encoded(target)?;
self.inner.write_encoded(mode, target)
}
Mode::Cer => {
Length::Indefinite.write_encoded(target)?;
self.inner.write_encoded(mode, target)?;
EndOfValue.write_encoded(mode, target)
}
}
}
}
pub enum Choice2<L, R> {
One(L),
Two(R)
}
impl<L: Values, R: Values> Values for Choice2<L, R> {
fn encoded_len(&self, mode: Mode) -> usize {
match *self {
Choice2::One(ref inner) => inner.encoded_len(mode),
Choice2::Two(ref inner) => inner.encoded_len(mode),
}
}
fn write_encoded<W: io::Write>(
&self,
mode: Mode,
target: &mut W
) -> Result<(), io::Error> {
match *self {
Choice2::One(ref inner) => inner.write_encoded(mode, target),
Choice2::Two(ref inner) => inner.write_encoded(mode, target),
}
}
}
pub enum Choice3<L, C, R> {
One(L),
Two(C),
Three(R)
}
impl<L: Values, C: Values, R: Values> Values for Choice3<L, C, R> {
fn encoded_len(&self, mode: Mode) -> usize {
match *self {
Choice3::One(ref inner) => inner.encoded_len(mode),
Choice3::Two(ref inner) => inner.encoded_len(mode),
Choice3::Three(ref inner) => inner.encoded_len(mode),
}
}
fn write_encoded<W: io::Write>(
&self,
mode: Mode,
target: &mut W
) -> Result<(), io::Error> {
match *self {
Choice3::One(ref inner) => inner.write_encoded(mode, target),
Choice3::Two(ref inner) => inner.write_encoded(mode, target),
Choice3::Three(ref inner) => inner.write_encoded(mode, target),
}
}
}
pub struct Iter<T>(pub T);
impl<T> Iter<T> {
pub fn new(iter: T) -> Self {
Iter(iter)
}
}
pub fn iter<T>(iter: T) -> Iter<T> {
Iter::new(iter)
}
impl<T: IntoIterator> IntoIterator for Iter<T> {
type Item = <T as IntoIterator>::Item;
type IntoIter = <T as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl<T: Clone + IntoIterator> IntoIterator for &'_ Iter<T> {
type Item = <T as IntoIterator>::Item;
type IntoIter = <T as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.clone().into_iter()
}
}
impl<T> Values for Iter<T>
where T: Clone + IntoIterator, <T as IntoIterator>::Item: Values {
fn encoded_len(&self, mode: Mode) -> usize {
self.into_iter().map(|item| item.encoded_len(mode)).sum()
}
fn write_encoded<W: io::Write>(
&self,
mode: Mode,
target: &mut W
) -> Result<(), io::Error> {
self.into_iter().try_for_each(|item| item.write_encoded(mode, target))
}
}
pub struct Slice<T, F, U, V>
where T: AsRef<[U]>, F: Fn(&U) -> V {
value: T,
f: F,
marker: PhantomData<(U, V)>,
}
impl<T, F, U, V> Slice<T, F, U, V>
where T: AsRef<[U]>, F: Fn(&U) -> V {
pub fn new(value: T, f: F) -> Self {
Slice { value, f, marker: PhantomData }
}
}
pub fn slice<T, F, U, V>(value: T, f: F) -> Slice<T, F, U, V>
where T: AsRef<[U]>, F: Fn(&U) -> V {
Slice::new(value, f)
}
impl<T, F, U, V> Values for Slice<T, F, U, V>
where T: AsRef<[U]>, F: Fn(&U) -> V, V: Values {
fn encoded_len(&self, mode: Mode) -> usize {
self.value.as_ref().iter().map(|v| (self.f)(v).encoded_len(mode)).sum()
}
fn write_encoded<W: io::Write>(
&self,
mode: Mode,
target: &mut W
) -> Result<(), io::Error> {
self.value.as_ref().iter().try_for_each(|v|
(self.f)(v).write_encoded(mode, target)
)
}
}
pub struct Nothing;
impl Values for Nothing {
fn encoded_len(&self, _mode: Mode) -> usize {
0
}
fn write_encoded<W: io::Write>(
&self,
_mode: Mode,
_target: &mut W
) -> Result<(), io::Error> {
Ok(())
}
}
pub fn sequence<V: Values>(inner: V) -> impl Values {
Constructed::new(Tag::SEQUENCE, inner)
}
pub fn sequence_as<V: Values>(tag: Tag, inner: V) -> impl Values {
Constructed::new(tag, inner)
}
pub fn set<V: Values>(inner: V) -> impl Values {
Constructed::new(Tag::SET, inner)
}
pub fn set_as<V: Values>(tag: Tag, inner: V) -> impl Values {
Constructed::new(tag, inner)
}
pub fn total_encoded_len(tag: Tag, content_l: usize) -> usize {
tag.encoded_len() + Length::Definite(content_l).encoded_len() + content_l
}
pub fn write_header<W: io::Write>(
target: &mut W,
tag: Tag,
constructed: bool,
content_length: usize
) -> Result<(), io::Error> {
tag.write_encoded(constructed, target)?;
Length::Definite(content_length).write_encoded(target)?;
Ok(())
}
struct EndOfValue;
impl Values for EndOfValue {
fn encoded_len(&self, _: Mode) -> usize {
2
}
fn write_encoded<W: io::Write>(
&self,
_: Mode,
target: &mut W
) -> Result<(), io::Error> {
let buf = [0, 0];
target.write_all(&buf)
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::encode::PrimitiveContent;
#[test]
fn encode_2_tuple() {
let mut res = Vec::new();
(0.encode(), 1.encode()).write_encoded(Mode::Der, &mut res).unwrap();
assert_eq!(res, b"\x02\x01\0\x02\x01\x01");
}
#[test]
fn encode_4_tuple() {
let mut res = Vec::new();
(0.encode(), 1.encode(), 2.encode(), 3.encode())
.write_encoded(Mode::Der, &mut res).unwrap();
assert_eq!(res, b"\x02\x01\0\x02\x01\x01\x02\x01\x02\x02\x01\x03");
}
}