use super::varint::{decode_varint, encode_varint};
use super::WireError;
use prost::alloc::vec::Vec;
pub fn encode_length_delimited(data: &[u8], buf: &mut Vec<u8>) {
encode_varint(data.len() as u64, buf);
buf.extend_from_slice(data);
}
pub fn decode_length_delimited(buf: &[u8]) -> Result<(&[u8], usize), WireError> {
let (length, prefix_len) = decode_varint(buf)?;
let length = length as usize;
let remaining = &buf[prefix_len..];
if remaining.len() < length {
return Err(WireError::TruncatedMessage {
declared: length,
available: remaining.len(),
});
}
Ok((&remaining[..length], prefix_len + length))
}
pub fn encode_string(s: &str, buf: &mut Vec<u8>) {
encode_length_delimited(s.as_bytes(), buf);
}
pub fn decode_string(buf: &[u8]) -> Result<(&str, usize), WireError> {
let (payload, consumed) = decode_length_delimited(buf)?;
let s = core::str::from_utf8(payload).map_err(WireError::InvalidUtf8)?;
Ok((s, consumed))
}
pub fn encoded_len_length_delimited(data_len: usize) -> usize {
super::varint::encoded_len_varint(data_len as u64) + data_len
}
#[cfg(test)]
mod tests {
use super::*;
use prost::alloc::vec;
#[test]
fn encode_decode_empty() {
let mut buf = Vec::new();
encode_length_delimited(b"", &mut buf);
assert_eq!(buf, &[0]); let (payload, consumed) = decode_length_delimited(&buf).expect("decode");
assert!(payload.is_empty());
assert_eq!(consumed, 1);
}
#[test]
fn encode_decode_hello() {
let mut buf = Vec::new();
encode_length_delimited(b"hello", &mut buf);
assert_eq!(buf.len(), 6); let (payload, consumed) = decode_length_delimited(&buf).expect("decode");
assert_eq!(payload, b"hello");
assert_eq!(consumed, 6);
}
#[test]
fn encode_decode_large() {
let data = vec![0xABu8; 300];
let mut buf = Vec::new();
encode_length_delimited(&data, &mut buf);
assert_eq!(buf.len(), 2 + 300);
let (payload, consumed) = decode_length_delimited(&buf).expect("decode");
assert_eq!(payload, &data[..]);
assert_eq!(consumed, 302);
}
#[test]
fn decode_truncated_returns_error() {
let buf = [10, 0x01, 0x02, 0x03];
assert!(matches!(
decode_length_delimited(&buf),
Err(WireError::TruncatedMessage {
declared: 10,
available: 3,
})
));
}
#[test]
fn decode_empty_buf_returns_eof() {
assert!(matches!(
decode_length_delimited(&[]),
Err(WireError::UnexpectedEof)
));
}
#[test]
fn encode_decode_string() {
let mut buf = Vec::new();
encode_string("world", &mut buf);
let (s, consumed) = decode_string(&buf).expect("decode");
assert_eq!(s, "world");
assert_eq!(consumed, 6);
}
#[test]
fn decode_string_invalid_utf8() {
let mut buf = Vec::new();
encode_length_delimited(&[0xFF, 0xFE], &mut buf);
assert!(matches!(
decode_string(&buf),
Err(WireError::InvalidUtf8(_))
));
}
#[test]
fn encoded_len_calculation() {
assert_eq!(encoded_len_length_delimited(0), 1); assert_eq!(encoded_len_length_delimited(5), 6); assert_eq!(encoded_len_length_delimited(127), 128); assert_eq!(encoded_len_length_delimited(128), 130); }
}