mod borrowed {
use crate::{property::DictRef, util};
use core::ops::Add;
use der::{
asn1::Ia5StringRef, DecodeValue, Encode, EncodeValue, FixedTag, Header, Length, Reader,
Writer,
};
#[cfg(any(feature = "alloc", test))]
use {
super::PayloadProps,
crate::{property::Value, Tag},
alloc::collections::BTreeMap,
der::referenced::RefToOwned,
};
#[derive(Clone, Debug)]
#[cfg_attr(test, derive(Eq, PartialEq))]
pub struct PayloadPropsRef<'a> {
pub(super) body: DictRef<'a>,
}
impl<'a> PayloadPropsRef<'a> {
pub fn decode_after_magic<R: Reader<'a>>(decoder: &mut R) -> der::Result<Self> {
Ok(PayloadPropsRef {
body: decoder.decode()?,
})
}
#[cfg(any(feature = "alloc", test))]
pub fn decode_body(&self) -> der::Result<BTreeMap<Tag, Value>> {
self.body.decode_owned()
}
}
impl FixedTag for PayloadPropsRef<'_> {
const TAG: der::Tag = der::Tag::Sequence;
}
impl<'a> DecodeValue<'a> for PayloadPropsRef<'a> {
fn decode_value<R: Reader<'a>>(decoder: &mut R, header: Header) -> der::Result<Self> {
decoder.read_nested(header.length, |nested_decoder| {
util::decode_and_check_magic(nested_decoder, b"PAYP")?;
Self::decode_after_magic(nested_decoder)
})
}
}
impl EncodeValue for PayloadPropsRef<'_> {
fn value_len(&self) -> der::Result<Length> {
let magic_len = Ia5StringRef::new(b"PAYP")?.encoded_len()?;
let body_len = self.body.encoded_len()?;
magic_len.add(body_len)
}
fn encode_value(&self, encoder: &mut impl Writer) -> der::Result<()> {
let magic = Ia5StringRef::new(b"PAYP")?;
magic.encode(encoder)?;
self.body.encode(encoder)
}
}
#[cfg(any(feature = "alloc", test))]
impl<'a> From<&'a PayloadProps> for PayloadPropsRef<'a> {
fn from(value: &'a PayloadProps) -> Self {
Self {
body: (&value.body).into(),
}
}
}
#[cfg(any(feature = "alloc", test))]
impl<'a> RefToOwned<'a> for PayloadPropsRef<'a> {
type Owned = PayloadProps;
fn ref_to_owned(&self) -> Self::Owned {
self.into()
}
}
}
#[cfg(any(feature = "alloc", test))]
mod owned {
use super::PayloadPropsRef;
use crate::{
property::{Dict, Value},
Tag,
};
use alloc::collections::BTreeMap;
use der::{
referenced::OwnedToRef, DecodeValue, EncodeValue, FixedTag, Header, Length, Reader, Writer,
};
#[derive(Clone, Debug)]
#[cfg_attr(test, derive(Eq, PartialEq))]
pub struct PayloadProps {
pub(super) body: Dict,
}
impl PayloadProps {
pub fn decode_after_magic<'a, R: Reader<'a>>(decoder: &mut R) -> der::Result<Self> {
Ok(PayloadProps {
body: decoder.decode()?,
})
}
pub fn encode_from(value: &BTreeMap<Tag, Value>) -> der::Result<Self> {
Ok(Self {
body: Dict::encode_from(value)?,
})
}
pub fn decode_body(&self) -> der::Result<BTreeMap<Tag, Value>> {
self.body.decode_owned()
}
}
impl From<PayloadPropsRef<'_>> for PayloadProps {
fn from(value: PayloadPropsRef<'_>) -> Self {
(&value).into()
}
}
impl From<&'_ PayloadPropsRef<'_>> for PayloadProps {
fn from(value: &'_ PayloadPropsRef<'_>) -> Self {
Self {
body: (&value.body).into(),
}
}
}
impl FixedTag for PayloadProps {
const TAG: der::Tag = der::Tag::Sequence;
}
impl<'a> DecodeValue<'a> for PayloadProps {
fn decode_value<R: Reader<'a>>(decoder: &mut R, header: Header) -> der::Result<Self> {
PayloadPropsRef::decode_value(decoder, header).map(PayloadProps::from)
}
}
impl EncodeValue for PayloadProps {
fn value_len(&self) -> der::Result<Length> {
PayloadPropsRef::from(self).value_len()
}
fn encode_value(&self, encoder: &mut impl Writer) -> der::Result<()> {
PayloadPropsRef::from(self).encode_value(encoder)
}
}
impl OwnedToRef for PayloadProps {
type Borrowed<'a> = PayloadPropsRef<'a>;
fn owned_to_ref(&self) -> Self::Borrowed<'_> {
self.into()
}
}
}
pub use borrowed::PayloadPropsRef;
#[cfg(any(feature = "alloc", test))]
pub use owned::PayloadProps;
#[cfg(test)]
mod tests {
use super::*;
use crate::{property::Value, Tag};
use alloc::{collections::BTreeMap, vec::Vec};
use der::{Decode, Encode};
use hex_literal::hex;
const TEST_PROPS: &[u8] = &hex!(
"3081B71604504159503181AEFF86DB8DCA7013301116046B636570020900FFFF
FFF007D38540FF86DB8DD8660E300C16046B636C66020403550000FF86DB8DD8
6F13301116046B636C6F020900FFFFFFF007004000FF86DB8DD87A0E300C1604
6B636C7A020400F20000FF86DB8DE4660B300916046B637266020100FF86DB8D
E47A0E300C16046B63727A0204031D8000FF86DB8DEE660E300C16046B637766
0204031D8000FF86DB8DEE7A0D300B16046B63777A0203378000"
);
fn make_test_dict() -> BTreeMap<Tag, Value> {
let mut dict = BTreeMap::new();
dict.insert(Tag::from_bytes(*b"kcep"), 18446744005121377600u64.into());
dict.insert(Tag::from_bytes(*b"kclf"), 55902208u64.into());
dict.insert(Tag::from_bytes(*b"kclo"), 18446744005107531776u64.into());
dict.insert(Tag::from_bytes(*b"kclz"), 15859712u64.into());
dict.insert(Tag::from_bytes(*b"kcrf"), 0u64.into());
dict.insert(Tag::from_bytes(*b"kcrz"), 52264960u64.into());
dict.insert(Tag::from_bytes(*b"kcwf"), 52264960u64.into());
dict.insert(Tag::from_bytes(*b"kcwz"), 3637248u64.into());
dict
}
#[test]
fn test_decode() {
let props = PayloadPropsRef::from_der(TEST_PROPS).unwrap();
let body = props.decode_body().unwrap();
let expected = make_test_dict();
assert_eq!(expected, body);
}
#[test]
fn test_encode() {
let props = PayloadPropsRef::from_der(TEST_PROPS).unwrap();
let mut encoded = Vec::new();
props.encode_to_vec(&mut encoded).unwrap();
assert_eq!(encoded, TEST_PROPS);
}
}