use crate::signature;
use crate::wire::marshal::traits::Signature;
use crate::wire::unmarshal;
use crate::wire::unmarshal::UnmarshalContext;
use crate::wire::util;
use crate::ByteOrder;
use std::borrow::Cow;
pub trait Unmarshal<'buf, 'fds>: Sized + Signature {
fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult<Self>;
}
pub fn unmarshal<'buf, 'fds, T: Unmarshal<'buf, 'fds>>(
ctx: &mut UnmarshalContext<'fds, 'buf>,
) -> unmarshal::UnmarshalResult<T> {
T::unmarshal(ctx)
}
#[test]
fn test_generic_unmarshal() {
use crate::wire::marshal::MarshalContext;
use crate::Marshal;
let mut fds = Vec::new();
let mut buf = Vec::new();
let mut ctx = MarshalContext {
buf: &mut buf,
fds: &mut fds,
byteorder: ByteOrder::LittleEndian,
};
let ctx = &mut ctx;
"ABCD".marshal(ctx).unwrap();
let _s: &str = unmarshal(&mut UnmarshalContext {
buf: &ctx.buf,
byteorder: ctx.byteorder,
fds: &ctx.fds,
offset: 0,
})
.unwrap()
.1;
ctx.buf.clear();
true.marshal(ctx).unwrap();
let _b: bool = unmarshal(&mut UnmarshalContext {
buf: &ctx.buf,
byteorder: ctx.byteorder,
fds: &ctx.fds,
offset: 0,
})
.unwrap()
.1;
ctx.buf.clear();
0i32.marshal(ctx).unwrap();
let _i = unmarshal::<i32>(&mut UnmarshalContext {
buf: &ctx.buf,
byteorder: ctx.byteorder,
fds: &ctx.fds,
offset: 0,
})
.unwrap()
.1;
ctx.buf.clear();
fn x(_arg: (i32, i32, &str)) {}
(0, 0, "ABCD").marshal(ctx).unwrap();
let arg = unmarshal(&mut UnmarshalContext {
buf: &ctx.buf,
byteorder: ctx.byteorder,
fds: &ctx.fds,
offset: 0,
})
.unwrap()
.1;
x(arg);
}
impl<'buf, 'fds, E1> Unmarshal<'buf, 'fds> for (E1,)
where
E1: Unmarshal<'buf, 'fds> + Sized,
{
fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult<Self> {
let padding = ctx.align_to(8)?;
let (bytes, val1) = E1::unmarshal(ctx)?;
Ok((bytes + padding, (val1,)))
}
}
impl<'buf, 'fds, E1, E2> Unmarshal<'buf, 'fds> for (E1, E2)
where
E1: Unmarshal<'buf, 'fds> + Sized,
E2: Unmarshal<'buf, 'fds> + Sized,
{
fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult<Self> {
let start_offset = ctx.offset;
ctx.align_to(8)?;
let (_bytes, val1) = E1::unmarshal(ctx)?;
ctx.align_to(E2::alignment())?;
let (_bytes, val2) = E2::unmarshal(ctx)?;
let total_bytes = ctx.offset - start_offset;
Ok((total_bytes, (val1, val2)))
}
}
impl<'buf, 'fds, E1, E2, E3> Unmarshal<'buf, 'fds> for (E1, E2, E3)
where
E1: Unmarshal<'buf, 'fds> + Sized,
E2: Unmarshal<'buf, 'fds> + Sized,
E3: Unmarshal<'buf, 'fds> + Sized,
{
fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult<Self> {
let start_offset = ctx.offset;
ctx.align_to(8)?;
let (_bytes, val1) = E1::unmarshal(ctx)?;
ctx.align_to(E2::alignment())?;
let (_bytes, val2) = E2::unmarshal(ctx)?;
ctx.align_to(E3::alignment())?;
let (_bytes, val3) = E3::unmarshal(ctx)?;
let total_bytes = ctx.offset - start_offset;
Ok((total_bytes, (val1, val2, val3)))
}
}
impl<'buf, 'fds, E1, E2, E3, E4> Unmarshal<'buf, 'fds> for (E1, E2, E3, E4)
where
E1: Unmarshal<'buf, 'fds> + Sized,
E2: Unmarshal<'buf, 'fds> + Sized,
E3: Unmarshal<'buf, 'fds> + Sized,
E4: Unmarshal<'buf, 'fds> + Sized,
{
fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult<Self> {
let start_offset = ctx.offset;
ctx.align_to(8)?;
let (_bytes, val1) = E1::unmarshal(ctx)?;
ctx.align_to(E2::alignment())?;
let (_bytes, val2) = E2::unmarshal(ctx)?;
ctx.align_to(E3::alignment())?;
let (_bytes, val3) = E3::unmarshal(ctx)?;
ctx.align_to(E4::alignment())?;
let (_bytes, val4) = E4::unmarshal(ctx)?;
let total_bytes = ctx.offset - start_offset;
Ok((total_bytes, (val1, val2, val3, val4)))
}
}
impl<'buf, 'fds> Unmarshal<'buf, 'fds> for u64 {
fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult<Self> {
let padding = ctx.align_to(Self::alignment())?;
let (bytes, val) = util::parse_u64(&ctx.buf[ctx.offset..], ctx.byteorder)?;
ctx.offset += bytes;
Ok((bytes + padding, val))
}
}
impl<'buf, 'fds> Unmarshal<'buf, 'fds> for u32 {
fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult<Self> {
let padding = ctx.align_to(Self::alignment())?;
let (bytes, val) = util::parse_u32(&ctx.buf[ctx.offset..], ctx.byteorder)?;
ctx.offset += bytes;
Ok((bytes + padding, val))
}
}
impl<'buf, 'fds> Unmarshal<'buf, 'fds> for u16 {
fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult<Self> {
let padding = ctx.align_to(Self::alignment())?;
let (bytes, val) = util::parse_u16(&ctx.buf[ctx.offset..], ctx.byteorder)?;
ctx.offset += bytes;
Ok((bytes + padding, val))
}
}
impl<'buf, 'fds> Unmarshal<'buf, 'fds> for i64 {
fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult<Self> {
let padding = ctx.align_to(Self::alignment())?;
let (bytes, val) = util::parse_u64(&ctx.buf[ctx.offset..], ctx.byteorder)
.map(|(bytes, val)| (bytes, val as i64))?;
ctx.offset += bytes;
Ok((bytes + padding, val))
}
}
impl<'buf, 'fds> Unmarshal<'buf, 'fds> for i32 {
fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult<Self> {
let padding = ctx.align_to(Self::alignment())?;
let (bytes, val) = util::parse_u32(&ctx.buf[ctx.offset..], ctx.byteorder)
.map(|(bytes, val)| (bytes, val as i32))?;
ctx.offset += bytes;
Ok((bytes + padding, val))
}
}
impl<'buf, 'fds> Unmarshal<'buf, 'fds> for i16 {
fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult<Self> {
let padding = ctx.align_to(Self::alignment())?;
let (bytes, val) = util::parse_u16(&ctx.buf[ctx.offset..], ctx.byteorder)
.map(|(bytes, val)| (bytes, val as i16))?;
ctx.offset += bytes;
Ok((bytes + padding, val))
}
}
impl<'buf, 'fds> Unmarshal<'buf, 'fds> for u8 {
fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult<Self> {
if ctx.offset >= ctx.buf.len() {
return Err(crate::wire::unmarshal::Error::NotEnoughBytes);
}
let val = ctx.buf[ctx.offset];
ctx.offset += 1;
Ok((1, val))
}
}
impl<'buf, 'fds> Unmarshal<'buf, 'fds> for bool {
fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult<Self> {
let padding = ctx.align_to(Self::alignment())?;
let (bytes, val) = util::parse_u32(&ctx.buf[ctx.offset..], ctx.byteorder)?;
ctx.offset += bytes;
match val {
0 => Ok((bytes + padding, false)),
1 => Ok((bytes + padding, true)),
_ => Err(crate::wire::unmarshal::Error::InvalidBoolean),
}
}
}
impl<'buf, 'fds> Unmarshal<'buf, 'fds> for &'buf str {
fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult<Self> {
let padding = ctx.align_to(Self::alignment())?;
let (bytes, val) = util::unmarshal_str(ctx.byteorder, &ctx.buf[ctx.offset..])?;
ctx.offset += bytes;
Ok((bytes + padding, val))
}
}
impl<'buf, 'fds> Unmarshal<'buf, 'fds> for String {
fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult<Self> {
let padding = ctx.align_to(Self::alignment())?;
let (bytes, val) = util::unmarshal_string(ctx.byteorder, &ctx.buf[ctx.offset..])?;
ctx.offset += bytes;
Ok((bytes + padding, val))
}
}
#[test]
fn test_unmarshal_byte_array() {
use crate::wire::marshal::MarshalContext;
use crate::Marshal;
let mut orig = vec![];
for x in 0..1024 {
orig.push((x % 255) as u8);
}
let mut fds = Vec::new();
let mut buf = Vec::new();
let mut ctx = MarshalContext {
buf: &mut buf,
fds: &mut fds,
byteorder: ByteOrder::LittleEndian,
};
let ctx = &mut ctx;
orig.marshal(ctx).unwrap();
assert_eq!(&ctx.buf[..4], &[0, 4, 0, 0]);
assert_eq!(ctx.buf.len(), 1028);
let (bytes, unorig) = <&[u8] as Unmarshal>::unmarshal(&mut UnmarshalContext {
buf: ctx.buf,
fds: ctx.fds,
byteorder: ctx.byteorder,
offset: 0,
})
.unwrap();
assert_eq!(bytes, orig.len() + 4);
assert_eq!(orig, unorig);
let mut orig1 = vec![];
let mut orig2 = vec![];
for x in 0..1024 {
orig1.push((x % 255) as u8);
}
for x in 0..1024 {
orig2.push(((x + 4) % 255) as u8);
}
let orig = vec![orig1.as_slice(), orig2.as_slice()];
ctx.buf.clear();
orig.marshal(ctx).unwrap();
let (_bytes, unorig) = <Vec<&[u8]> as Unmarshal>::unmarshal(&mut UnmarshalContext {
buf: ctx.buf,
fds: ctx.fds,
byteorder: ctx.byteorder,
offset: 0,
})
.unwrap();
assert_eq!(orig, unorig);
}
impl<E: Signature> Signature for Vec<E> {
fn signature() -> crate::signature::Type {
crate::signature::Type::Container(crate::signature::Container::Array(Box::new(
E::signature(),
)))
}
fn alignment() -> usize {
4
}
}
impl<E: Signature + Clone> Signature for Cow<'_, [E]> {
fn signature() -> crate::signature::Type {
let e_type = Box::new(E::signature());
crate::signature::Type::Container(crate::signature::Container::Array(e_type))
}
fn alignment() -> usize {
4
}
}
impl<'buf, 'fds> Unmarshal<'buf, 'fds> for &'buf [u8] {
fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult<Self> {
let padding = ctx.align_to(Self::alignment())?;
let (_, bytes_in_array) = u32::unmarshal(ctx)?;
let elements = &ctx.buf[ctx.offset..ctx.offset + bytes_in_array as usize];
ctx.offset += bytes_in_array as usize;
let total_bytes_used = padding + 4 + bytes_in_array as usize;
Ok((total_bytes_used, elements))
}
}
unsafe fn unmarshal_slice<'a, 'buf, 'fds, E>(
ctx: &'a mut UnmarshalContext<'fds, 'buf>,
) -> unmarshal::UnmarshalResult<&'a [E]>
where
E: Unmarshal<'buf, 'fds>,
{
let start_offset = ctx.offset;
ctx.align_to(4)?;
let (_, bytes_in_array) = u32::unmarshal(ctx)?;
let bytes_in_array = bytes_in_array as usize;
let alignment = E::alignment();
ctx.align_to(alignment)?;
if bytes_in_array % alignment != 0 {
return Err(super::Error::NotAllBytesUsed);
}
let elem_cnt = bytes_in_array / alignment;
let ptr = &ctx.buf[ctx.offset..] as *const [u8] as *const E;
let slice = std::slice::from_raw_parts(ptr, elem_cnt);
ctx.offset += bytes_in_array;
Ok((ctx.offset - start_offset, slice))
}
impl<'buf, 'fds, E: Unmarshal<'buf, 'fds> + Clone> Unmarshal<'buf, 'fds> for Cow<'buf, [E]> {
fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult<Self> {
unsafe {
if E::valid_slice(ctx.byteorder) {
let (used, src): (_, &[E]) = unmarshal_slice(ctx)?;
let l_expand: &'buf [E] = std::mem::transmute(src);
return Ok((used, Cow::Borrowed(l_expand)));
}
}
Vec::unmarshal(ctx).map(|o| (o.0, Cow::Owned(o.1)))
}
}
impl<'buf, 'fds, E: Unmarshal<'buf, 'fds>> Unmarshal<'buf, 'fds> for Vec<E> {
fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult<Self> {
unsafe {
if E::valid_slice(ctx.byteorder) {
let (used, src) = unmarshal_slice::<E>(ctx)?;
let mut ret = Vec::with_capacity(src.len());
let dst = ret.as_mut_ptr();
std::ptr::copy_nonoverlapping(src.as_ptr(), dst, src.len());
ret.set_len(src.len());
return Ok((used, ret));
}
}
let start_offset = ctx.offset;
ctx.align_to(4)?;
let (_, bytes_in_array) = u32::unmarshal(ctx)?;
ctx.align_to(E::alignment())?;
let mut elements = Vec::new();
let mut bytes_used_counter = 0;
while bytes_used_counter < bytes_in_array as usize {
if ctx.offset >= ctx.buf.len() {
return Err(super::Error::NotEnoughBytes);
}
let elem_padding = util::align_offset(E::alignment(), ctx.buf, ctx.offset)?;
bytes_used_counter += elem_padding;
ctx.offset += elem_padding;
let (bytes_used, element) = E::unmarshal(ctx)?;
elements.push(element);
bytes_used_counter += bytes_used;
}
let total_bytes_used = ctx.offset - start_offset;
Ok((total_bytes_used, elements))
}
}
impl<'buf, 'fds, K: Unmarshal<'buf, 'fds> + std::hash::Hash + Eq, V: Unmarshal<'buf, 'fds>>
Unmarshal<'buf, 'fds> for std::collections::HashMap<K, V>
{
fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult<Self> {
let start_offset = ctx.offset;
ctx.align_to(4)?;
let (_, bytes_in_array) = u32::unmarshal(ctx)?;
ctx.align_to(8)?;
let mut map = std::collections::HashMap::new();
let mut bytes_used_counter = 0;
while bytes_used_counter < bytes_in_array as usize {
if ctx.offset >= ctx.buf.len() {
return Err(super::Error::NotEnoughBytes);
}
let elem_padding = util::align_offset(8, ctx.buf, ctx.offset)?;
bytes_used_counter += elem_padding;
ctx.offset += elem_padding;
let (key_bytes_used, key) = K::unmarshal(ctx)?;
bytes_used_counter += key_bytes_used;
let val_padding = util::align_offset(V::alignment(), ctx.buf, ctx.offset)?;
bytes_used_counter += val_padding;
ctx.offset += val_padding;
let (val_bytes_used, val) = V::unmarshal(ctx)?;
bytes_used_counter += val_bytes_used;
map.insert(key, val);
}
let total_bytes_used = ctx.offset - start_offset;
Ok((total_bytes_used, map))
}
}
impl<'buf, 'fds> Unmarshal<'buf, 'fds> for crate::wire::marshal::traits::SignatureWrapper<'buf> {
fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult<Self> {
let (bytes, val) = util::unmarshal_signature(&ctx.buf[ctx.offset..])?;
ctx.offset += bytes;
let sig = crate::wire::marshal::traits::SignatureWrapper::new(val)?;
Ok((bytes, sig))
}
}
impl<'buf, 'fds, S: AsRef<str> + Unmarshal<'buf, 'fds>> Unmarshal<'buf, 'fds>
for crate::wire::marshal::traits::ObjectPath<S>
{
fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult<Self> {
let (bytes, val) = <S as Unmarshal>::unmarshal(ctx)?;
let path = crate::wire::marshal::traits::ObjectPath::new(val)?;
Ok((bytes, path))
}
}
#[derive(Debug)]
pub struct Variant<'fds, 'buf> {
pub(crate) sig: signature::Type,
pub(crate) byteorder: ByteOrder,
pub(crate) offset: usize,
pub(crate) buf: &'buf [u8],
pub(crate) fds: &'fds [crate::wire::UnixFd],
}
impl<'buf, 'fds> Variant<'fds, 'buf> {
pub fn get_value_sig(&self) -> &signature::Type {
&self.sig
}
pub fn get<T: Unmarshal<'buf, 'fds>>(&self) -> Result<T, unmarshal::Error> {
if self.sig != T::signature() {
return Err(unmarshal::Error::WrongSignature);
}
let mut ctx = UnmarshalContext {
byteorder: self.byteorder,
offset: self.offset,
buf: self.buf,
fds: self.fds,
};
T::unmarshal(&mut ctx).map(|r| r.1)
}
}
impl Signature for Variant<'_, '_> {
fn signature() -> signature::Type {
signature::Type::Container(signature::Container::Variant)
}
fn alignment() -> usize {
Variant::signature().get_alignment()
}
}
impl<'buf, 'fds> Unmarshal<'buf, 'fds> for Variant<'fds, 'buf> {
fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult<Self> {
let start_offset = ctx.offset;
let (sig_bytes, desc) = util::unmarshal_signature(&ctx.buf[ctx.offset..])?;
ctx.offset += sig_bytes;
let mut sigs = match signature::Type::parse_description(desc) {
Ok(sigs) => sigs,
Err(_) => return Err(unmarshal::Error::WrongSignature),
};
if sigs.len() != 1 {
return Err(unmarshal::Error::WrongSignature);
}
let sig = sigs.remove(0);
ctx.align_to(sig.get_alignment())?;
let start_loc = ctx.offset;
let val_bytes = crate::wire::validate_raw::validate_marshalled(
ctx.byteorder,
ctx.offset,
ctx.buf,
&sig,
)
.map_err(|e| e.1)?;
ctx.offset += val_bytes;
let total_bytes = ctx.offset - start_offset;
Ok((
total_bytes,
Variant {
sig,
buf: &ctx.buf[..ctx.offset],
offset: start_loc,
byteorder: ctx.byteorder,
fds: ctx.fds,
},
))
}
}
#[test]
fn test_unmarshal_traits() {
use crate::wire::marshal::MarshalContext;
use crate::Marshal;
let mut fds = Vec::new();
let mut buf = Vec::new();
let mut ctx = MarshalContext {
buf: &mut buf,
fds: &mut fds,
byteorder: ByteOrder::LittleEndian,
};
let ctx = &mut ctx;
let original = &["a", "b"];
original.marshal(ctx).unwrap();
let (_, v) = Vec::<&str>::unmarshal(&mut UnmarshalContext {
buf: ctx.buf,
fds: ctx.fds,
byteorder: ctx.byteorder,
offset: 0,
})
.unwrap();
assert_eq!(original, v.as_slice());
ctx.buf.clear();
let mut original = std::collections::HashMap::new();
original.insert(0u64, "abc");
original.insert(1u64, "dce");
original.insert(2u64, "fgh");
original.marshal(ctx).unwrap();
let (_, map) = std::collections::HashMap::<u64, &str>::unmarshal(&mut UnmarshalContext {
buf: ctx.buf,
fds: ctx.fds,
byteorder: ctx.byteorder,
offset: 0,
})
.unwrap();
assert_eq!(original, map);
ctx.buf.clear();
let orig = (30u8, true, 100u8, -123i32);
orig.marshal(ctx).unwrap();
type ST = (u8, bool, u8, i32);
let s = ST::unmarshal(&mut UnmarshalContext {
buf: ctx.buf,
fds: ctx.fds,
byteorder: ctx.byteorder,
offset: 0,
})
.unwrap()
.1;
assert_eq!(orig, s);
ctx.buf.clear();
use crate::wire::marshal::traits::{ObjectPath, SignatureWrapper};
use crate::wire::UnixFd;
let orig_fd = UnixFd::new(nix::unistd::dup(1).unwrap());
let orig = (
ObjectPath::new("/a/b/c").unwrap(),
SignatureWrapper::new("ss(aiau)").unwrap(),
&orig_fd,
);
orig.marshal(ctx).unwrap();
assert_eq!(
ctx.buf,
&[
6, 0, 0, 0, b'/', b'a', b'/', b'b', b'/', b'c', 0, 8, b's', b's', b'(', b'a', b'i',
b'a', b'u', b')', 0, 0, 0, 0, 0, 0, 0, 0
]
);
let (_, (p, s, _fd)) =
<(ObjectPath<String>, SignatureWrapper, UnixFd) as Unmarshal>::unmarshal(
&mut UnmarshalContext {
buf: ctx.buf,
fds: ctx.fds,
byteorder: ctx.byteorder,
offset: 0,
},
)
.unwrap();
assert_eq!(p.as_ref(), "/a/b/c");
assert_eq!(s.as_ref(), "ss(aiau)");
}
#[test]
fn test_variant() {
use crate::message_builder::MarshalledMessageBody;
use crate::params::{Array, Base, Container, Dict, Param, Variant as ParamVariant};
use crate::signature::Type;
use crate::wire::marshal::traits::SignatureWrapper;
use std::collections::HashMap;
let params: [(Param, Type); 10] = [
(Base::Byte(0x41).into(), u8::signature()),
(Base::Int16(-1234).into(), i16::signature()),
(Base::Uint16(1234).into(), u16::signature()),
(Base::Int32(-1234567).into(), i32::signature()),
(Base::Uint32(1234567).into(), u32::signature()),
(Base::Int64(-1234568901234).into(), i64::signature()),
(Base::Uint64(1234568901234).into(), u64::signature()),
(
Base::String("Hello world!".to_string()).into(),
String::signature(),
),
(
Base::Signature("sy".to_string()).into(),
SignatureWrapper::signature(),
),
(Base::Boolean(true).into(), bool::signature()),
];
let mut body = MarshalledMessageBody::new();
for param in ¶ms {
let cont = Container::Variant(Box::new(ParamVariant {
sig: param.1.clone(),
value: param.0.clone(),
}));
body.push_old_param(&Param::Container(cont)).unwrap();
}
let var_vec = params
.iter()
.map(|(param, typ)| {
Param::Container(Container::Variant(Box::new(ParamVariant {
sig: typ.clone(),
value: param.clone(),
})))
})
.collect();
let vec_param = Param::Container(Container::Array(Array {
element_sig: Variant::signature(),
values: var_vec,
}));
body.push_old_param(&vec_param).unwrap();
let var_map = params
.iter()
.enumerate()
.map(|(i, (param, typ))| {
(
Base::String(format!("{}", i)),
Param::Container(Container::Variant(Box::new(ParamVariant {
sig: typ.clone(),
value: param.clone(),
}))),
)
})
.collect();
let map_param = Param::Container(Container::Dict(Dict {
key_sig: crate::signature::Base::String,
value_sig: Variant::signature(),
map: var_map,
}));
body.push_old_param(&map_param).unwrap();
let mut parser = body.parser();
assert_eq!(
0x41_u8,
parser.get::<Variant>().unwrap().get::<u8>().unwrap()
);
assert_eq!(
-1234_i16,
parser.get::<Variant>().unwrap().get::<i16>().unwrap()
);
assert_eq!(
1234_u16,
parser.get::<Variant>().unwrap().get::<u16>().unwrap()
);
assert_eq!(
-1234567_i32,
parser.get::<Variant>().unwrap().get::<i32>().unwrap()
);
assert_eq!(
1234567_u32,
parser.get::<Variant>().unwrap().get::<u32>().unwrap()
);
assert_eq!(
-1234568901234_i64,
parser.get::<Variant>().unwrap().get::<i64>().unwrap()
);
assert_eq!(
1234568901234_u64,
parser.get::<Variant>().unwrap().get::<u64>().unwrap()
);
assert_eq!(
"Hello world!",
parser.get::<Variant>().unwrap().get::<&str>().unwrap()
);
assert_eq!(
SignatureWrapper::new("sy").unwrap(),
parser.get::<Variant>().unwrap().get().unwrap()
);
assert_eq!(
true,
parser.get::<Variant>().unwrap().get::<bool>().unwrap()
);
let var_vec: Vec<Variant> = parser.get().unwrap();
assert_eq!(0x41_u8, var_vec[0].get::<u8>().unwrap());
assert_eq!(-1234_i16, var_vec[1].get::<i16>().unwrap());
assert_eq!(1234_u16, var_vec[2].get::<u16>().unwrap());
assert_eq!(-1234567_i32, var_vec[3].get::<i32>().unwrap());
assert_eq!(1234567_u32, var_vec[4].get::<u32>().unwrap());
assert_eq!(-1234568901234_i64, var_vec[5].get::<i64>().unwrap());
assert_eq!(1234568901234_u64, var_vec[6].get::<u64>().unwrap());
assert_eq!("Hello world!", var_vec[7].get::<&str>().unwrap());
assert_eq!(
SignatureWrapper::new("sy").unwrap(),
var_vec[8].get().unwrap()
);
assert_eq!(true, var_vec[9].get::<bool>().unwrap());
let var_map: HashMap<String, Variant> = parser.get().unwrap();
assert_eq!(0x41_u8, var_map["0"].get::<u8>().unwrap());
assert_eq!(-1234_i16, var_map["1"].get::<i16>().unwrap());
assert_eq!(1234_u16, var_map["2"].get::<u16>().unwrap());
assert_eq!(-1234567_i32, var_map["3"].get::<i32>().unwrap());
assert_eq!(1234567_u32, var_map["4"].get::<u32>().unwrap());
assert_eq!(-1234568901234_i64, var_map["5"].get::<i64>().unwrap());
assert_eq!(1234568901234_u64, var_map["6"].get::<u64>().unwrap());
assert_eq!("Hello world!", var_map["7"].get::<&str>().unwrap());
assert_eq!(
SignatureWrapper::new("sy").unwrap(),
var_map["8"].get().unwrap()
);
assert_eq!(true, var_map["9"].get::<bool>().unwrap());
}