use crate::{BodyBuf, Endianness, Result, Signature, Variant, ty};
#[test]
fn dict_array_padding() -> Result<()> {
let mut buf = BodyBuf::with_endianness(Endianness::LITTLE);
let mut dict = buf.store_array::<ty::Dict<ty::Str, ty::Variant>>()?;
dict.store_entry()
.store("a")
.store(Variant::U32(1))
.finish();
dict.finish();
assert_eq!(buf.signature(), "a{sv}");
#[rustfmt::skip]
assert_eq!(buf.get(), &[
16, 0, 0, 0,
0, 0, 0, 0,
1, 0, 0, 0, b'a', 0,
1, b'u', 0,
0, 0, 0, 1, 0, 0, 0,
]);
Ok(())
}
#[test]
fn empty_dict_array_padding() -> Result<()> {
let mut buf = BodyBuf::with_endianness(Endianness::LITTLE);
buf.store_array::<ty::Dict<ty::Str, ty::Variant>>()?
.finish();
buf.store(42u8)?;
assert_eq!(buf.signature(), "a{sv}y");
assert_eq!(buf.get(), &[0, 0, 0, 0, 0, 0, 0, 0, 42]);
Ok(())
}
#[test]
fn no_trailing_array_padding() -> Result<()> {
let mut buf = BodyBuf::with_endianness(Endianness::LITTLE);
let mut array = buf.store_array::<u64>()?;
array.store(1u64);
array.finish();
buf.store(2u8)?;
assert_eq!(buf.signature(), "aty");
#[rustfmt::skip]
assert_eq!(buf.get(), &[
8, 0, 0, 0,
0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
2,
]);
Ok(())
}
#[test]
fn array_of_structs() -> Result<()> {
let mut buf = BodyBuf::new();
let mut array = buf.store_array::<(i32, i32, ty::Array<u8>)>()?;
for n in [1i32, 2i32] {
array
.store_struct()
.store(n)
.store(n)
.store_array(|w| w.write_slice(&[n as u8; 3]))
.finish();
}
array.finish();
assert_eq!(buf.signature(), "a(iiay)");
let mut buf = buf.as_body();
let mut array = buf.load_array::<(i32, i32, ty::Array<u8>)>()?;
for n in [1i32, 2i32] {
let Some((a, b, mut bytes)) = array.load_struct()? else {
panic!("Missing element {n}");
};
assert_eq!(a, n);
assert_eq!(b, n);
assert_eq!(bytes.load()?, Some(n as u8));
assert_eq!(bytes.load()?, Some(n as u8));
assert_eq!(bytes.load()?, Some(n as u8));
assert_eq!(bytes.load()?, None);
}
assert!(array.load_struct()?.is_none());
Ok(())
}
#[test]
fn nested_variants() -> Result<()> {
const INNER: &Signature = Signature::new_const(b"a{sv}");
let mut buf = BodyBuf::new();
buf.store(1u8)?;
let mut outer = buf
.store_variant(INNER)?
.store_array::<ty::Dict<ty::Str, ty::Variant>>();
outer
.store_entry()
.store("inner")
.store_variant(INNER, |w| {
let mut inner = w.store_array::<ty::Dict<ty::Str, ty::Variant>>();
inner
.store_entry()
.store("value")
.store(Variant::String("Hello World!"))
.finish();
})
.finish();
outer.finish();
buf.store(2u8)?;
assert_eq!(buf.signature(), "yvy");
let mut buf = buf.as_body();
assert_eq!(buf.load::<u8>()?, 1);
assert_eq!(buf.skip_variant()?, INNER);
assert_eq!(buf.load::<u8>()?, 2);
assert!(buf.is_empty());
Ok(())
}
#[test]
fn nested_variants_round_trip() -> Result<()> {
const INNER: &Signature = Signature::new_const(b"a{sv}");
let mut buf = BodyBuf::new();
let mut outer = buf.store_array::<ty::Dict<ty::Str, ty::Variant>>()?;
outer
.store_entry()
.store("inner")
.store_variant(INNER, |w| {
let mut inner = w.store_array::<ty::Dict<ty::Str, ty::Variant>>();
inner
.store_entry()
.store("value")
.store(Variant::String("Hello World!"))
.finish();
inner
.store_entry()
.store("n")
.store(Variant::I32(-1))
.finish();
})
.finish();
outer.finish();
assert_eq!(buf.signature(), "a{sv}");
let mut buf = buf.as_body();
let mut outer = buf.load_array::<ty::Dict<ty::Str, ty::Variant>>()?;
let Some((key, mut value)) =
outer.load_entry_as::<ty::Array<ty::Dict<ty::Str, ty::Variant>>>()?
else {
panic!("Missing entry");
};
assert_eq!(key, "inner");
assert_eq!(
value.load_entry()?,
Some(("value", Variant::String("Hello World!")))
);
assert_eq!(value.load_entry()?, Some(("n", Variant::I32(-1))));
assert_eq!(value.load_entry()?, None);
Ok(())
}