Converse of deser macro to make serialization of structs less verbose.

This commit is contained in:
Ignotus Peverell 2016-10-24 20:41:28 -07:00
parent b50e1ab038
commit 9f780f6865
No known key found for this signature in database
GPG key ID: 99CD25F39F8F8211
5 changed files with 70 additions and 49 deletions

View file

@ -61,12 +61,13 @@ impl Default for BlockHeader {
// core. Readable is in the ser package. // core. Readable is in the ser package.
impl Writeable for BlockHeader { impl Writeable for BlockHeader {
fn write(&self, writer: &mut Writer) -> Option<ser::Error> { fn write(&self, writer: &mut Writer) -> Option<ser::Error> {
try_m!(writer.write_u64(self.height)); ser_multiwrite!(writer,
try_m!(writer.write_fixed_bytes(&self.previous)); [write_u64, self.height],
try_m!(writer.write_i64(self.timestamp.to_timespec().sec)); [write_fixed_bytes, &self.previous],
try_m!(writer.write_fixed_bytes(&self.utxo_merkle)); [write_i64, self.timestamp.to_timespec().sec],
try_m!(writer.write_fixed_bytes(&self.tx_merkle)); [write_fixed_bytes, &self.utxo_merkle],
try_m!(writer.write_u64(self.total_fees)); [write_fixed_bytes, &self.tx_merkle],
[write_u64, self.total_fees]);
// make sure to not introduce any variable length data before the nonce to // make sure to not introduce any variable length data before the nonce to
// avoid complicating PoW // avoid complicating PoW
try_m!(writer.write_u64(self.nonce)); try_m!(writer.write_u64(self.nonce));
@ -103,9 +104,10 @@ impl Writeable for Block {
fn write(&self, writer: &mut Writer) -> Option<ser::Error> { fn write(&self, writer: &mut Writer) -> Option<ser::Error> {
try_m!(self.header.write(writer)); try_m!(self.header.write(writer));
try_m!(writer.write_u64(self.inputs.len() as u64)); ser_multiwrite!(writer,
try_m!(writer.write_u64(self.outputs.len() as u64)); [write_u64, self.inputs.len() as u64],
try_m!(writer.write_u64(self.proofs.len() as u64)); [write_u64, self.outputs.len() as u64],
[write_u64, self.proofs.len() as u64]);
for inp in &self.inputs { for inp in &self.inputs {
try_m!(inp.write(writer)); try_m!(inp.write(writer));
} }
@ -124,7 +126,14 @@ impl Writeable for Block {
impl Readable<Block> for Block { impl Readable<Block> for Block {
fn read(reader: &mut Reader) -> Result<Block, ser::Error> { fn read(reader: &mut Reader) -> Result<Block, ser::Error> {
let (height, previous, timestamp, utxo_merkle, tx_merkle, total_fees, nonce) = let (height, previous, timestamp, utxo_merkle, tx_merkle, total_fees, nonce) =
ser_multiread!(reader, read_u64, read_32_bytes, read_i64, read_32_bytes, read_32_bytes, read_u64, read_u64); ser_multiread!(reader,
read_u64,
read_32_bytes,
read_i64,
read_32_bytes,
read_32_bytes,
read_u64,
read_u64);
// cuckoo cycle of 42 nodes // cuckoo cycle of 42 nodes
let mut pow = [0; PROOFSIZE]; let mut pow = [0; PROOFSIZE];
@ -136,7 +145,8 @@ impl Readable<Block> for Block {
ser_multiread!(reader, read_u64, read_u64, read_u64, read_u64); ser_multiread!(reader, read_u64, read_u64, read_u64, read_u64);
if input_len > MAX_IN_OUT_LEN || output_len > MAX_IN_OUT_LEN || proof_len > MAX_IN_OUT_LEN { if input_len > MAX_IN_OUT_LEN || output_len > MAX_IN_OUT_LEN || proof_len > MAX_IN_OUT_LEN {
return Err(ser::Error::TooLargeReadErr("Too many inputs, outputs or proofs.".to_string())); return Err(ser::Error::TooLargeReadErr("Too many inputs, outputs or proofs."
.to_string()));
} }
let inputs = try!((0..input_len).map(|_| Input::read(reader)).collect()); let inputs = try!((0..input_len).map(|_| Input::read(reader)).collect());
@ -463,4 +473,3 @@ mod test {
assert_eq!(b3.outputs.len(), 4); assert_eq!(b3.outputs.len(), 4);
} }
} }

View file

@ -80,4 +80,3 @@ impl Hashed for [u8] {
self.to_owned() self.to_owned()
} }
} }

View file

@ -69,10 +69,11 @@ pub struct Transaction {
/// write the transaction as binary. /// write the transaction as binary.
impl Writeable for Transaction { impl Writeable for Transaction {
fn write(&self, writer: &mut Writer) -> Option<ser::Error> { fn write(&self, writer: &mut Writer) -> Option<ser::Error> {
try_m!(writer.write_u64(self.fee)); ser_multiwrite!(writer,
try_m!(writer.write_vec(&mut self.zerosig.clone())); [write_u64, self.fee],
try_m!(writer.write_u64(self.inputs.len() as u64)); [write_vec, &mut self.zerosig.clone()],
try_m!(writer.write_u64(self.outputs.len() as u64)); [write_u64, self.inputs.len() as u64],
[write_u64, self.outputs.len() as u64]);
for inp in &self.inputs { for inp in &self.inputs {
try_m!(inp.write(writer)); try_m!(inp.write(writer));
} }
@ -545,5 +546,3 @@ mod test {
} }
} }
} }

View file

@ -72,7 +72,8 @@ macro_rules! try_m {
} }
} }
/// Eliminate some of the boilerplate of deserialization (package ser) by passing just the list of reader function. /// Eliminate some of the boilerplate of deserialization (package ser) by
/// passing just the list of reader function.
/// Example before: /// Example before:
/// let foo = try!(reader.read_u64()); /// let foo = try!(reader.read_u64());
/// let bar = try!(reader.read_u32()); /// let bar = try!(reader.read_u32());
@ -85,3 +86,9 @@ macro_rules! ser_multiread {
} }
} }
#[macro_export]
macro_rules! ser_multiwrite {
($wrtr:ident, $([ $write_call:ident, $val:expr ]),* ) => {
$( try_m!($wrtr.$write_call($val)) );*
}
}

View file

@ -82,7 +82,8 @@ pub trait Reader {
fn read_32_bytes(&mut self) -> Result<Vec<u8>, Error>; fn read_32_bytes(&mut self) -> Result<Vec<u8>, Error>;
/// Convenience function to read 33 fixed bytes /// Convenience function to read 33 fixed bytes
fn read_33_bytes(&mut self) -> Result<Vec<u8>, Error>; fn read_33_bytes(&mut self) -> Result<Vec<u8>, Error>;
/// Consumes a byte from the reader, producing an error if it doesn't have the expected value /// Consumes a byte from the reader, producing an error if it doesn't have
/// the expected value
fn expect_u8(&mut self, val: u8) -> Result<u8, Error>; fn expect_u8(&mut self, val: u8) -> Result<u8, Error>;
} }
@ -164,7 +165,14 @@ impl<'a> Reader for BinReader<'a> {
} }
fn expect_u8(&mut self, val: u8) -> Result<u8, Error> { fn expect_u8(&mut self, val: u8) -> Result<u8, Error> {
let b = try!(self.read_u8()); let b = try!(self.read_u8());
if b == val { Ok(b) } else { Err(Error::UnexpectedData{expected: vec![val], received: vec![b]}) } if b == val {
Ok(b)
} else {
Err(Error::UnexpectedData {
expected: vec![val],
received: vec![b],
})
}
} }
} }
@ -228,4 +236,3 @@ impl AsFixedBytes for ::secp::pedersen::RangeProof {
&self.bytes() &self.bytes()
} }
} }