pub use derive::BinaryHashRepr;
use serialize::VecExt;
use std::io;
pub trait MemWrite<T> {
fn write(&mut self, buf: &[T]);
}
impl<T: Copy> MemWrite<T> for Vec<T> {
fn write(&mut self, buf: &[T]) {
self.extend(buf);
}
}
impl<T, W: MemWrite<T>> MemWrite<T> for &mut W {
fn write(&mut self, buf: &[T]) {
W::write(self, buf);
}
}
pub struct IoWrite<W: MemWrite<u8>>(pub W);
impl<W: MemWrite<u8>> io::Write for IoWrite<W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf);
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
pub trait BinaryHashRepr {
fn binary_repr<W: MemWrite<u8>>(&self, writer: &mut W);
fn binary_len(&self) -> usize;
fn binary_vec(&self) -> Vec<u8> {
let mut res = Vec::with_bounded_capacity(self.binary_len());
self.binary_repr(&mut res);
res
}
}
impl BinaryHashRepr for [u8] {
fn binary_repr<W: MemWrite<u8>>(&self, writer: &mut W) {
writer.write(self);
}
fn binary_len(&self) -> usize {
self.len()
}
}
impl<const N: usize> BinaryHashRepr for [u8; N] {
fn binary_repr<W: MemWrite<u8>>(&self, writer: &mut W) {
writer.write(self)
}
fn binary_len(&self) -> usize {
N
}
}
macro_rules! integer_hash_repr {
($($ty:ty),*) => {
$(
impl BinaryHashRepr for $ty {
fn binary_repr<W: MemWrite<u8>>(&self, writer: &mut W) {
writer.write(&self.to_le_bytes());
}
fn binary_len(&self) -> usize {
<$ty>::BITS as usize / 8
}
}
)*
}
}
macro_rules! tuple_repr {
($head:ident$(, $tail:ident)*) => {
#[allow(unused_parens, non_snake_case)]
impl<$head: BinaryHashRepr$(, $tail: BinaryHashRepr)*> BinaryHashRepr for ($head, $($tail),*) {
fn binary_repr<W: MemWrite<u8>>(&self, writer: &mut W) {
let ($head, $($tail),*) = self;
$head.binary_repr(writer);
$($tail.binary_repr(writer);)*
}
fn binary_len(&self) -> usize {
let ($head, $($tail),*) = self;
$head.binary_len() $(+ $tail.binary_len())*
}
}
tuple_repr!($($tail),*);
};
() => {
impl BinaryHashRepr for () {
fn binary_repr<W: MemWrite<u8>>(&self, _: &mut W) {
}
fn binary_len(&self) -> usize {
0
}
}
};
}
tuple_repr!(A, B, C, D, E, F, G, H, I, J, K, L);
integer_hash_repr!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128);
impl BinaryHashRepr for bool {
fn binary_repr<W: MemWrite<u8>>(&self, writer: &mut W) {
writer.write(&[*self as u8]);
}
fn binary_len(&self) -> usize {
1
}
}