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(
|
macro_rules! impl_array_newtype_show(
|
||||||
($thing:ident) => {
|
($thing:ident) => {
|
||||||
impl ::std::fmt::Show for $thing {
|
impl ::std::fmt::Show for $thing {
|
||||||
|
|
|
@ -68,3 +68,6 @@ pub mod blockdata;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
pub mod wallet;
|
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.
|
//! 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::encodable::{ConsensusDecodable, ConsensusEncodable};
|
||||||
use network::serialize::{SimpleEncoder, SimpleDecoder};
|
use network::serialize::{SimpleEncoder, SimpleDecoder};
|
||||||
|
|
||||||
/// The cryptocurrency to operate on
|
user_enum!(
|
||||||
#[deriving(PartialEq, Eq, Clone, Hash)]
|
#[deriving(PartialEq, Eq, Clone, Hash)]
|
||||||
|
#[doc="The cryptocurrency to act on"]
|
||||||
pub enum Network {
|
pub enum Network {
|
||||||
/// Classic Bitcoin
|
#[doc="Classic Bitcoin"]
|
||||||
Bitcoin,
|
Bitcoin <-> "bitcoin",
|
||||||
/// Bitcoin's testnet
|
#[doc="Bitcoin's testnet"]
|
||||||
BitcoinTestnet,
|
BitcoinTestnet <-> "testnet"
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Show for Network {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
f.pad(match *self {
|
|
||||||
Bitcoin => "bitcoin",
|
|
||||||
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 PROTOCOL_VERSION: u32 = 70001;
|
||||||
pub static SERVICES: u64 = 0;
|
pub static SERVICES: u64 = 0;
|
||||||
|
|
|
@ -28,7 +28,7 @@ use util::hash::Sha256dHash;
|
||||||
/// An address index
|
/// An address index
|
||||||
#[deriving(Clone, PartialEq, Eq, Show)]
|
#[deriving(Clone, PartialEq, Eq, Show)]
|
||||||
pub struct AddressIndex {
|
pub struct AddressIndex {
|
||||||
index: HashMap<Script, (Sha256dHash, uint)>
|
index: HashMap<Script, Vec<(Sha256dHash, uint)>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AddressIndex {
|
impl AddressIndex {
|
||||||
|
@ -40,7 +40,9 @@ impl AddressIndex {
|
||||||
};
|
};
|
||||||
for (key, idx, txo) in utxo_set.iter() {
|
for (key, idx, txo) in utxo_set.iter() {
|
||||||
if wallet.might_be_mine(txo) {
|
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
|
ret
|
||||||
|
|
|
@ -37,18 +37,20 @@ use util::base58::{Base58Error,
|
||||||
pub struct ChainCode([u8, ..32]);
|
pub struct ChainCode([u8, ..32]);
|
||||||
impl_array_newtype!(ChainCode, u8, 32)
|
impl_array_newtype!(ChainCode, u8, 32)
|
||||||
impl_array_newtype_show!(ChainCode)
|
impl_array_newtype_show!(ChainCode)
|
||||||
|
impl_array_newtype_encodable!(ChainCode, u8, 32)
|
||||||
|
|
||||||
/// A fingerprint
|
/// A fingerprint
|
||||||
pub struct Fingerprint([u8, ..4]);
|
pub struct Fingerprint([u8, ..4]);
|
||||||
impl_array_newtype!(Fingerprint, u8, 4)
|
impl_array_newtype!(Fingerprint, u8, 4)
|
||||||
impl_array_newtype_show!(Fingerprint)
|
impl_array_newtype_show!(Fingerprint)
|
||||||
|
impl_array_newtype_encodable!(Fingerprint, u8, 4)
|
||||||
|
|
||||||
impl Default for Fingerprint {
|
impl Default for Fingerprint {
|
||||||
fn default() -> Fingerprint { Fingerprint([0, 0, 0, 0]) }
|
fn default() -> Fingerprint { Fingerprint([0, 0, 0, 0]) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extended private key
|
/// Extended private key
|
||||||
#[deriving(Clone, PartialEq, Eq, Show)]
|
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Show)]
|
||||||
pub struct ExtendedPrivKey {
|
pub struct ExtendedPrivKey {
|
||||||
/// The network this key is to be used on
|
/// The network this key is to be used on
|
||||||
pub network: Network,
|
pub network: Network,
|
||||||
|
@ -65,7 +67,7 @@ pub struct ExtendedPrivKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extended public key
|
/// Extended public key
|
||||||
#[deriving(Clone, PartialEq, Eq, Show)]
|
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Show)]
|
||||||
pub struct ExtendedPubKey {
|
pub struct ExtendedPubKey {
|
||||||
/// The network this key is to be used on
|
/// The network this key is to be used on
|
||||||
pub network: Network,
|
pub network: Network,
|
||||||
|
@ -82,7 +84,7 @@ pub struct ExtendedPubKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A child number for a derived key
|
/// A child number for a derived key
|
||||||
#[deriving(Clone, PartialEq, Eq, Show)]
|
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Show)]
|
||||||
pub enum ChildNumber {
|
pub enum ChildNumber {
|
||||||
/// Hardened key index, within [0, 2^31 - 1]
|
/// Hardened key index, within [0, 2^31 - 1]
|
||||||
Hardened(u32),
|
Hardened(u32),
|
||||||
|
@ -98,7 +100,9 @@ pub enum Error {
|
||||||
/// A secp256k1 error occured
|
/// A secp256k1 error occured
|
||||||
EcdsaError(secp256k1::Error),
|
EcdsaError(secp256k1::Error),
|
||||||
/// A child number was provided that was out of range
|
/// 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 {
|
impl ExtendedPrivKey {
|
||||||
|
|
|
@ -34,7 +34,7 @@ pub enum Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An account
|
/// An account
|
||||||
#[deriving(Clone, PartialEq, Eq, Show)]
|
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Show)]
|
||||||
pub struct Account {
|
pub struct Account {
|
||||||
name: String,
|
name: String,
|
||||||
internal_path: Vec<ChildNumber>,
|
internal_path: Vec<ChildNumber>,
|
||||||
|
@ -52,7 +52,7 @@ impl Default for Account {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A wallet
|
/// A wallet
|
||||||
#[deriving(Clone, PartialEq, Eq, Show)]
|
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Show)]
|
||||||
pub struct Wallet {
|
pub struct Wallet {
|
||||||
master: ExtendedPrivKey,
|
master: ExtendedPrivKey,
|
||||||
accounts: HashMap<String, Account>
|
accounts: HashMap<String, Account>
|
||||||
|
|
Loading…
Reference in New Issue