use super::Serializable;
pub trait ByteWriter: Sized {
fn write_u8(&mut self, value: u8);
fn write_bytes(&mut self, values: &[u8]);
fn write_bool(&mut self, val: bool) {
self.write_u8(val as u8);
}
fn write_u16(&mut self, value: u16) {
self.write_bytes(&value.to_le_bytes());
}
fn write_u32(&mut self, value: u32) {
self.write_bytes(&value.to_le_bytes());
}
fn write_u64(&mut self, value: u64) {
self.write_bytes(&value.to_le_bytes());
}
fn write_u128(&mut self, value: u128) {
self.write_bytes(&value.to_le_bytes());
}
fn write_usize(&mut self, value: usize) {
let value = value as u64;
let length = usize_encoded_len(value);
if length == 9 {
self.write_u8(0);
self.write(value.to_le_bytes());
} else {
let encoded_bytes = (((value << 1) | 1) << (length - 1)).to_le_bytes();
self.write_bytes(&encoded_bytes[..length]);
}
}
fn write<S: Serializable>(&mut self, value: S) {
value.write_into(self)
}
fn write_many<S, T>(&mut self, elements: T)
where
T: IntoIterator<Item = S>,
S: Serializable,
{
for element in elements {
element.write_into(self);
}
}
}
#[cfg(feature = "std")]
impl<W: std::io::Write> ByteWriter for W {
#[inline(always)]
fn write_u8(&mut self, byte: u8) {
<W as std::io::Write>::write_all(self, &[byte]).expect("write failed")
}
#[inline(always)]
fn write_bytes(&mut self, bytes: &[u8]) {
<W as std::io::Write>::write_all(self, bytes).expect("write failed")
}
}
#[cfg(not(feature = "std"))]
impl ByteWriter for alloc::vec::Vec<u8> {
fn write_u8(&mut self, value: u8) {
self.push(value);
}
fn write_bytes(&mut self, values: &[u8]) {
self.extend_from_slice(values);
}
}
pub(super) fn usize_encoded_len(value: u64) -> usize {
let zeros = value.leading_zeros() as usize;
let len = zeros.saturating_sub(1) / 7;
9 - core::cmp::min(len, 8)
}
#[cfg(all(test, feature = "std"))]
mod tests {
use std::io::Cursor;
use super::*;
#[test]
fn write_adapter_passthrough() {
let mut writer = Cursor::new([0u8; 128]);
writer.write_bytes(b"nope");
let buf = writer.get_ref();
assert_eq!(&buf[..4], b"nope");
}
#[test]
#[should_panic]
fn write_adapter_writer_out_of_capacity() {
let mut writer = Cursor::new([0; 2]);
writer.write_bytes(b"nope");
}
}