Replace AsFixedBytes with Sized + AsRef<[u8]> (#35)

* Replace AsFixedBytes with Sized + AsRef<[u8]>
* Add AsRef<u8> to impl_array_newtype!
* Include AsFixedBytes as marker trait
* Related fixes
* Remove Deref
This commit is contained in:
Jacob Payne 2017-04-06 22:54:54 -07:00 committed by Ignotus Peverell
parent 382754e54c
commit 9e82fb1774
16 changed files with 87 additions and 95 deletions

View file

@ -60,7 +60,7 @@ impl Tip {
/// Serialization of a tip, required to save to datastore.
impl ser::Writeable for Tip {
fn write(&self, writer: &mut ser::Writer) -> Result<(), ser::Error> {
fn write<W: ser::Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
try!(writer.write_u64(self.height));
try!(writer.write_fixed_bytes(&self.last_block_h));
try!(writer.write_fixed_bytes(&self.prev_block_h));

View file

@ -80,7 +80,7 @@ impl Default for BlockHeader {
/// Serialization of a block header
impl Writeable for BlockHeader {
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
ser_multiwrite!(writer,
[write_u64, self.height],
[write_fixed_bytes, &self.previous],
@ -148,7 +148,7 @@ pub struct Block {
/// binary writer. Differentiates between writing the block for the purpose of
/// full serialization and the one of just extracting a hash.
impl Writeable for Block {
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
try!(self.header.write(writer));
if writer.serialization_mode() != ser::SerializationMode::Hash {

View file

@ -20,8 +20,9 @@
use byteorder::{ByteOrder, BigEndian};
use std::fmt;
use tiny_keccak::Keccak;
use std::convert::AsRef;
use ser::{self, AsFixedBytes, Reader, Readable, Writer, Writeable, Error};
use ser::{self, Reader, Readable, Writer, Writeable, Error, AsFixedBytes};
pub const ZERO_HASH: Hash = Hash([0; 32]);
@ -50,6 +51,12 @@ impl Hash {
}
}
impl AsRef<[u8]> for Hash {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl Readable<Hash> for Hash {
fn read(reader: &mut Reader) -> Result<Hash, ser::Error> {
let v = try!(reader.read_fixed_bytes(32));
@ -62,7 +69,7 @@ impl Readable<Hash> for Hash {
}
impl Writeable for Hash {
fn write(&self, writer: &mut Writer) -> Result<(), Error> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
writer.write_fixed_bytes(&self.0)
}
}
@ -89,8 +96,8 @@ impl ser::Writer for HashWriter {
ser::SerializationMode::Hash
}
fn write_fixed_bytes(&mut self, b32: &AsFixedBytes) -> Result<(), ser::Error> {
self.state.update(b32.as_fixed_bytes());
fn write_fixed_bytes<T: AsFixedBytes>(&mut self, b32: &T) -> Result<(), ser::Error> {
self.state.update(b32.as_ref());
Ok(())
}
}

View file

@ -149,7 +149,7 @@ impl Readable<Proof> for Proof {
}
impl Writeable for Proof {
fn write(&self, writer: &mut Writer) -> Result<(), Error> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
for n in 0..PROOFSIZE {
try!(writer.write_u32(self.0[n]));
}
@ -162,9 +162,9 @@ impl Writeable for Proof {
struct HPair(Hash, Hash);
impl Writeable for HPair {
fn write(&self, writer: &mut Writer) -> Result<(), Error> {
try!(writer.write_bytes(&self.0.to_slice()));
try!(writer.write_bytes(&self.1.to_slice()));
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
try!(writer.write_bytes(&self.0));
try!(writer.write_bytes(&self.1));
Ok(())
}
}

View file

@ -67,7 +67,7 @@ impl Add<Difficulty> for Difficulty {
}
impl Writeable for Difficulty {
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
let data = self.num.to_bytes_be();
try!(writer.write_u8(data.len() as u8));
writer.write_fixed_bytes(&data)

View file

@ -52,7 +52,7 @@ pub struct TxKernel {
}
impl Writeable for TxKernel {
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
ser_multiwrite!(writer,
[write_u8, self.features.bits()],
[write_fixed_bytes, &self.excess],
@ -103,7 +103,7 @@ pub struct Transaction {
/// Implementation of Writeable for a fully blinded transaction, defines how to
/// write the transaction as binary.
impl Writeable for Transaction {
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
ser_multiwrite!(writer,
[write_u64, self.fee],
[write_bytes, &self.excess_sig],
@ -251,7 +251,7 @@ pub struct Input(pub Commitment);
/// Implementation of Writeable for a transaction Input, defines how to write
/// an Input as binary.
impl Writeable for Input {
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
writer.write_fixed_bytes(&self.0)
}
}
@ -295,11 +295,11 @@ pub struct Output {
/// Implementation of Writeable for a transaction Output, defines how to write
/// an Output as binary.
impl Writeable for Output {
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
ser_multiwrite!(writer, [write_u8, self.features.bits()], [write_fixed_bytes, &self.commit]);
// The hash of an output doesn't include the range proof
if writer.serialization_mode() == ser::SerializationMode::Full {
writer.write_bytes(&self.proof.bytes())?
writer.write_bytes(&self.proof)?
}
Ok(())
}

View file

@ -80,14 +80,6 @@ impl error::Error for Error {
}
}
/// Useful trait to implement on types that can be translated to byte slices
/// directly. Allows the use of `write_fixed_bytes` on them.
pub trait AsFixedBytes {
/// The slice representation of self
fn as_fixed_bytes(&self) -> &[u8];
}
/// Signal to a serializable object how much of its data should be serialized
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum SerializationMode {
@ -140,14 +132,14 @@ pub trait Writer {
/// Writes a variable number of bytes. The length is encoded as a 64-bit
/// prefix.
fn write_bytes(&mut self, bytes: &AsFixedBytes) -> Result<(), Error> {
try!(self.write_u64(bytes.as_fixed_bytes().len() as u64));
fn write_bytes<T: AsFixedBytes>(&mut self, bytes: &T) -> Result<(), Error> {
try!(self.write_u64(bytes.as_ref().len() as u64));
self.write_fixed_bytes(bytes)
}
/// Writes a fixed number of bytes from something that can turn itself into
/// a `&[u8]`. The reader is expected to know the actual length on read.
fn write_fixed_bytes(&mut self, fixed: &AsFixedBytes) -> Result<(), Error>;
fn write_fixed_bytes<T: AsFixedBytes>(&mut self, fixed: &T) -> Result<(), Error>;
}
/// Implementations defined how different numbers and binary structures are
@ -179,7 +171,7 @@ pub trait Reader {
/// underlying Write implementation.
pub trait Writeable {
/// Write the data held by this Writeable to the provided writer
fn write(&self, writer: &mut Writer) -> Result<(), Error>;
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error>;
}
/// Trait that every type that can be deserialized from binary must implement.
@ -197,14 +189,14 @@ pub fn deserialize<T: Readable<T>>(mut source: &mut Read) -> Result<T, Error> {
}
/// Serializes a Writeable into any std::io::Write implementation.
pub fn serialize(mut sink: &mut Write, thing: &Writeable) -> Result<(), Error> {
pub fn serialize<W: Writeable>(mut sink: &mut Write, thing: &W) -> Result<(), Error> {
let mut writer = BinWriter { sink: sink };
thing.write(&mut writer)
}
/// Utility function to serialize a writeable directly in memory using a
/// Vec<u8>.
pub fn ser_vec(thing: &Writeable) -> Result<Vec<u8>, Error> {
pub fn ser_vec<W: Writeable>(thing: &W) -> Result<Vec<u8>, Error> {
let mut vec = Vec::new();
try!(serialize(&mut vec, thing));
Ok(vec)
@ -302,53 +294,25 @@ impl<'a> Writer for BinWriter<'a> {
SerializationMode::Full
}
fn write_fixed_bytes(&mut self, fixed: &AsFixedBytes) -> Result<(), Error> {
let bs = fixed.as_fixed_bytes();
fn write_fixed_bytes<T: AsFixedBytes>(&mut self, fixed: &T) -> Result<(), Error> {
let bs = fixed.as_ref();
try!(self.sink.write_all(bs));
Ok(())
}
}
macro_rules! impl_slice_bytes {
($byteable: ty) => {
impl AsFixedBytes for $byteable {
fn as_fixed_bytes(&self) -> &[u8] {
&self[..]
}
}
}
}
/// Useful marker trait on types that can be sized byte slices
pub trait AsFixedBytes: Sized + AsRef<[u8]> {}
impl_slice_bytes!(::secp::key::SecretKey);
impl_slice_bytes!(::secp::Signature);
impl_slice_bytes!(::secp::pedersen::Commitment);
impl_slice_bytes!(Vec<u8>);
impl_slice_bytes!([u8; 1]);
impl_slice_bytes!([u8; 2]);
impl_slice_bytes!([u8; 4]);
impl_slice_bytes!([u8; 8]);
impl_slice_bytes!([u8; 32]);
impl<'a> AsFixedBytes for &'a [u8] {
fn as_fixed_bytes(&self) -> &[u8] {
*self
}
}
impl<'a> AsFixedBytes for String {
fn as_fixed_bytes(&self) -> &[u8] {
self.as_bytes()
}
}
impl AsFixedBytes for ::core::hash::Hash {
fn as_fixed_bytes(&self) -> &[u8] {
self.to_slice()
}
}
impl AsFixedBytes for ::secp::pedersen::RangeProof {
fn as_fixed_bytes(&self) -> &[u8] {
&self.bytes()
}
}
impl AsFixedBytes for Vec<u8> {}
impl AsFixedBytes for [u8; 1] {}
impl AsFixedBytes for [u8; 2] {}
impl AsFixedBytes for [u8; 4] {}
impl AsFixedBytes for [u8; 8] {}
impl AsFixedBytes for [u8; 32] {}
impl AsFixedBytes for String {}
impl AsFixedBytes for ::core::hash::Hash {}
impl AsFixedBytes for ::secp::pedersen::RangeProof {}
impl AsFixedBytes for ::secp::key::SecretKey {}
impl AsFixedBytes for ::secp::Signature {}
impl AsFixedBytes for ::secp::pedersen::Commitment {}

View file

@ -202,7 +202,7 @@ impl Connection {
/// Utility function to send any Writeable. Handles adding the header and
/// serialization.
pub fn send_msg(&self, t: Type, body: &ser::Writeable) -> Result<(), Error> {
pub fn send_msg<W: ser::Writeable> (&self, t: Type, body: &W) -> Result<(), Error> {
let mut body_data = vec![];
try!(ser::serialize(&mut body_data, body));
@ -282,10 +282,10 @@ impl TimeoutConnection {
/// Sends a request and registers a timer on the provided message type and
/// optionally the hash of the sent data.
pub fn send_request(&self,
pub fn send_request<W: ser::Writeable>(&self,
t: Type,
rt: Type,
body: &ser::Writeable,
body: &W,
expect_h: Option<(Hash)>)
-> Result<(), Error> {
let sent = try!(self.underlying.send_msg(t, body));
@ -296,7 +296,7 @@ impl TimeoutConnection {
}
/// Same as Connection
pub fn send_msg(&self, t: Type, body: &ser::Writeable) -> Result<(), Error> {
pub fn send_msg<W: ser::Writeable>(&self, t: Type, body: &W) -> Result<(), Error> {
self.underlying.send_msg(t, body)
}

View file

@ -147,7 +147,7 @@ impl MsgHeader {
}
impl Writeable for MsgHeader {
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
ser_multiwrite!(writer,
[write_u8, self.magic[0]],
[write_u8, self.magic[1]],
@ -197,7 +197,7 @@ pub struct Hand {
}
impl Writeable for Hand {
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
ser_multiwrite!(writer,
[write_u32, self.version],
[write_u32, self.capabilities.bits()],
@ -246,7 +246,7 @@ pub struct Shake {
}
impl Writeable for Shake {
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
ser_multiwrite!(writer,
[write_u32, self.version],
[write_u32, self.capabilities.bits()]);
@ -279,7 +279,7 @@ pub struct GetPeerAddrs {
}
impl Writeable for GetPeerAddrs {
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
writer.write_u32(self.capabilities.bits())
}
}
@ -299,7 +299,7 @@ pub struct PeerAddrs {
}
impl Writeable for PeerAddrs {
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
try!(writer.write_u32(self.peers.len() as u32));
for p in &self.peers {
p.write(writer);
@ -335,7 +335,7 @@ pub struct PeerError {
}
impl Writeable for PeerError {
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
ser_multiwrite!(writer, [write_u32, self.code], [write_bytes, &self.message]);
Ok(())
}
@ -358,7 +358,7 @@ impl Readable<PeerError> for PeerError {
pub struct SockAddr(pub SocketAddr);
impl Writeable for SockAddr {
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
match self.0 {
SocketAddr::V4(sav4) => {
ser_multiwrite!(writer,
@ -413,7 +413,7 @@ pub struct Locator {
}
impl Writeable for Locator {
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
writer.write_u8(self.hashes.len() as u8)?;
for h in &self.hashes {
h.write(writer)?
@ -439,7 +439,7 @@ pub struct Headers {
}
impl Writeable for Headers {
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
writer.write_u16(self.headers.len() as u16)?;
for h in &self.headers {
h.write(writer)?
@ -464,7 +464,7 @@ impl Readable<Headers> for Headers {
pub struct Empty {}
impl Writeable for Empty {
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
Ok(())
}
}

View file

@ -106,14 +106,14 @@ impl Protocol for ProtocolV1 {
}
impl ProtocolV1 {
fn send_msg(&self, t: Type, body: &ser::Writeable) -> Result<(), Error> {
fn send_msg<W: ser::Writeable>(&self, t: Type, body: &W) -> Result<(), Error> {
self.conn.borrow().send_msg(t, body)
}
fn send_request(&self,
fn send_request<W: ser::Writeable>(&self,
t: Type,
rt: Type,
body: &ser::Writeable,
body: &W,
expect_resp: Option<Hash>)
-> Result<(), Error> {
self.conn.borrow().send_request(t, rt, body, expect_resp)

View file

@ -50,7 +50,7 @@ pub struct PeerData {
}
impl Writeable for PeerData {
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
SockAddr(self.addr).write(writer)?;
ser_multiwrite!(writer,
[write_u32, self.capabilities.bits()],

View file

@ -32,6 +32,7 @@ pub struct SecretKey([u8; constants::SECRET_KEY_SIZE]);
impl_array_newtype!(SecretKey, u8, constants::SECRET_KEY_SIZE);
impl_pretty_debug!(SecretKey);
/// The number 1 encoded as a secret key
/// Deprecated; `static` is not what I want; use `ONE_KEY` instead
pub static ONE: SecretKey = SecretKey([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

View file

@ -69,6 +69,12 @@ pub struct RecoveryId(i32);
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct Signature(ffi::Signature);
impl std::convert::AsRef<[u8]> for Signature {
fn as_ref(&self) -> &[u8] {
&self.0.as_ref()
}
}
/// An ECDSA signature with a recovery ID for pubkey recovery
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct RecoverableSignature(ffi::RecoverableSignature);

View file

@ -42,6 +42,12 @@ macro_rules! impl_array_newtype {
pub fn is_empty(&self) -> bool { false }
}
impl AsRef<[u8]> for $thing {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl PartialEq for $thing {
#[inline]
fn eq(&self, other: &$thing) -> bool {

View file

@ -16,6 +16,7 @@
//! # Pedersen commitments and related range proofs
use std::mem;
use std::convert;
use ContextFlag;
use Error;
@ -32,6 +33,7 @@ pub struct Commitment(pub [u8; constants::PEDERSEN_COMMITMENT_SIZE]);
impl_array_newtype!(Commitment, u8, constants::PEDERSEN_COMMITMENT_SIZE);
impl_pretty_debug!(Commitment);
impl Commitment {
/// Uninitialized commitment, use with caution
unsafe fn blank() -> Commitment {
@ -74,6 +76,12 @@ impl Clone for RangeProof {
}
}
impl AsRef<[u8]> for RangeProof {
fn as_ref(&self) -> &[u8] {
&self.proof[..self.plen as usize]
}
}
impl RangeProof {
pub fn bytes(&self) -> &[u8] {
&self.proof[..self.plen as usize]

View file

@ -92,7 +92,7 @@ impl Store {
/// Writes a single key and its `Writeable` value to the db. Encapsulates
/// serialization.
pub fn put_ser(&self, key: &[u8], value: &ser::Writeable) -> Result<(), Error> {
pub fn put_ser<W: ser::Writeable>(&self, key: &[u8], value: &W) -> Result<(), Error> {
let ser_value = ser::ser_vec(value);
match ser_value {
Ok(data) => self.put(key, data),
@ -176,7 +176,7 @@ pub struct Batch<'a> {
impl<'a> Batch<'a> {
/// Writes a single key and its `Writeable` value to the batch. The write
/// function must be called to "commit" the batch to storage.
pub fn put_ser(mut self, key: &[u8], value: &ser::Writeable) -> Result<Batch<'a>, Error> {
pub fn put_ser<W: ser::Writeable>(mut self, key: &[u8], value: &W) -> Result<Batch<'a>, Error> {
let ser_value = ser::ser_vec(value);
match ser_value {
Ok(data) => {