use bytes::Bytes;
pub(crate) fn encode_delayed_member(name: &str, payload: &[u8]) -> Bytes {
let name_bytes = name.as_bytes();
let mut out = Vec::with_capacity(4 + name_bytes.len() + payload.len());
out.extend_from_slice(&(name_bytes.len() as u32).to_le_bytes());
out.extend_from_slice(name_bytes);
out.extend_from_slice(payload);
Bytes::from(out)
}
#[allow(dead_code)]
pub(crate) fn decode_delayed_member(member: &[u8]) -> Option<(String, &[u8])> {
if member.len() < 4 {
return None;
}
let name_len = u32::from_le_bytes([member[0], member[1], member[2], member[3]]) as usize;
if member.len() < 4 + name_len {
return None;
}
let name = std::str::from_utf8(&member[4..4 + name_len])
.ok()?
.to_string();
let payload = &member[4 + name_len..];
Some((name, payload))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn encode_then_decode_round_trips_named() {
let payload = b"\x91\x01"; let member = encode_delayed_member("send-email", payload);
let (name, rest) = decode_delayed_member(&member).expect("decode");
assert_eq!(name, "send-email");
assert_eq!(rest, payload);
}
#[test]
fn encode_then_decode_round_trips_empty_name() {
let payload = b"opaque-body";
let member = encode_delayed_member("", payload);
let (name, rest) = decode_delayed_member(&member).expect("decode");
assert_eq!(name, "");
assert_eq!(rest, payload);
assert_eq!(&member[..4], &[0u8, 0, 0, 0]);
assert_eq!(&member[4..], payload);
}
#[test]
fn encode_layout_is_le_u32_prefix_plus_name_plus_payload() {
let member = encode_delayed_member("ab", b"XY");
assert_eq!(&member[..4], &[2u8, 0, 0, 0]);
assert_eq!(&member[4..6], b"ab");
assert_eq!(&member[6..], b"XY");
}
#[test]
fn decode_short_input_returns_none() {
assert!(decode_delayed_member(b"").is_none());
assert!(decode_delayed_member(b"\x00\x00\x00").is_none());
}
#[test]
fn decode_truncated_name_returns_none() {
let bad = [10u8, 0, 0, 0, b'a', b'b'];
assert!(decode_delayed_member(&bad).is_none());
}
#[test]
fn decode_legacy_msgpack_member_returns_none() {
let legacy: &[u8] = &[0x95, 0xa3, b'x', b'y', b'z']; assert!(decode_delayed_member(legacy).is_none());
}
#[test]
fn decode_unicode_name_round_trips() {
let member = encode_delayed_member("発送-email", b"body");
let (name, rest) = decode_delayed_member(&member).expect("decode");
assert_eq!(name, "発送-email");
assert_eq!(rest, b"body");
}
}