// Rust Bitcoin Library // Written in 2014 by // Andrew Poelstra // // To the extent possible under law, the author(s) have dedicated all // copyright and related and neighboring rights to this software to // the public domain worldwide. This software is distributed without // any warranty. // // You should have received a copy of the CC0 Public Domain Dedication // along with this software. // If not, see . // //! Internal Macros //! //! Macros meant to be used inside the Rust Bitcoin library macro_rules! impl_consensus_encoding { ($thing:ident, $($field:ident),+) => ( impl ::consensus::Encodable for $thing { #[inline] fn consensus_encode( &self, mut s: S, ) -> Result { let mut len = 0; $(len += self.$field.consensus_encode(&mut s)?;)+ Ok(len) } } impl ::consensus::Decodable for $thing { #[inline] fn consensus_decode( mut d: D, ) -> Result<$thing, ::consensus::encode::Error> { Ok($thing { $($field: ::consensus::Decodable::consensus_decode(&mut d)?),+ }) } } ); } macro_rules! impl_array_newtype { ($thing:ident, $ty:ty, $len:expr) => { impl $thing { #[inline] /// Converts the object to a raw pointer pub fn as_ptr(&self) -> *const $ty { let &$thing(ref dat) = self; dat.as_ptr() } #[inline] /// Converts the object to a mutable raw pointer pub fn as_mut_ptr(&mut self) -> *mut $ty { let &mut $thing(ref mut dat) = self; dat.as_mut_ptr() } #[inline] /// Returns the length of the object as an array pub fn len(&self) -> usize { $len } #[inline] /// Returns whether the object, as an array, is empty. Always false. pub fn is_empty(&self) -> bool { false } #[inline] /// Returns the underlying bytes. pub fn as_bytes(&self) -> &[$ty; $len] { &self.0 } #[inline] /// Returns the underlying bytes. pub fn to_bytes(&self) -> [$ty; $len] { self.0.clone() } #[inline] /// Returns the underlying bytes. pub fn into_bytes(self) -> [$ty; $len] { self.0 } } impl<'a> From<&'a [$ty]> for $thing { fn from(data: &'a [$ty]) -> $thing { assert_eq!(data.len(), $len); let mut ret = [0; $len]; ret.copy_from_slice(&data[..]); $thing(ret) } } impl ::std::ops::Index for $thing { type Output = $ty; #[inline] fn index(&self, index: usize) -> &$ty { let &$thing(ref dat) = self; &dat[index] } } impl_index_newtype!($thing, $ty); impl PartialEq for $thing { #[inline] fn eq(&self, other: &$thing) -> bool { &self[..] == &other[..] } } impl Eq for $thing {} impl PartialOrd for $thing { #[inline] fn partial_cmp(&self, other: &$thing) -> Option<::std::cmp::Ordering> { Some(self.cmp(&other)) } } impl Ord for $thing { #[inline] fn cmp(&self, other: &$thing) -> ::std::cmp::Ordering { // manually implement comparison to get little-endian ordering // (we need this for our numeric types; non-numeric ones shouldn't // be ordered anyway except to put them in BTrees or whatever, and // they don't care how we order as long as we're consistent). for i in 0..$len { if self[$len - 1 - i] < other[$len - 1 - i] { return ::std::cmp::Ordering::Less; } if self[$len - 1 - i] > other[$len - 1 - i] { return ::std::cmp::Ordering::Greater; } } ::std::cmp::Ordering::Equal } } #[cfg_attr(feature = "clippy", allow(expl_impl_clone_on_copy))] // we don't define the `struct`, we have to explicitly impl impl Clone for $thing { #[inline] fn clone(&self) -> $thing { $thing::from(&self[..]) } } impl Copy for $thing {} impl ::std::hash::Hash for $thing { #[inline] fn hash(&self, state: &mut H) where H: ::std::hash::Hasher { (&self[..]).hash(state); } fn hash_slice(data: &[$thing], state: &mut H) where H: ::std::hash::Hasher { for d in data.iter() { (&d[..]).hash(state); } } } } } macro_rules! impl_array_newtype_show { ($thing:ident) => { impl ::std::fmt::Debug for $thing { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { write!(f, concat!(stringify!($thing), "({:?})"), &self[..]) } } } } macro_rules! impl_index_newtype { ($thing:ident, $ty:ty) => { impl ::std::ops::Index<::std::ops::Range> for $thing { type Output = [$ty]; #[inline] fn index(&self, index: ::std::ops::Range) -> &[$ty] { &self.0[index] } } impl ::std::ops::Index<::std::ops::RangeTo> for $thing { type Output = [$ty]; #[inline] fn index(&self, index: ::std::ops::RangeTo) -> &[$ty] { &self.0[index] } } impl ::std::ops::Index<::std::ops::RangeFrom> for $thing { type Output = [$ty]; #[inline] fn index(&self, index: ::std::ops::RangeFrom) -> &[$ty] { &self.0[index] } } impl ::std::ops::Index<::std::ops::RangeFull> for $thing { type Output = [$ty]; #[inline] fn index(&self, _: ::std::ops::RangeFull) -> &[$ty] { &self.0[..] } } } } macro_rules! display_from_debug { ($thing:ident) => { impl ::std::fmt::Display for $thing { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { ::std::fmt::Debug::fmt(self, f) } } } } #[cfg(test)] macro_rules! hex_script (($s:expr) => (::blockdata::script::Script::from(::hex::decode($s).unwrap()))); #[cfg(test)] macro_rules! hex_hash (($s:expr) => (::bitcoin_hashes::sha256d::Hash::from_slice(&::hex::decode($s).unwrap()).unwrap())); macro_rules! serde_struct_impl { ($name:ident, $($fe:ident),*) => ( #[cfg(feature = "serde")] impl<'de> $crate::serde::Deserialize<'de> for $name { fn deserialize(deserializer: D) -> Result<$name, D::Error> where D: $crate::serde::de::Deserializer<'de>, { use $crate::std::fmt::{self, Formatter}; use $crate::serde::de::IgnoredAny; #[allow(non_camel_case_types)] enum Enum { Unknown__Field, $($fe),* } struct EnumVisitor; impl<'de> $crate::serde::de::Visitor<'de> for EnumVisitor { type Value = Enum; fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { formatter.write_str("a field name") } fn visit_str(self, v: &str) -> Result where E: $crate::serde::de::Error, { match v { $( stringify!($fe) => Ok(Enum::$fe) ),*, _ => Ok(Enum::Unknown__Field) } } } impl<'de> $crate::serde::Deserialize<'de> for Enum { fn deserialize(deserializer: D) -> Result where D: ::serde::de::Deserializer<'de>, { deserializer.deserialize_str(EnumVisitor) } } struct Visitor; impl<'de> $crate::serde::de::Visitor<'de> for Visitor { type Value = $name; fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { formatter.write_str("a struct") } fn visit_map(self, mut map: A) -> Result where A: $crate::serde::de::MapAccess<'de>, { use $crate::serde::de::Error; $(let mut $fe = None;)* loop { match map.next_key::()? { Some(Enum::Unknown__Field) => { map.next_value::()?; } $( Some(Enum::$fe) => { $fe = Some(map.next_value()?); } )* None => { break; } } } $( let $fe = match $fe { Some(x) => x, None => return Err(A::Error::missing_field(stringify!($fe))), }; )* let ret = $name { $($fe: $fe),* }; Ok(ret) } } // end type defs static FIELDS: &'static [&'static str] = &[$(stringify!($fe)),*]; deserializer.deserialize_struct(stringify!($name), FIELDS, Visitor) } } #[cfg(feature = "serde")] impl<'de> $crate::serde::Serialize for $name { fn serialize(&self, serializer: S) -> Result where S: $crate::serde::Serializer, { use $crate::serde::ser::SerializeStruct; // Only used to get the struct length. static FIELDS: &'static [&'static str] = &[$(stringify!($fe)),*]; let mut st = serializer.serialize_struct(stringify!($name), FIELDS.len())?; $( st.serialize_field(stringify!($fe), &self.$fe)?; )* st.end() } } ) } macro_rules! serde_string_impl { ($name:ident, $expecting:expr) => { #[cfg(feature = "serde")] impl<'de> $crate::serde::Deserialize<'de> for $name { fn deserialize(deserializer: D) -> Result<$name, D::Error> where D: $crate::serde::de::Deserializer<'de>, { use $crate::std::fmt::{self, Formatter}; use $crate::std::str::FromStr; struct Visitor; impl<'de> $crate::serde::de::Visitor<'de> for Visitor { type Value = $name; fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { formatter.write_str($expecting) } fn visit_str(self, v: &str) -> Result where E: $crate::serde::de::Error, { $name::from_str(v).map_err(E::custom) } fn visit_borrowed_str(self, v: &'de str) -> Result where E: $crate::serde::de::Error, { self.visit_str(v) } fn visit_string(self, v: String) -> Result where E: $crate::serde::de::Error, { self.visit_str(&v) } } deserializer.deserialize_str(Visitor) } } #[cfg(feature = "serde")] impl<'de> $crate::serde::Serialize for $name { fn serialize(&self, serializer: S) -> Result where S: $crate::serde::Serializer, { serializer.collect_str(&self) } } }; } /// A combination of serde_struct_impl and serde_string_impl where string is /// used for human-readable serialization and struct is used for /// non-human-readable serialization. macro_rules! serde_struct_human_string_impl { ($name:ident, $expecting:expr, $($fe:ident),*) => ( #[cfg(feature = "serde")] impl<'de> $crate::serde::Deserialize<'de> for $name { fn deserialize(deserializer: D) -> Result<$name, D::Error> where D: $crate::serde::de::Deserializer<'de>, { if deserializer.is_human_readable() { use $crate::std::fmt::{self, Formatter}; use $crate::std::str::FromStr; struct Visitor; impl<'de> $crate::serde::de::Visitor<'de> for Visitor { type Value = $name; fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { formatter.write_str($expecting) } fn visit_str(self, v: &str) -> Result where E: $crate::serde::de::Error, { $name::from_str(v).map_err(E::custom) } fn visit_borrowed_str(self, v: &'de str) -> Result where E: $crate::serde::de::Error, { self.visit_str(v) } fn visit_string(self, v: String) -> Result where E: $crate::serde::de::Error, { self.visit_str(&v) } } deserializer.deserialize_str(Visitor) } else { use $crate::std::fmt::{self, Formatter}; use $crate::serde::de::IgnoredAny; #[allow(non_camel_case_types)] enum Enum { Unknown__Field, $($fe),* } struct EnumVisitor; impl<'de> $crate::serde::de::Visitor<'de> for EnumVisitor { type Value = Enum; fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { formatter.write_str("a field name") } fn visit_str(self, v: &str) -> Result where E: $crate::serde::de::Error, { match v { $( stringify!($fe) => Ok(Enum::$fe) ),*, _ => Ok(Enum::Unknown__Field) } } } impl<'de> $crate::serde::Deserialize<'de> for Enum { fn deserialize(deserializer: D) -> Result where D: $crate::serde::de::Deserializer<'de>, { deserializer.deserialize_str(EnumVisitor) } } struct Visitor; impl<'de> $crate::serde::de::Visitor<'de> for Visitor { type Value = $name; fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { formatter.write_str("a struct") } fn visit_map(self, mut map: A) -> Result where A: $crate::serde::de::MapAccess<'de>, { use $crate::serde::de::Error; $(let mut $fe = None;)* loop { match map.next_key::()? { Some(Enum::Unknown__Field) => { map.next_value::()?; } $( Some(Enum::$fe) => { $fe = Some(map.next_value()?); } )* None => { break; } } } $( let $fe = match $fe { Some(x) => x, None => return Err(A::Error::missing_field(stringify!($fe))), }; )* let ret = $name { $($fe: $fe),* }; Ok(ret) } } // end type defs static FIELDS: &'static [&'static str] = &[$(stringify!($fe)),*]; deserializer.deserialize_struct(stringify!($name), FIELDS, Visitor) } } } #[cfg(feature = "serde")] impl<'de> $crate::serde::Serialize for $name { fn serialize(&self, serializer: S) -> Result where S: $crate::serde::Serializer, { if serializer.is_human_readable() { serializer.collect_str(&self) } else { use $crate::serde::ser::SerializeStruct; // Only used to get the struct length. static FIELDS: &'static [&'static str] = &[$(stringify!($fe)),*]; let mut st = serializer.serialize_struct(stringify!($name), FIELDS.len())?; $( st.serialize_field(stringify!($fe), &self.$fe)?; )* st.end() } } } ) } /// Implements several traits for byte-based newtypes. /// Implements: /// - std::fmt::LowerHex (implies bitcoin_hashes::hex::ToHex) /// - std::fmt::Display /// - std::str::FromStr /// - bitcoin_hashes::hex::FromHex macro_rules! impl_bytes_newtype { ($t:ident, $len:expr) => ( impl ::std::fmt::LowerHex for $t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { for &ch in self.0.iter() { write!(f, "{:02x}", ch)?; } Ok(()) } } impl ::std::fmt::Display for $t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(self, f) } } impl ::bitcoin_hashes::hex::FromHex for $t { fn from_byte_iter(iter: I) -> Result where I: Iterator> + ExactSizeIterator + DoubleEndedIterator, { if iter.len() == $len { let mut ret = [0; $len]; for (n, byte) in iter.enumerate() { ret[n] = byte?; } Ok($t(ret)) } else { Err(::bitcoin_hashes::hex::Error::InvalidLength(2 * $len, 2 * iter.len())) } } } impl ::std::str::FromStr for $t { type Err = bitcoin_hashes::hex::Error; fn from_str(s: &str) -> Result { hex::FromHex::from_hex(s) } } #[cfg(feature="serde")] impl ::serde::Serialize for $t { fn serialize(&self, s: S) -> Result { if s.is_human_readable() { s.serialize_str(&::bitcoin_hashes::hex::ToHex::to_hex(self)) } else { s.serialize_bytes(&self[..]) } } } #[cfg(feature="serde")] impl<'de> ::serde::Deserialize<'de> for $t { fn deserialize>(d: D) -> Result<$t, D::Error> { if d.is_human_readable() { struct HexVisitor; impl<'de> ::serde::de::Visitor<'de> for HexVisitor { type Value = $t; fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { formatter.write_str("an ASCII hex string") } fn visit_bytes(self, v: &[u8]) -> Result where E: ::serde::de::Error, { if let Ok(hex) = ::std::str::from_utf8(v) { ::bitcoin_hashes::hex::FromHex::from_hex(hex).map_err(E::custom) } else { return Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self)); } } fn visit_str(self, v: &str) -> Result where E: ::serde::de::Error, { ::bitcoin_hashes::hex::FromHex::from_hex(v).map_err(E::custom) } } d.deserialize_str(HexVisitor) } else { struct BytesVisitor; impl<'de> ::serde::de::Visitor<'de> for BytesVisitor { type Value = $t; fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { formatter.write_str("a bytestring") } fn visit_bytes(self, v: &[u8]) -> Result where E: ::serde::de::Error, { if v.len() != $len { Err(E::invalid_length(v.len(), &stringify!($len))) } else { let mut ret = [0; $len]; ret.copy_from_slice(v); Ok($t(ret)) } } } d.deserialize_bytes(BytesVisitor) } } } ) } 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::Debug for $name { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { f.pad(match *self { $($name::$elem => $txt),* }) } } impl ::std::fmt::Display for $name { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { f.pad(match *self { $($name::$elem => $txt),* }) } } impl ::std::str::FromStr for $name { type Err = ::std::io::Error; #[inline] fn from_str(s: &str) -> Result { match s { $($txt => Ok($name::$elem)),*, _ => Err(::std::io::Error::new( ::std::io::ErrorKind::InvalidInput, format!("Unknown network (type {})", s), )), } } } #[cfg(feature = "serde")] impl<'de> $crate::serde::Deserialize<'de> for $name { #[inline] fn deserialize(deserializer: D) -> Result where D: $crate::serde::Deserializer<'de>, { use $crate::std::fmt::{self, Formatter}; struct Visitor; impl<'de> $crate::serde::de::Visitor<'de> for Visitor { type Value = $name; fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { formatter.write_str("an enum value") } fn visit_str(self, v: &str) -> Result where E: $crate::serde::de::Error, { static FIELDS: &'static [&'static str] = &[$(stringify!($txt)),*]; $( if v == $txt { Ok($name::$elem) } )else* else { Err(E::unknown_variant(v, FIELDS)) } } fn visit_borrowed_str(self, v: &'de str) -> Result where E: $crate::serde::de::Error, { self.visit_str(v) } fn visit_string(self, v: String) -> Result where E: $crate::serde::de::Error, { self.visit_str(&v) } } deserializer.deserialize_str(Visitor) } } #[cfg(feature = "serde")] impl ::serde::Serialize for $name { fn serialize(&self, serializer: S) -> Result where S: ::serde::Serializer, { serializer.collect_str(&self) } } ); }