use crate::typed_bytes::ByteArray;
use std::marker::PhantomData;
use std::num::NonZeroUsize;
#[derive(Clone)]
pub struct ByteBuilder<T> {
buffer: Vec<u8>,
phantom: PhantomData<T>,
expected: Option<NonZeroUsize>,
}
impl<T> From<ByteBuilder<T>> for Vec<u8> {
fn from(bb: ByteBuilder<T>) -> Vec<u8> {
bb.buffer
}
}
impl<T> ByteBuilder<T> {
pub fn new() -> Self {
ByteBuilder {
buffer: Vec::new(),
phantom: PhantomData,
expected: None,
}
}
pub fn new_fixed(size: NonZeroUsize) -> Self {
ByteBuilder {
buffer: Vec::with_capacity(size.get()),
phantom: PhantomData,
expected: Some(size),
}
}
pub fn u8(self, v: u8) -> Self {
let mut buf = self.buffer;
buf.push(v);
ByteBuilder {
buffer: buf,
phantom: self.phantom,
expected: self.expected,
}
}
pub fn bytes(self, v: &[u8]) -> Self {
let mut buf = self.buffer;
buf.extend_from_slice(v);
ByteBuilder {
buffer: buf,
phantom: self.phantom,
expected: self.expected,
}
}
pub fn fold<F, I>(self, l: I, f: F) -> Self
where
I: Iterator,
F: FnMut(Self, I::Item) -> Self,
{
l.fold(self, f)
}
pub fn iter8<F, I>(self, l: I, f: F) -> Self
where
I: Iterator + ExactSizeIterator,
F: FnMut(Self, I::Item) -> Self,
{
assert!(l.len() < 256);
let bb = self.u8(l.len() as u8);
l.fold(bb, f)
}
pub fn iter16<F, I>(self, l: I, f: F) -> Self
where
I: Iterator + ExactSizeIterator,
F: FnMut(Self, I::Item) -> Self,
{
assert!(l.len() < 65536);
let bb = self.u16(l.len() as u16);
l.fold(bb, f)
}
#[allow(clippy::should_implement_trait)]
pub fn sub<F, U>(self, f: F) -> Self
where
F: Fn(ByteBuilder<U>) -> ByteBuilder<U>,
{
let res = f(ByteBuilder {
buffer: self.buffer,
phantom: PhantomData,
expected: None,
});
ByteBuilder {
buffer: res.buffer,
phantom: self.phantom,
expected: self.expected,
}
}
pub fn u16(self, v: u16) -> Self {
self.bytes(&v.to_be_bytes())
}
pub fn u32(self, v: u32) -> Self {
self.bytes(&v.to_be_bytes())
}
pub fn u64(self, v: u64) -> Self {
self.bytes(&v.to_be_bytes())
}
pub fn u128(self, v: u128) -> Self {
self.bytes(&v.to_be_bytes())
}
pub fn finalize(self) -> ByteArray<T> {
match self.expected {
None => ByteArray::from_vec(self.buffer),
Some(expected_sz) => {
if expected_sz.get() == self.buffer.len() {
ByteArray::from_vec(self.buffer)
} else {
panic!(
"internal-error: bytebuilder: expected size {} but got {}",
expected_sz.get(),
self.buffer.len()
)
}
}
}
}
pub fn finalize_as_vec(self) -> Vec<u8> {
self.buffer
}
}
impl<T> Default for ByteBuilder<T> {
fn default() -> Self {
Self::new()
}
}