use alloc::vec::Vec;
use crate::parse::UInt;
#[derive(Debug)]
pub struct Writer<'a>(&'a mut Vec<u8>);
impl<'a> Writer<'a> {
pub fn new(buffer: &'a mut Vec<u8>) -> Self {
Self(buffer)
}
pub fn uleb128<T: UInt>(&mut self, value: T) {
let mut remaining = value;
while {
let byte = remaining.little();
remaining >>= 7;
let more = remaining != T::ZERO;
self.u8(if more { byte | 0x80 } else { byte & !0x80 });
more
} {}
}
pub fn u8(&mut self, byte: u8) {
self.0.push(byte);
}
pub fn u16(&mut self, int: u16) {
self.bytes(int.to_le_bytes());
}
pub fn u32(&mut self, int: u32) {
self.bytes(int.to_le_bytes());
}
pub fn u64(&mut self, int: u64) {
self.bytes(int.to_le_bytes());
}
pub fn u128(&mut self, int: u128) {
self.bytes(int.to_le_bytes());
}
pub fn str(&mut self, string: impl AsRef<str>) {
self.bytes(string.as_ref().as_bytes())
}
pub fn bytes(&mut self, bytes: impl AsRef<[u8]>) {
self.0.extend(bytes.as_ref())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{parse::Reader, wasm::Read as _};
#[test]
fn roundtrip() {
let mut buffer = Vec::new();
let mut writer = Writer::new(&mut buffer);
for i in (0..=u32::from(u16::MAX))
.chain((u32::MAX - u32::from(u16::MAX))..=u32::MAX)
{
writer.uleb128(i);
assert!(writer.0.len() < 7);
let mut reader = Reader::new(&writer.0[..]);
let j = reader.integer().unwrap();
assert_eq!(i, j);
assert!(reader.end().is_some());
writer.0.clear();
}
for i in (u64::from(u32::MAX) + 1)
..(u64::from(u32::MAX) + u64::from(u16::MAX))
{
writer.uleb128(i);
let mut reader = Reader::new(&writer.0[..]);
let decoded = reader.integer();
assert!(decoded.is_none(), "{i} decoded is {decoded:?}");
writer.0.clear();
}
}
}