Encodable/Decodable improvements; add `user_enum` macro for string enums
This commit is contained in:
parent
331e555e4c
commit
bc7077fac4
|
@ -159,6 +159,39 @@ macro_rules! impl_array_newtype(
|
|||
}
|
||||
)
|
||||
|
||||
macro_rules! impl_array_newtype_encodable(
|
||||
($thing:ident, $ty:ty, $len:expr) => {
|
||||
impl<D: ::serialize::Decoder<E>, E> ::serialize::Decodable<D, E> for $thing {
|
||||
fn decode(d: &mut D) -> ::std::prelude::Result<$thing, E> {
|
||||
use serialize::Decodable;
|
||||
|
||||
::assert_type_is_copy::<$ty>();
|
||||
|
||||
d.read_seq(|d, len| {
|
||||
if len != $len {
|
||||
Err(d.error("Invalid length"))
|
||||
} else {
|
||||
unsafe {
|
||||
use std::mem;
|
||||
let mut ret: [$ty, ..$len] = mem::uninitialized();
|
||||
for i in range(0, len) {
|
||||
ret[i] = try!(d.read_seq_elt(i, |d| Decodable::decode(d)));
|
||||
}
|
||||
Ok($thing(ret))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: ::serialize::Encoder<S>, S> ::serialize::Encodable<E, S> for $thing {
|
||||
fn encode(&self, e: &mut E) -> ::std::prelude::Result<(), S> {
|
||||
self.as_slice().encode(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
macro_rules! impl_array_newtype_show(
|
||||
($thing:ident) => {
|
||||
impl ::std::fmt::Show for $thing {
|
||||
|
|
|
@ -68,3 +68,6 @@ pub mod blockdata;
|
|||
pub mod util;
|
||||
pub mod wallet;
|
||||
|
||||
/// I dunno where else to put this..
|
||||
fn assert_type_is_copy<T: Copy>() { }
|
||||
|
||||
|
|
|
@ -84,4 +84,35 @@ macro_rules! nu_select(
|
|||
})
|
||||
)
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! user_enum(
|
||||
($(#[$attr:meta])* pub enum $name:ident { $(#[$doc:meta] $elem:ident <-> $txt:expr),* }) => (
|
||||
$(#[$attr])*
|
||||
pub enum $name {
|
||||
$(#[$doc] $elem),*
|
||||
}
|
||||
|
||||
impl ::std::fmt::Show for $name {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
f.pad(match *self {
|
||||
$($elem => $txt),*
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: ::serialize::Encoder<E>, E> ::serialize::Encodable<S, E> for $name {
|
||||
fn encode(&self, s: &mut S) -> Result<(), E> {
|
||||
s.emit_str(self.to_string().as_slice())
|
||||
}
|
||||
}
|
||||
|
||||
impl <D: ::serialize::Decoder<E>, E> ::serialize::Decodable<D, E> for $name {
|
||||
fn decode(d: &mut D) -> Result<$name, E> {
|
||||
let s = try!(d.read_str());
|
||||
$( if s.as_slice() == $txt { Ok($elem) } )else*
|
||||
else { Err(d.error(format!("unknown `{}`", s).as_slice())) }
|
||||
}
|
||||
}
|
||||
);
|
||||
)
|
||||
|
||||
|
|
|
@ -18,46 +18,19 @@
|
|||
//! protocol, such as protocol versioning and magic header bytes.
|
||||
//!
|
||||
|
||||
use std::fmt;
|
||||
use serialize::{Decoder, Encoder, Encodable, Decodable};
|
||||
|
||||
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
||||
use network::serialize::{SimpleEncoder, SimpleDecoder};
|
||||
|
||||
/// The cryptocurrency to operate on
|
||||
#[deriving(PartialEq, Eq, Clone, Hash)]
|
||||
pub enum Network {
|
||||
/// Classic Bitcoin
|
||||
Bitcoin,
|
||||
/// Bitcoin's testnet
|
||||
BitcoinTestnet,
|
||||
}
|
||||
|
||||
impl fmt::Show for Network {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad(match *self {
|
||||
Bitcoin => "bitcoin",
|
||||
BitcoinTestnet => "testnet",
|
||||
})
|
||||
user_enum!(
|
||||
#[deriving(PartialEq, Eq, Clone, Hash)]
|
||||
#[doc="The cryptocurrency to act on"]
|
||||
pub enum Network {
|
||||
#[doc="Classic Bitcoin"]
|
||||
Bitcoin <-> "bitcoin",
|
||||
#[doc="Bitcoin's testnet"]
|
||||
BitcoinTestnet <-> "testnet"
|
||||
}
|
||||
}
|
||||
|
||||
impl<S:Encoder<E>, E> Encodable<S, E> for Network {
|
||||
fn encode(&self, s: &mut S) -> Result<(), E> {
|
||||
s.emit_str(self.to_string().as_slice())
|
||||
}
|
||||
}
|
||||
|
||||
impl <D:Decoder<E>, E> Decodable<D, E> for Network {
|
||||
fn decode(d: &mut D) -> Result<Network, E> {
|
||||
let s = try!(d.read_str());
|
||||
match s.as_slice() {
|
||||
"bitcoin" => Ok(Bitcoin),
|
||||
"testnet" => Ok(BitcoinTestnet),
|
||||
_ => Err(d.error(format!("Unknown network {}", s).as_slice()))
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
pub static PROTOCOL_VERSION: u32 = 70001;
|
||||
pub static SERVICES: u64 = 0;
|
||||
|
|
|
@ -28,7 +28,7 @@ use util::hash::Sha256dHash;
|
|||
/// An address index
|
||||
#[deriving(Clone, PartialEq, Eq, Show)]
|
||||
pub struct AddressIndex {
|
||||
index: HashMap<Script, (Sha256dHash, uint)>
|
||||
index: HashMap<Script, Vec<(Sha256dHash, uint)>>
|
||||
}
|
||||
|
||||
impl AddressIndex {
|
||||
|
@ -40,7 +40,9 @@ impl AddressIndex {
|
|||
};
|
||||
for (key, idx, txo) in utxo_set.iter() {
|
||||
if wallet.might_be_mine(txo) {
|
||||
ret.index.insert(txo.script_pubkey.clone(), (key, idx));
|
||||
ret.index.insert_or_update_with(txo.script_pubkey.clone(),
|
||||
vec![(key, idx)],
|
||||
|_, v| v.push((key, idx)));
|
||||
}
|
||||
}
|
||||
ret
|
||||
|
|
|
@ -37,18 +37,20 @@ use util::base58::{Base58Error,
|
|||
pub struct ChainCode([u8, ..32]);
|
||||
impl_array_newtype!(ChainCode, u8, 32)
|
||||
impl_array_newtype_show!(ChainCode)
|
||||
impl_array_newtype_encodable!(ChainCode, u8, 32)
|
||||
|
||||
/// A fingerprint
|
||||
pub struct Fingerprint([u8, ..4]);
|
||||
impl_array_newtype!(Fingerprint, u8, 4)
|
||||
impl_array_newtype_show!(Fingerprint)
|
||||
impl_array_newtype_encodable!(Fingerprint, u8, 4)
|
||||
|
||||
impl Default for Fingerprint {
|
||||
fn default() -> Fingerprint { Fingerprint([0, 0, 0, 0]) }
|
||||
}
|
||||
|
||||
/// Extended private key
|
||||
#[deriving(Clone, PartialEq, Eq, Show)]
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Show)]
|
||||
pub struct ExtendedPrivKey {
|
||||
/// The network this key is to be used on
|
||||
pub network: Network,
|
||||
|
@ -65,7 +67,7 @@ pub struct ExtendedPrivKey {
|
|||
}
|
||||
|
||||
/// Extended public key
|
||||
#[deriving(Clone, PartialEq, Eq, Show)]
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Show)]
|
||||
pub struct ExtendedPubKey {
|
||||
/// The network this key is to be used on
|
||||
pub network: Network,
|
||||
|
@ -82,7 +84,7 @@ pub struct ExtendedPubKey {
|
|||
}
|
||||
|
||||
/// A child number for a derived key
|
||||
#[deriving(Clone, PartialEq, Eq, Show)]
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Show)]
|
||||
pub enum ChildNumber {
|
||||
/// Hardened key index, within [0, 2^31 - 1]
|
||||
Hardened(u32),
|
||||
|
@ -98,7 +100,9 @@ pub enum Error {
|
|||
/// A secp256k1 error occured
|
||||
EcdsaError(secp256k1::Error),
|
||||
/// A child number was provided that was out of range
|
||||
InvalidChildNumber(ChildNumber)
|
||||
InvalidChildNumber(ChildNumber),
|
||||
/// Error creating a master seed --- for application use
|
||||
RngError(String)
|
||||
}
|
||||
|
||||
impl ExtendedPrivKey {
|
||||
|
|
|
@ -34,7 +34,7 @@ pub enum Error {
|
|||
}
|
||||
|
||||
/// An account
|
||||
#[deriving(Clone, PartialEq, Eq, Show)]
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Show)]
|
||||
pub struct Account {
|
||||
name: String,
|
||||
internal_path: Vec<ChildNumber>,
|
||||
|
@ -52,7 +52,7 @@ impl Default for Account {
|
|||
}
|
||||
|
||||
/// A wallet
|
||||
#[deriving(Clone, PartialEq, Eq, Show)]
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Show)]
|
||||
pub struct Wallet {
|
||||
master: ExtendedPrivKey,
|
||||
accounts: HashMap<String, Account>
|
||||
|
|
Loading…
Reference in New Issue