pub(crate) fn write_varint(mut value: u64, out: &mut Vec<u8>) {
loop {
let byte = (value & 0x7f) as u8;
value >>= 7;
if value == 0 {
out.push(byte);
return;
}
out.push(byte | 0x80);
}
}
fn write_key(number: u32, wire_type: u8, out: &mut Vec<u8>) {
write_varint((u64::from(number) << 3) | u64::from(wire_type), out);
}
pub(crate) fn write_i32_field(number: u32, value: i32, out: &mut Vec<u8>) {
write_key(number, 0, out);
write_varint(i64::from(value) as u64, out);
}
pub(crate) fn write_bytes_field(number: u32, payload: &[u8], out: &mut Vec<u8>) {
write_key(number, 2, out);
write_varint(payload.len() as u64, out);
out.extend_from_slice(payload);
}
pub(crate) fn write_string_field(number: u32, value: &str, out: &mut Vec<u8>) {
write_bytes_field(number, value.as_bytes(), out);
}
pub(crate) fn write_packed_i32_field(number: u32, values: &[i32], out: &mut Vec<u8>) {
let mut payload = Vec::with_capacity(values.len() * 2);
for &value in values {
write_varint(i64::from(value) as u64, &mut payload);
}
write_bytes_field(number, &payload, out);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn varint_matches_the_spec_examples() {
let cases: [(u64, &[u8]); 4] = [
(0, &[0x00]),
(1, &[0x01]),
(127, &[0x7f]),
(300, &[0xac, 0x02]),
];
for (value, expected) in cases {
let mut out = Vec::new();
write_varint(value, &mut out);
assert_eq!(out, expected, "varint {value}");
}
}
#[test]
fn negative_int32_is_sign_extended_to_ten_bytes() {
let mut out = Vec::new();
write_i32_field(12, -5, &mut out);
assert_eq!(out.len(), 1 + 10, "key byte + ten varint bytes");
}
#[test]
fn packed_repeated_is_one_length_delimited_field() {
let mut out = Vec::new();
write_packed_i32_field(26, &[10_000, 20_000], &mut out);
assert_eq!(
out,
vec![
0xd2, 0x01, 0x05, 0x90, 0x4e, 0xa0, 0x9c, 0x01, ]
);
}
}