use crate::error::{Error, Result};
pub fn fill_random(buf: &mut [u8]) {
use rand_core::{OsRng, RngCore};
OsRng.fill_bytes(buf);
}
#[must_use]
pub fn random_16() -> [u8; 16] {
let mut b = [0u8; 16];
fill_random(&mut b);
b
}
#[must_use]
pub fn blake2b_256(data: &[u8]) -> [u8; 32] {
use blake2::digest::{Digest, consts::U32};
let mut h = blake2::Blake2b::<U32>::new();
h.update(data);
let out = h.finalize();
let mut r = [0u8; 32];
r.copy_from_slice(&out);
r
}
pub fn blake2b_256_reader<R: std::io::Read>(mut r: R) -> std::io::Result<[u8; 32]> {
use blake2::digest::{Digest, consts::U32};
let mut h = blake2::Blake2b::<U32>::new();
let mut buf = vec![0u8; 1 << 20];
loop {
let n = r.read(&mut buf)?;
if n == 0 {
break;
}
h.update(buf.get(..n).unwrap_or(&[]));
}
Ok(h.finalize().into())
}
pub struct Cursor<'a> {
data: &'a [u8],
pos: usize,
context: &'static str,
}
impl<'a> Cursor<'a> {
#[must_use]
pub const fn new(data: &'a [u8], context: &'static str) -> Self {
Self { data, pos: 0, context }
}
#[must_use]
pub const fn position(&self) -> usize {
self.pos
}
#[must_use]
pub const fn remaining(&self) -> usize {
self.data.len().saturating_sub(self.pos)
}
pub fn skip(&mut self, n: usize) -> Result<()> {
self.take(n).map(|_| ())
}
pub fn take(&mut self, n: usize) -> Result<&'a [u8]> {
let end = self.pos.checked_add(n).ok_or(Error::Truncated {
context: self.context,
need: n,
got: self.remaining(),
})?;
let s = self.data.get(self.pos..end).ok_or(Error::Truncated {
context: self.context,
need: n,
got: self.remaining(),
})?;
self.pos = end;
Ok(s)
}
pub fn take_array<const N: usize>(&mut self) -> Result<[u8; N]> {
let s = self.take(N)?;
let mut a = [0u8; N];
a.copy_from_slice(s);
Ok(a)
}
pub fn u8(&mut self) -> Result<u8> {
Ok(self.take_array::<1>()?[0])
}
pub fn u16le(&mut self) -> Result<u16> {
Ok(u16::from_le_bytes(self.take_array::<2>()?))
}
pub fn u32le(&mut self) -> Result<u32> {
Ok(u32::from_le_bytes(self.take_array::<4>()?))
}
pub fn u64le(&mut self) -> Result<u64> {
Ok(u64::from_le_bytes(self.take_array::<8>()?))
}
}
#[derive(Debug, Default)]
pub struct Writer {
buf: Vec<u8>,
}
impl Writer {
#[must_use]
pub const fn new() -> Self {
Self { buf: Vec::new() }
}
#[must_use]
pub fn with_capacity(n: usize) -> Self {
Self { buf: Vec::with_capacity(n) }
}
#[must_use]
pub fn len(&self) -> usize {
self.buf.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.buf.is_empty()
}
pub fn bytes(&mut self, b: &[u8]) -> &mut Self {
self.buf.extend_from_slice(b);
self
}
pub fn u8(&mut self, v: u8) -> &mut Self {
self.buf.push(v);
self
}
pub fn u16le(&mut self, v: u16) -> &mut Self {
self.buf.extend_from_slice(&v.to_le_bytes());
self
}
pub fn u32le(&mut self, v: u32) -> &mut Self {
self.buf.extend_from_slice(&v.to_le_bytes());
self
}
pub fn u64le(&mut self, v: u64) -> &mut Self {
self.buf.extend_from_slice(&v.to_le_bytes());
self
}
pub fn zeros(&mut self, n: usize) -> &mut Self {
self.buf.resize(self.buf.len().saturating_add(n), 0);
self
}
pub fn random(&mut self, n: usize) -> &mut Self {
let start = self.buf.len();
self.buf.resize(start.saturating_add(n), 0);
if let Some(tail) = self.buf.get_mut(start..) {
fill_random(tail);
}
self
}
pub fn pad_to(&mut self, total: usize) -> Result<&mut Self> {
if self.buf.len() > total {
return Err(Error::MalformedHeader { reason: "field overflow while padding" });
}
self.buf.resize(total, 0);
Ok(self)
}
#[must_use]
pub fn into_vec(self) -> Vec<u8> {
self.buf
}
#[must_use]
pub fn as_slice(&self) -> &[u8] {
&self.buf
}
}