tests/pass.rs
use elvwf::Wired;
fn roundtrip<'a, T>(msg: T, buf: &'a mut [u8]) -> (T, usize)
where
T: Wired<'a> + Clone + PartialEq + std::fmt::Debug,
{
let len = {
let writer = &mut &mut buf[..];
let total = writer.len();
elvwf::msg::encode_value(writer, msg.clone()).unwrap();
total - writer.len()
};
let reader = &mut &buf[..];
let value = elvwf::msg::decode_value(reader, len).unwrap();
(value, len)
}
fn assert_roundtrip<'a, T>(msg: T, buf: &'a mut [u8])
where
T: Wired<'a> + Clone + PartialEq + std::fmt::Debug,
{
let original = msg.clone();
let (decoded, _) = roundtrip(msg, buf);
assert_eq!(original, decoded);
}
#[derive(Wired)]
struct Empty;
#[test]
fn test_empty() {
assert_eq!(elvwf::msg::value_len(&Empty), 0);
}
mod scalar_tests {
use super::*;
#[derive(Wired, Clone, Debug, PartialEq)]
struct ScalarBe {
#[wf(value(format = Be))]
v: u32,
}
#[derive(Wired, Clone, Debug, PartialEq)]
struct ScalarLe {
#[wf(value(format = Le))]
v: u32,
}
#[derive(Wired, Clone, Debug, PartialEq)]
struct ScalarNe {
#[wf(value(format = Ne))]
v: u32,
}
#[derive(Wired, Clone, Debug, PartialEq)]
struct ScalarVle {
#[wf(value(format = VLE))]
v: u32,
}
#[test]
fn test_be_u32() {
let mut data = [0u8; 64];
let msg = ScalarBe { v: 0x12345678 };
let (value, len) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
assert_eq!(len, 4);
assert_eq!(&data[..4], &[0x12, 0x34, 0x56, 0x78]);
}
#[test]
fn test_le_u32() {
let mut data = [0u8; 64];
let msg = ScalarLe { v: 0x12345678 };
let (value, len) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
assert_eq!(len, 4);
assert_eq!(&data[..4], &[0x78, 0x56, 0x34, 0x12]);
}
#[test]
fn test_ne_u32() {
let mut data = [0u8; 64];
let msg = ScalarNe { v: 0x12345678 };
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_vle_small() {
let mut data = [0u8; 64];
let msg = ScalarVle { v: 0 };
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_vle_max() {
let mut data = [0u8; 64];
let msg = ScalarVle { v: u32::MAX };
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_vle_various() {
let mut data = [0u8; 64];
for v in [1u32, 127, 128, 16383, 16384, 2097151, 2097152] {
let msg = ScalarVle { v };
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
}
}
mod scalar_types {
use super::*;
#[derive(Wired, Clone, Debug, PartialEq)]
struct AllScalars {
#[wf(value(format = Be))]
a: u8,
#[wf(value(format = Be))]
b: u16,
#[wf(value(format = Be))]
c: u32,
#[wf(value(format = Be))]
d: u64,
#[wf(value(format = Le))]
e: i8,
#[wf(value(format = Le))]
f: i16,
#[wf(value(format = Le))]
g: i32,
#[wf(value(format = Le))]
h: i64,
}
#[test]
fn test_all_scalar_types() {
let mut data = [0u8; 128];
let msg = AllScalars {
a: 0xAB,
b: 0xABCD,
c: 0x12345678,
d: 0x1122334455667788,
e: -1,
f: -2,
g: -3,
h: -4,
};
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_signed_extremes() {
let mut data = [0u8; 128];
let msg = AllScalars {
a: u8::MAX,
b: u16::MAX,
c: u32::MAX,
d: u64::MAX,
e: i8::MIN,
f: i16::MIN,
g: i32::MIN,
h: i64::MIN,
};
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
}
mod slice_tests {
use super::*;
#[derive(Wired, Clone, Debug, PartialEq)]
struct PrefixedSlice<'a> {
#[wf(len(prefixed(format = Be)))]
data: &'a [u8],
}
#[derive(Wired, Clone, Debug, PartialEq)]
struct PrefixedStr<'a> {
#[wf(len(prefixed(format = Le)))]
s: &'a str,
}
#[derive(Wired, Clone, Debug, PartialEq)]
struct FixedArray<'a> {
#[wf(len(embedded))]
arr: &'a [u8; 5],
}
#[test]
fn test_prefixed_slice() {
let mut data = [0u8; 64];
let msg = PrefixedSlice {
data: &[1, 2, 3, 4, 5],
};
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_empty_slice() {
let mut data = [0u8; 64];
let msg = PrefixedSlice { data: &[] };
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_prefixed_str() {
let mut data = [0u8; 64];
let msg = PrefixedStr { s: "Hello, World!" };
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_empty_str() {
let mut data = [0u8; 64];
let msg = PrefixedStr { s: "" };
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_unicode_str() {
let mut data = [0u8; 128];
let msg = PrefixedStr {
s: "héllo 世界 🦀"
};
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_fixed_array() {
let mut data = [0u8; 64];
let msg = FixedArray {
arr: &[10, 20, 30, 40, 50],
};
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
}
mod nested_tests {
use super::*;
#[derive(Wired, Clone, Debug, PartialEq)]
struct Inner<'a> {
#[wf(value(format = Be))]
id: u32,
#[wf(len(prefixed(format = Ne)))]
name: &'a str,
}
#[derive(Wired, Clone, Debug, PartialEq)]
struct Outer<'a> {
#[wf(len(prefixed(format = Ne)))]
inner: Inner<'a>,
#[wf(value(format = Be))]
extra: u16,
}
#[test]
fn test_nested_basic() {
let mut data = [0u8; 128];
let msg = Outer {
inner: Inner {
id: 42,
name: "test",
},
extra: 0xCAFE,
};
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
}
mod header_tests {
use super::*;
#[derive(Wired, Clone, Debug, PartialEq)]
#[wf(header(dsl = "A|_:7"))]
struct OptU8 {
#[wf(opt(flag = A), value(format = Be))]
v: Option<u32>,
}
#[derive(Wired, Clone, Debug, PartialEq)]
#[wf(header(dsl = "A|B|C|D|_:4"))]
struct ManyOpts {
#[wf(opt(flag = A), value(format = Be))]
a: Option<u8>,
#[wf(opt(flag = B), value(format = Be))]
b: Option<u16>,
#[wf(opt(flag = C), value(format = Be))]
c: Option<u32>,
#[wf(opt(flag = D), value(format = Be))]
d: Option<u64>,
}
#[derive(Wired, Clone, Debug, PartialEq)]
#[wf(header(dsl = "A|_:15"))]
struct Header16 {
#[wf(opt(flag = A), value(format = Be))]
v: Option<u32>,
}
#[derive(Wired, Clone, Debug, PartialEq)]
#[wf(header(dsl = "A|_:31"))]
struct Header32 {
#[wf(opt(flag = A), value(format = Be))]
v: Option<u32>,
}
#[test]
fn test_opt_present() {
let mut data = [0u8; 64];
let msg = OptU8 { v: Some(42) };
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_opt_absent() {
let mut data = [0u8; 64];
let msg = OptU8 { v: None };
let (value, len) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
assert_eq!(len, 1);
}
#[test]
fn test_many_opts_all_present() {
let mut data = [0u8; 64];
let msg = ManyOpts {
a: Some(1),
b: Some(2),
c: Some(3),
d: Some(4),
};
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_many_opts_all_absent() {
let mut data = [0u8; 64];
let msg = ManyOpts {
a: None,
b: None,
c: None,
d: None,
};
let (value, len) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
assert_eq!(len, 1);
}
#[test]
fn test_many_opts_mixed() {
let mut data = [0u8; 64];
let msg = ManyOpts {
a: Some(1),
b: None,
c: Some(3),
d: None,
};
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_header_16bits() {
let mut data = [0u8; 64];
let msg = Header16 { v: Some(123) };
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_header_32bits() {
let mut data = [0u8; 64];
let msg = Header32 { v: Some(456) };
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
}
mod conditional_tests {
use super::*;
#[derive(Wired, Clone, Debug, PartialEq)]
#[wf(header(dsl = "A|_:7"))]
struct CondScalar {
#[wf(opt(if = 0, flag = A), value(format = Be))]
v: u32,
}
#[derive(Wired, Clone, Debug, PartialEq)]
#[wf(header(dsl = "A|_:7"))]
struct CondStr<'a> {
#[wf(opt(if = { "default" }, flag = A), len(prefixed(format = Be)))]
s: &'a str,
}
#[test]
fn test_cond_default_omits() {
let mut data = [0u8; 64];
let msg = CondScalar { v: 0 };
let (value, len) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
assert_eq!(len, 1);
}
#[test]
fn test_cond_non_default_emits() {
let mut data = [0u8; 64];
let msg = CondScalar { v: 42 };
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_cond_str_default() {
let mut data = [0u8; 64];
let msg = CondStr { s: "default" };
let (value, len) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
assert_eq!(len, 1);
}
#[test]
fn test_cond_str_other() {
let mut data = [0u8; 64];
let msg = CondStr { s: "other" };
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
}
mod full_example {
use super::*;
#[derive(Wired, Clone, Debug, PartialEq)]
#[wf(header(dsl = "S:16"))]
struct Attachment<'a> {
#[wf(len(slot = S))]
content: &'a str,
}
#[derive(Wired, Clone, Debug, PartialEq)]
#[wf(header(dsl = "A|B|C|D|E|F|_:2"))]
struct Message<'a> {
#[wf(opt(flag = A), value(format = VLE))]
pub opt_scalar: Option<u32>,
#[wf(opt(flag = B), len(prefixed(format = Ne)))]
pub opt_slice: Option<&'a str>,
#[wf(opt(flag = C), len(prefixed(format = Ne)))]
pub opt_msg: Option<Attachment<'a>>,
#[wf(value(format = Be))]
pub scalar: u64,
#[wf(len(embedded))]
pub slice: &'a [u8; 10],
#[wf(len(prefixed(format = Le)))]
pub msg: Attachment<'a>,
#[wf(opt(if = 0, flag = D), value(format = Ne))]
pub cond_scalar: u16,
#[wf(opt(if = { "hello" }, flag = E), len(prefixed(format = Le)))]
pub cond_slice: &'a str,
#[wf(opt(if = Attachment { content: "hello" }, flag = F), len(prefixed(format = VLE)))]
pub cond_msg: Attachment<'a>,
}
#[test]
fn test_full_example_all_present() {
let msg = Message {
opt_scalar: Some(2),
opt_slice: Some("AHAH"),
opt_msg: Some(Attachment { content: "hello" }),
scalar: 1208420121,
slice: &[19, 29, 39, 49, 59, 69, 79, 89, 99, 109],
msg: Attachment { content: "ICI" },
cond_scalar: 12,
cond_slice: "WORLD",
cond_msg: Attachment {
content: "biiiiiiiz",
},
};
let mut data = [0u8; 128];
let buf = &mut &mut data[..];
elvwf::msg::encode::<Message, elvwf::scalar::VLE>(buf, msg.clone()).unwrap();
let buf = &mut &data[..];
let value = elvwf::msg::decode::<Message, elvwf::scalar::VLE>(buf).unwrap();
assert_eq!(msg, value);
}
#[test]
fn test_full_example_all_defaults() {
let msg = Message {
opt_scalar: None,
opt_slice: None,
opt_msg: None,
scalar: 0,
slice: &[0; 10],
msg: Attachment { content: "" },
cond_scalar: 0,
cond_slice: "hello",
cond_msg: Attachment { content: "hello" },
};
let mut data = [0u8; 128];
let buf = &mut &mut data[..];
elvwf::msg::encode::<Message, elvwf::scalar::VLE>(buf, msg.clone()).unwrap();
let buf = &mut &data[..];
let value = elvwf::msg::decode::<Message, elvwf::scalar::VLE>(buf).unwrap();
assert_eq!(msg, value);
}
#[test]
fn test_full_example_minimal() {
let msg = Message {
opt_scalar: None,
opt_slice: None,
opt_msg: None,
scalar: 42,
slice: &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
msg: Attachment { content: "x" },
cond_scalar: 0,
cond_slice: "hello",
cond_msg: Attachment { content: "hello" },
};
let mut data = [0u8; 128];
let buf = &mut &mut data[..];
let before = buf.len();
elvwf::msg::encode::<Message, elvwf::scalar::VLE>(buf, msg.clone()).unwrap();
let encoded_len = before - buf.len();
let buf = &mut &data[..];
let value = elvwf::msg::decode::<Message, elvwf::scalar::VLE>(buf).unwrap();
assert_eq!(msg, value);
println!("Taille minimale: {} octets", encoded_len);
}
}
mod slot_tests {
use super::*;
#[derive(Wired, Clone, Debug, PartialEq)]
#[wf(header(dsl = "S:8"))]
struct Slot8<'a> {
#[wf(len(slot = S))]
content: &'a str,
}
#[derive(Wired, Clone, Debug, PartialEq)]
#[wf(header(dsl = "S:16"))]
struct Slot16<'a> {
#[wf(len(slot = S))]
content: &'a [u8],
}
#[derive(Wired, Clone, Debug, PartialEq)]
#[wf(header(dsl = "S:4|_:4"))]
struct Slot4<'a> {
#[wf(len(slot = S))]
content: &'a [u8],
}
#[derive(Wired, Clone, Debug, PartialEq)]
#[wf(header(dsl = "S:3|_:5"))]
struct Slot3<'a> {
#[wf(len(slot = S))]
content: &'a [u8],
}
#[test]
fn test_slot_8bits() {
let mut data = [0u8; 64];
let msg = Slot8 { content: "hi" };
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_slot_16bits() {
let mut data = [0u8; 1024];
let msg = Slot16 {
content: &[42; 300],
};
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_slot_empty() {
let mut data = [0u8; 64];
let msg = Slot8 { content: "" };
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_slot_8bits_max() {
let mut data = [0u8; 512];
let msg = Slot8 {
content: std::str::from_utf8(&[b'a'; 255]).unwrap(),
};
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_slot_4bits_boundary() {
let mut data = [0u8; 64];
let msg = Slot4 { content: &[7; 15] };
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_slot_3bits_all_sizes() {
let mut data = [0u8; 64];
for size in 0..=7 {
let buf: Vec<u8> = vec![0xAB; size];
let msg = Slot3 { content: &buf };
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
}
#[derive(Wired, Clone, Debug, PartialEq)]
#[wf(header(dsl = "A:8|B:8"))]
struct TwoSlots<'a> {
#[wf(len(slot = A))]
first: &'a str,
#[wf(len(slot = B))]
second: &'a [u8],
}
#[derive(Wired, Clone, Debug, PartialEq)]
#[wf(header(dsl = "A:4|B:4|C:8"))]
struct ThreeSlots<'a> {
#[wf(len(slot = A))]
a: &'a [u8],
#[wf(len(slot = B))]
b: &'a [u8],
#[wf(len(slot = C))]
c: &'a str,
}
#[derive(Wired, Clone, Debug, PartialEq)]
#[wf(header(dsl = "X:16|Y:16"))]
struct LargeSlots<'a> {
#[wf(len(slot = X))]
x: &'a [u8],
#[wf(len(slot = Y))]
y: &'a [u8],
}
#[test]
fn test_two_slots() {
let mut data = [0u8; 128];
let msg = TwoSlots {
first: "hello",
second: &[1, 2, 3, 4, 5, 6, 7, 8],
};
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_two_slots_both_empty() {
let mut data = [0u8; 64];
let msg = TwoSlots {
first: "",
second: &[],
};
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_two_slots_asymmetric() {
let mut data = [0u8; 128];
let msg = TwoSlots {
first: "",
second: &[42; 100],
};
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
let msg = TwoSlots {
first: "longer string here",
second: &[],
};
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_three_slots() {
let mut data = [0u8; 128];
let msg = ThreeSlots {
a: &[1, 2, 3],
b: &[4, 5, 6, 7, 8],
c: "trois slots ici",
};
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_three_slots_boundaries() {
let mut data = [0u8; 512];
let a_data = [0xAA; 15];
let b_data = [0xBB; 15];
let c_data = vec![b'c'; 255];
let msg = ThreeSlots {
a: &a_data,
b: &b_data,
c: std::str::from_utf8(&c_data).unwrap(),
};
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_large_slots() {
let mut data = [0u8; 4096];
let x_buf = vec![0x55; 1000];
let y_buf = vec![0xAA; 2000];
let msg = LargeSlots {
x: &x_buf,
y: &y_buf,
};
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[derive(Wired, Clone, Debug, PartialEq)]
#[wf(header(dsl = "S:8"))]
struct SlotWithScalars<'a> {
#[wf(value(format = Be))]
before: u32,
#[wf(len(slot = S))]
content: &'a [u8],
#[wf(value(format = Le))]
after: u16,
}
#[derive(Wired, Clone, Debug, PartialEq)]
#[wf(header(dsl = "A:8|F|_:7"))]
struct SlotWithFlag<'a> {
#[wf(len(slot = A))]
content: &'a [u8],
#[wf(opt(flag = F), value(format = Be))]
opt_field: Option<u32>,
}
#[test]
fn test_slot_with_scalars() {
let mut data = [0u8; 128];
let msg = SlotWithScalars {
before: 0xDEADBEEF,
content: &[1, 2, 3, 4, 5],
after: 0xCAFE,
};
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_slot_with_flag_present() {
let mut data = [0u8; 128];
let msg = SlotWithFlag {
content: &[1, 2, 3],
opt_field: Some(42),
};
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_slot_with_flag_absent() {
let mut data = [0u8; 128];
let msg = SlotWithFlag {
content: &[1, 2, 3],
opt_field: None,
};
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[derive(Wired, Clone, Debug, PartialEq)]
#[wf(header(dsl = "S:8"))]
struct InnerSlot<'a> {
#[wf(len(slot = S))]
data: &'a [u8],
}
#[derive(Wired, Clone, Debug, PartialEq)]
#[wf(header(dsl = "S:16"))]
struct OuterSlot<'a> {
#[wf(len(slot = S))]
outer_data: &'a [u8],
#[wf(len(prefixed(format = Be)))]
inner: InnerSlot<'a>,
}
#[test]
fn test_nested_slots() {
let mut data = [0u8; 256];
let msg = OuterSlot {
outer_data: &[1; 50],
inner: InnerSlot { data: &[2; 30] },
};
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
#[test]
fn test_slot_8bits_overflow() {
let mut data = [0u8; 512];
let content_buf = vec![b'a'; 256];
let msg = Slot8 {
content: std::str::from_utf8(&content_buf).unwrap(),
};
let buf = &mut &mut data[..];
let result = elvwf::msg::encode::<Slot8, elvwf::scalar::VLE>(buf, msg);
assert!(
result.is_err(),
"encoding 256 bytes dans un slot 8-bit devrait échouer"
);
}
#[test]
fn test_slot_4bits_overflow() {
let mut data = [0u8; 64];
let content = [0u8; 16];
let msg = Slot4 { content: &content };
let buf = &mut &mut data[..];
let result = elvwf::msg::encode::<Slot4, elvwf::scalar::VLE>(buf, msg);
assert!(
result.is_err(),
"encoding 16 bytes dans un slot 4-bit devrait échouer"
);
}
#[test]
fn test_slot_3bits_overflow() {
let mut data = [0u8; 64];
let content = [0u8; 8];
let msg = Slot3 { content: &content };
let buf = &mut &mut data[..];
let result = elvwf::msg::encode::<Slot3, elvwf::scalar::VLE>(buf, msg);
assert!(
result.is_err(),
"encoding 8 bytes dans un slot 3-bit devrait échouer"
);
}
#[test]
fn test_slot_16bits_overflow() {
let mut data = vec![0u8; 70_000];
let content = vec![0u8; 65_536];
let msg = Slot16 { content: &content };
let buf = &mut &mut data[..];
let result = elvwf::msg::encode::<Slot16, elvwf::scalar::VLE>(buf, msg);
assert!(
result.is_err(),
"encoding 65536 bytes dans un slot 16-bit devrait échouer"
);
}
#[test]
fn test_multi_slot_one_overflows() {
let mut data = [0u8; 512];
let content_buf = vec![b'x'; 256];
let msg = TwoSlots {
first: std::str::from_utf8(&content_buf).unwrap(),
second: &[1, 2, 3],
};
let buf = &mut &mut data[..];
let result = elvwf::msg::encode::<TwoSlots, elvwf::scalar::VLE>(buf, msg);
assert!(result.is_err());
let big = vec![0u8; 256];
let msg = TwoSlots {
first: "ok",
second: &big,
};
let buf = &mut &mut data[..];
let result = elvwf::msg::encode::<TwoSlots, elvwf::scalar::VLE>(buf, msg);
assert!(result.is_err());
}
#[test]
fn test_slot_at_boundary_no_overflow() {
let mut data = [0u8; 512];
let content_buf = vec![b'a'; 255];
let msg = Slot8 {
content: std::str::from_utf8(&content_buf).unwrap(),
};
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
let content = [0u8; 15];
let msg = Slot4 { content: &content };
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
let content = [0u8; 7];
let msg = Slot3 { content: &content };
let (value, _) = roundtrip(msg.clone(), &mut data);
assert_eq!(msg, value);
}
}
mod error_tests {
use super::*;
#[derive(Wired, Clone, Debug, PartialEq)]
struct BigMsg {
#[wf(value(format = Be))]
v: u64,
}
#[test]
fn test_encode_buffer_too_small() {
let mut data = [0u8; 4];
let buf = &mut &mut data[..];
let result = elvwf::msg::encode::<BigMsg, elvwf::scalar::VLE>(buf, BigMsg { v: 42 });
assert!(result.is_err());
}
#[test]
fn test_decode_buffer_too_small() {
let data = [0u8; 4];
let buf = &mut &data[..];
let result = elvwf::msg::decode::<BigMsg, elvwf::scalar::VLE>(buf);
assert!(result.is_err());
}
#[derive(Wired, Clone, Debug, PartialEq)]
struct StrMsg<'a> {
#[wf(len(prefixed(format = Be)))]
s: &'a str,
}
#[test]
fn test_decode_truncated_str() {
let data = [0, 0, 0, 100, b'h', b'i'];
let buf = &mut &data[..];
let result = elvwf::msg::decode::<StrMsg, elvwf::scalar::VLE>(buf);
assert!(result.is_err());
}
}
#[derive(Wired, Clone, PartialEq, Debug)]
#[wf(header(dsl = "_:8"))]
struct BasicRemaining<'a> {
#[wf(value(format = Be))]
v: u8,
#[wf(len(remaining))]
p: &'a [u8],
}
#[test]
fn basic_remaining_non_empty() {
let mut buf = [0u8; 64];
assert_roundtrip(
BasicRemaining {
v: 1,
p: &[2, 3, 4],
},
&mut buf,
);
}
#[test]
fn basic_remaining_empty() {
let mut buf = [0u8; 64];
assert_roundtrip(BasicRemaining { v: 42, p: &[] }, &mut buf);
}
#[test]
fn basic_remaining_single_byte() {
let mut buf = [0u8; 64];
assert_roundtrip(BasicRemaining { v: 0, p: &[0xFF] }, &mut buf);
}
#[test]
fn basic_remaining_large() {
let big: Vec<u8> = (0..200).map(|i| i as u8).collect();
let mut buf = [0u8; 256];
assert_roundtrip(BasicRemaining { v: 7, p: &big }, &mut buf);
}
#[test]
fn basic_remaining_encoded_size() {
let mut buf = [0u8; 64];
let msg = BasicRemaining {
v: 1,
p: &[2, 3, 4],
};
let (_, len) = roundtrip(msg, &mut buf);
assert_eq!(len, 5);
}
#[derive(Wired, Clone, PartialEq, Debug)]
#[wf(header(dsl = "_:8"))]
struct RemainingStr<'a> {
#[wf(value(format = Be))]
code: u16,
#[wf(len(remaining))]
text: &'a str,
}
#[test]
fn remaining_str_basic() {
let mut buf = [0u8; 64];
assert_roundtrip(
RemainingStr {
code: 0xABCD,
text: "Hello, world!",
},
&mut buf,
);
}
#[test]
fn remaining_str_empty() {
let mut buf = [0u8; 64];
assert_roundtrip(RemainingStr { code: 0, text: "" }, &mut buf);
}
#[test]
fn remaining_str_unicode() {
let mut buf = [0u8; 64];
assert_roundtrip(
RemainingStr {
code: 1,
text: "héllo 🌍 café",
},
&mut buf,
);
}
#[derive(Wired, Clone, PartialEq, Debug)]
#[wf(header(dsl = "_:8"))]
struct MultiPrefix<'a> {
#[wf(value(format = Be))]
a: u8,
#[wf(value(format = Be))]
b: u16,
#[wf(value(format = Le))]
c: u32,
#[wf(len(remaining))]
rest: &'a [u8],
}
#[test]
fn multi_prefix_remaining() {
let mut buf = [0u8; 64];
assert_roundtrip(
MultiPrefix {
a: 1,
b: 0x0203,
c: 0xDEADBEEF,
rest: &[10, 20, 30, 40, 50],
},
&mut buf,
);
}
#[test]
fn multi_prefix_remaining_empty() {
let mut buf = [0u8; 64];
assert_roundtrip(
MultiPrefix {
a: 0,
b: 0,
c: 0,
rest: &[],
},
&mut buf,
);
}
#[derive(Wired, Clone, PartialEq, Debug)]
struct NoHeaderRemaining<'a> {
#[wf(value(format = Be))]
tag: u8,
#[wf(len(remaining))]
payload: &'a [u8],
}
#[test]
fn no_header_remaining() {
let mut buf = [0u8; 64];
assert_roundtrip(
NoHeaderRemaining {
tag: 9,
payload: &[1, 2, 3, 4, 5],
},
&mut buf,
);
}
#[test]
fn no_header_remaining_empty() {
let mut buf = [0u8; 64];
assert_roundtrip(
NoHeaderRemaining {
tag: 0,
payload: &[],
},
&mut buf,
);
}
#[derive(Wired, Clone, PartialEq, Debug)]
#[wf(header(dsl = "_:8"))]
struct InnerRemaining<'a> {
#[wf(value(format = Be))]
kind: u8,
#[wf(len(remaining))]
blob: &'a [u8],
}
#[derive(Wired, Clone, PartialEq, Debug)]
#[wf(header(dsl = "S:16"))]
struct OuterWithInner<'a> {
#[wf(value(format = Be))]
id: u32,
#[wf(len(slot = S))]
inner: InnerRemaining<'a>,
}
#[test]
fn nested_remaining_inside_prefixed_message() {
let mut buf = [0u8; 128];
assert_roundtrip(
OuterWithInner {
id: 0xCAFEBABE,
inner: InnerRemaining {
kind: 3,
blob: &[100, 101, 102, 103],
},
},
&mut buf,
);
}
#[test]
fn nested_remaining_inside_prefixed_message_empty_blob() {
let mut buf = [0u8; 128];
assert_roundtrip(
OuterWithInner {
id: 1,
inner: InnerRemaining { kind: 0, blob: &[] },
},
&mut buf,
);
}
#[derive(Wired, Clone, PartialEq, Debug)]
#[wf(header(dsl = "_:8"))]
struct L1<'a> {
#[wf(value(format = Be))]
x: u8,
#[wf(len(remaining))]
tail: &'a [u8],
}
#[derive(Wired, Clone, PartialEq, Debug)]
#[wf(header(dsl = "S:8|_:8"))]
struct L2<'a> {
#[wf(value(format = Be))]
y: u8,
#[wf(len(slot = S))]
l1: L1<'a>,
}
#[derive(Wired, Clone, PartialEq, Debug)]
#[wf(header(dsl = "S:16"))]
struct L3<'a> {
#[wf(value(format = Be))]
z: u16,
#[wf(len(slot = S))]
l2: L2<'a>,
}
#[test]
fn triple_nested_remaining() {
let mut buf = [0u8; 128];
assert_roundtrip(
L3 {
z: 0x1234,
l2: L2 {
y: 7,
l1: L1 {
x: 9,
tail: &[1, 2, 3, 4, 5, 6],
},
},
},
&mut buf,
);
}
#[test]
fn triple_nested_remaining_empty_tail() {
let mut buf = [0u8; 128];
assert_roundtrip(
L3 {
z: 0,
l2: L2 {
y: 0,
l1: L1 { x: 0, tail: &[] },
},
},
&mut buf,
);
}
#[derive(Wired, Clone, PartialEq, Debug)]
#[wf(header(dsl = "S:8|_:8"))]
struct RootWithRemainingAndInner<'a> {
#[wf(value(format = Be))]
hdr: u8,
#[wf(len(slot = S))]
inner: InnerRemaining<'a>,
#[wf(len(remaining))]
outer_tail: &'a [u8],
}
#[test]
fn remaining_at_two_levels() {
let mut buf = [0u8; 128];
assert_roundtrip(
RootWithRemainingAndInner {
hdr: 1,
inner: InnerRemaining {
kind: 42,
blob: &[7, 8, 9],
},
outer_tail: &[100, 101, 102, 103, 104],
},
&mut buf,
);
}
#[test]
fn remaining_at_two_levels_inner_empty() {
let mut buf = [0u8; 128];
assert_roundtrip(
RootWithRemainingAndInner {
hdr: 2,
inner: InnerRemaining { kind: 0, blob: &[] },
outer_tail: &[1, 2, 3],
},
&mut buf,
);
}
#[test]
fn remaining_at_two_levels_outer_empty() {
let mut buf = [0u8; 128];
assert_roundtrip(
RootWithRemainingAndInner {
hdr: 3,
inner: InnerRemaining {
kind: 5,
blob: &[1, 2, 3],
},
outer_tail: &[],
},
&mut buf,
);
}
#[test]
fn remaining_at_two_levels_both_empty() {
let mut buf = [0u8; 128];
assert_roundtrip(
RootWithRemainingAndInner {
hdr: 0,
inner: InnerRemaining { kind: 0, blob: &[] },
outer_tail: &[],
},
&mut buf,
);
}
#[derive(Wired, Clone, PartialEq, Debug)]
#[wf(header(dsl = "F:1|_:7"))]
struct OptionalThenRemaining<'a> {
#[wf(opt(flag = F), value(format = Be))]
maybe: Option<u32>,
#[wf(len(remaining))]
tail: &'a [u8],
}
#[test]
fn optional_present_then_remaining() {
let mut buf = [0u8; 64];
assert_roundtrip(
OptionalThenRemaining {
maybe: Some(0xDEADBEEF),
tail: &[1, 2, 3],
},
&mut buf,
);
}
#[test]
fn optional_absent_then_remaining() {
let mut buf = [0u8; 64];
assert_roundtrip(
OptionalThenRemaining {
maybe: None,
tail: &[1, 2, 3, 4, 5, 6, 7, 8],
},
&mut buf,
);
}
#[test]
fn optional_absent_then_remaining_empty() {
let mut buf = [0u8; 64];
assert_roundtrip(
OptionalThenRemaining {
maybe: None,
tail: &[],
},
&mut buf,
);
}
#[test]
fn encoded_len_equals_fixed_plus_remaining() {
let mut buf = [0u8; 64];
let payload: &[u8] = &[10, 20, 30, 40, 50, 60];
let msg = BasicRemaining { v: 99, p: payload };
let (_, len) = roundtrip(msg, &mut buf);
assert_eq!(len, 1 + 1 + payload.len());
}
#[test]
fn nested_remaining_length_consistency() {
let mut buf_inner = [0u8; 64];
let inner = InnerRemaining {
kind: 1,
blob: &[1, 2, 3, 4],
};
let (_, inner_len) = roundtrip(inner.clone(), &mut buf_inner);
let mut buf_outer = [0u8; 128];
let outer = OuterWithInner {
id: 0x11223344,
inner,
};
let (_, outer_len) = roundtrip(outer, &mut buf_outer);
assert_eq!(outer_len, 4 + 2 + inner_len);
}