use hex::encode as hex_encode;
use std::io::{Cursor, Read, Write};
use std::ops::Deref;
use std::{fmt, io, mem, u32};
use thiserror::Error;
use super::endian;
use crate::blockdata::transaction;
use crate::util::{key, ringct};
#[cfg(feature = "serde_support")]
use serde::{Deserialize, Serialize};
#[derive(Error, Debug)]
pub enum Error {
#[error("IO error: {0}")]
Io(#[from] io::Error),
#[error("Key error: {0}")]
Key(#[from] key::Error),
#[error("Transaction error: {0}")]
Transaction(#[from] transaction::Error),
#[error("RingCT error: {0}")]
RingCT(#[from] ringct::Error),
#[error("Parsing error: {0}")]
ParseFailed(&'static str),
}
pub fn serialize<T: Encodable + std::fmt::Debug + ?Sized>(data: &T) -> Vec<u8> {
let mut encoder = Vec::new();
let len = data.consensus_encode(&mut encoder).unwrap();
debug_assert_eq!(len, encoder.len());
encoder
}
pub fn serialize_hex<T: Encodable + std::fmt::Debug + ?Sized>(data: &T) -> String {
hex_encode(serialize(data))
}
pub fn deserialize<T: Decodable>(data: &[u8]) -> Result<T, Error> {
let (rv, consumed) = deserialize_partial(data)?;
if consumed == data.len() {
Ok(rv)
} else {
Err(Error::ParseFailed(
"data not consumed entirely when explicitly deserializing",
))
}
}
pub fn deserialize_partial<T: Decodable>(data: &[u8]) -> Result<(T, usize), Error> {
let mut decoder = Cursor::new(data);
let rv = Decodable::consensus_decode(&mut decoder)?;
let consumed = decoder.position() as usize;
Ok((rv, consumed))
}
pub trait WriteExt {
fn emit_u64(&mut self, v: u64) -> Result<(), io::Error>;
fn emit_u32(&mut self, v: u32) -> Result<(), io::Error>;
fn emit_u16(&mut self, v: u16) -> Result<(), io::Error>;
fn emit_u8(&mut self, v: u8) -> Result<(), io::Error>;
fn emit_i64(&mut self, v: i64) -> Result<(), io::Error>;
fn emit_i32(&mut self, v: i32) -> Result<(), io::Error>;
fn emit_i16(&mut self, v: i16) -> Result<(), io::Error>;
fn emit_i8(&mut self, v: i8) -> Result<(), io::Error>;
fn emit_bool(&mut self, v: bool) -> Result<(), io::Error>;
fn emit_slice(&mut self, v: &[u8]) -> Result<(), io::Error>;
}
pub trait ReadExt {
fn read_u64(&mut self) -> Result<u64, Error>;
fn read_u32(&mut self) -> Result<u32, Error>;
fn read_u16(&mut self) -> Result<u16, Error>;
fn read_u8(&mut self) -> Result<u8, Error>;
fn read_i64(&mut self) -> Result<i64, Error>;
fn read_i32(&mut self) -> Result<i32, Error>;
fn read_i16(&mut self) -> Result<i16, Error>;
fn read_i8(&mut self) -> Result<i8, Error>;
fn read_bool(&mut self) -> Result<bool, Error>;
fn read_slice(&mut self, slice: &mut [u8]) -> Result<(), Error>;
}
macro_rules! encoder_fn {
($name:ident, $val_type:ty, $writefn:ident) => {
#[inline]
fn $name(&mut self, v: $val_type) -> Result<(), io::Error> {
self.write_all(&endian::$writefn(v))
}
};
}
macro_rules! decoder_fn {
($name:ident, $val_type:ty, $readfn:ident, $byte_len: expr) => {
#[inline]
fn $name(&mut self) -> Result<$val_type, Error> {
let mut val = [0; $byte_len];
self.read_exact(&mut val[..]).map_err(Error::Io)?;
Ok(endian::$readfn(&val))
}
};
}
impl<W: Write> WriteExt for W {
encoder_fn!(emit_u64, u64, u64_to_array_le);
encoder_fn!(emit_u32, u32, u32_to_array_le);
encoder_fn!(emit_u16, u16, u16_to_array_le);
encoder_fn!(emit_i64, i64, i64_to_array_le);
encoder_fn!(emit_i32, i32, i32_to_array_le);
encoder_fn!(emit_i16, i16, i16_to_array_le);
#[inline]
fn emit_i8(&mut self, v: i8) -> Result<(), io::Error> {
self.write_all(&[v as u8])
}
#[inline]
fn emit_u8(&mut self, v: u8) -> Result<(), io::Error> {
self.write_all(&[v])
}
#[inline]
fn emit_bool(&mut self, v: bool) -> Result<(), io::Error> {
self.write_all(&[v as u8])
}
#[inline]
fn emit_slice(&mut self, v: &[u8]) -> Result<(), io::Error> {
self.write_all(v)
}
}
impl<R: Read> ReadExt for R {
decoder_fn!(read_u64, u64, slice_to_u64_le, 8);
decoder_fn!(read_u32, u32, slice_to_u32_le, 4);
decoder_fn!(read_u16, u16, slice_to_u16_le, 2);
decoder_fn!(read_i64, i64, slice_to_i64_le, 8);
decoder_fn!(read_i32, i32, slice_to_i32_le, 4);
decoder_fn!(read_i16, i16, slice_to_i16_le, 2);
#[inline]
fn read_u8(&mut self) -> Result<u8, Error> {
let mut slice = [0u8; 1];
self.read_exact(&mut slice)?;
Ok(slice[0])
}
#[inline]
fn read_i8(&mut self) -> Result<i8, Error> {
let mut slice = [0u8; 1];
self.read_exact(&mut slice)?;
Ok(slice[0] as i8)
}
#[inline]
fn read_bool(&mut self) -> Result<bool, Error> {
ReadExt::read_i8(self).map(|bit| bit != 0)
}
#[inline]
fn read_slice(&mut self, slice: &mut [u8]) -> Result<(), Error> {
self.read_exact(slice).map_err(Error::Io)
}
}
pub trait Encodable {
fn consensus_encode<W: io::Write>(&self, writer: &mut W) -> Result<usize, io::Error>;
}
pub trait Decodable: Sized {
fn consensus_decode<D: io::Read>(d: &mut D) -> Result<Self, Error>;
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Default)]
#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
pub struct VarInt(pub u64);
impl fmt::Display for VarInt {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl fmt::Debug for VarInt {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl Deref for VarInt {
type Target = u64;
fn deref(&self) -> &u64 {
&self.0
}
}
macro_rules! impl_int_encodable {
($ty:ident, $meth_dec:ident, $meth_enc:ident) => {
impl Decodable for $ty {
#[inline]
fn consensus_decode<D: io::Read>(d: &mut D) -> Result<Self, Error> {
ReadExt::$meth_dec(d).map($ty::from_le)
}
}
impl Encodable for $ty {
#[inline]
fn consensus_encode<S: io::Write>(&self, s: &mut S) -> Result<usize, io::Error> {
s.$meth_enc(self.to_le())?;
Ok(mem::size_of::<$ty>())
}
}
};
}
impl_int_encodable!(u8, read_u8, emit_u8);
impl_int_encodable!(u16, read_u16, emit_u16);
impl_int_encodable!(u32, read_u32, emit_u32);
impl_int_encodable!(u64, read_u64, emit_u64);
impl_int_encodable!(i8, read_i8, emit_i8);
impl_int_encodable!(i16, read_i16, emit_i16);
impl_int_encodable!(i32, read_i32, emit_i32);
impl_int_encodable!(i64, read_i64, emit_i64);
impl Encodable for VarInt {
#[inline]
fn consensus_encode<S: io::Write>(&self, s: &mut S) -> Result<usize, io::Error> {
let mut res: Vec<u8> = vec![];
let mut n = self.0;
loop {
let bits = (n & 0b0111_1111) as u8;
n >>= 7;
res.push(bits);
if n == 0u64 {
break;
}
}
match res.split_last() {
Some((last, arr)) => {
let a: Result<Vec<_>, io::Error> = arr
.iter()
.map(|bits| s.emit_u8(*bits | 0b1000_0000))
.collect();
let len = a?.len();
s.emit_u8(*last)?;
Ok(len + 1)
}
None => {
s.emit_u8(0x00)?;
Ok(1)
}
}
}
}
impl Decodable for VarInt {
#[inline]
fn consensus_decode<D: io::Read>(d: &mut D) -> Result<Self, Error> {
let mut res: Vec<u8> = vec![];
loop {
let n = d.read_u8()?;
res.push(n & 0b0111_1111);
if n & 0b1000_0000 == 0 {
break;
}
}
let mut int = 0u64;
res.reverse();
let (last, arr) = res.split_last().unwrap();
arr.iter().for_each(|bits| {
int |= *bits as u64;
int <<= 7;
});
int |= *last as u64;
Ok(VarInt(int))
}
}
impl Encodable for bool {
#[inline]
fn consensus_encode<S: io::Write>(&self, s: &mut S) -> Result<usize, io::Error> {
s.emit_bool(*self)?;
Ok(1)
}
}
impl Decodable for bool {
#[inline]
fn consensus_decode<D: io::Read>(d: &mut D) -> Result<bool, Error> {
ReadExt::read_bool(d)
}
}
impl Encodable for String {
#[inline]
fn consensus_encode<S: io::Write>(&self, s: &mut S) -> Result<usize, io::Error> {
let b = self.as_bytes();
let vi_len = VarInt(b.len() as u64).consensus_encode(s)?;
s.emit_slice(&b)?;
Ok(vi_len + b.len())
}
}
impl Decodable for String {
#[inline]
fn consensus_decode<D: io::Read>(d: &mut D) -> Result<String, Error> {
String::from_utf8(Decodable::consensus_decode(d)?)
.map_err(|_| self::Error::ParseFailed("String was not valid UTF8"))
}
}
macro_rules! impl_array {
( $size:expr ) => {
impl<T: Encodable> Encodable for [T; $size] {
#[inline]
fn consensus_encode<S: io::Write>(&self, s: &mut S) -> Result<usize, io::Error> {
let mut len = 0;
for i in self.iter() {
len += i.consensus_encode(s)?;
}
Ok(len)
}
}
impl<T: Decodable + Copy> Decodable for [T; $size] {
#[inline]
fn consensus_decode<D: io::Read>(d: &mut D) -> Result<Self, Error> {
let mut ret = [Decodable::consensus_decode(d)?; $size];
for item in ret.iter_mut().take($size).skip(1) {
*item = Decodable::consensus_decode(d)?;
}
Ok(ret)
}
}
};
}
impl_array!(8);
impl_array!(32);
impl_array!(64);
impl<T: Encodable> Encodable for [T] {
#[inline]
fn consensus_encode<S: io::Write>(&self, s: &mut S) -> Result<usize, io::Error> {
let mut len = VarInt(self.len() as u64).consensus_encode(s)?;
for c in self.iter() {
len += c.consensus_encode(s)?;
}
Ok(len)
}
}
impl<T: Encodable> Encodable for Vec<T> {
#[inline]
fn consensus_encode<S: io::Write>(&self, s: &mut S) -> Result<usize, io::Error> {
(&self[..]).consensus_encode(s)
}
}
impl<T: Decodable> Decodable for Vec<T> {
#[inline]
fn consensus_decode<D: io::Read>(d: &mut D) -> Result<Self, Error> {
let len = VarInt::consensus_decode(d)?.0;
let mut ret = Vec::with_capacity(len as usize);
for _ in 0..len {
ret.push(Decodable::consensus_decode(d)?);
}
Ok(ret)
}
}
macro_rules! decode_sized_vec {
( $size:expr, $d:expr ) => {{
let mut ret = Vec::with_capacity($size as usize);
for _ in 0..$size {
ret.push(Decodable::consensus_decode($d)?);
}
ret
}};
}
macro_rules! encode_sized_vec {
( $vec:expr, $s:expr ) => {{
let mut len = 0;
for c in $vec.iter() {
len += c.consensus_encode($s)?;
}
len
}};
}
impl<T: Encodable> Encodable for Box<[T]> {
#[inline]
fn consensus_encode<S: io::Write>(&self, s: &mut S) -> Result<usize, io::Error> {
(&self[..]).consensus_encode(s)
}
}
impl<T: Decodable> Decodable for Box<[T]> {
#[inline]
fn consensus_decode<D: io::Read>(d: &mut D) -> Result<Self, Error> {
let len = VarInt::consensus_decode(d)?.0;
let len = len as usize;
let mut ret = Vec::with_capacity(len);
for _ in 0..len {
ret.push(Decodable::consensus_decode(d)?);
}
Ok(ret.into_boxed_slice())
}
}
#[cfg(test)]
mod tests {
use super::VarInt;
use super::{deserialize, serialize};
#[test]
fn deserialize_varint() {
let int: VarInt = deserialize(&[0b000_0001]).unwrap();
assert_eq!(VarInt(1), int);
let int: VarInt = deserialize(&[0b1010_1100, 0b0000_0010]).unwrap();
assert_eq!(VarInt(300), int);
}
#[test]
fn serialize_varint() {
assert_eq!(vec![0b000_0001], serialize(&VarInt(1)));
assert_eq!(vec![0b1010_1100, 0b0000_0010], serialize(&VarInt(300)));
assert_eq!("80e497d012", hex::encode(serialize(&VarInt(5000000000))));
}
}