1use super::Error;
18use rustc_hex::{FromHex, ToHex};
19use serde::{
20 de::{Error as SerdeError, Visitor},
21 Deserialize, Deserializer, Serialize, Serializer,
22};
23use std::{cmp::Ordering, fmt, ops, str};
24
25macro_rules! impl_hash {
26 ($name:ident, $size:expr) => {
27 pub struct $name([u8; $size]);
28
29 impl $name {
30 pub fn at(&self, idx: usize) -> u8 {
31 assert!(idx < $size);
32 self.0[idx]
33 }
34 }
35
36 impl fmt::Debug for $name {
37 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
38 let self_ref: &[u8] = &self.0;
39 write!(f, "{:?}", self_ref)
40 }
41 }
42
43 impl PartialEq for $name {
44 fn eq(&self, other: &Self) -> bool {
45 let self_ref: &[u8] = &self.0;
46 let other_ref: &[u8] = &other.0;
47 self_ref == other_ref
48 }
49 }
50
51 impl ops::Deref for $name {
52 type Target = [u8];
53
54 fn deref(&self) -> &Self::Target { &self.0 }
55 }
56
57 impl Serialize for $name {
58 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
59 where S: Serializer {
60 serializer.serialize_str(&self.0.to_hex::<String>())
61 }
62 }
63
64 impl<'a> Deserialize<'a> for $name {
65 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
66 where D: Deserializer<'a> {
67 struct HashVisitor;
68
69 impl<'b> Visitor<'b> for HashVisitor {
70 type Value = $name;
71
72 fn expecting(
73 &self, formatter: &mut fmt::Formatter,
74 ) -> fmt::Result {
75 write!(formatter, "a hex-encoded {}", stringify!($name))
76 }
77
78 fn visit_str<E>(
79 self, value: &str,
80 ) -> Result<Self::Value, E>
81 where E: SerdeError {
82 value.parse().map_err(SerdeError::custom)
83 }
84
85 fn visit_string<E>(
86 self, value: String,
87 ) -> Result<Self::Value, E>
88 where E: SerdeError {
89 self.visit_str(value.as_ref())
90 }
91 }
92
93 deserializer.deserialize_any(HashVisitor)
94 }
95 }
96
97 impl str::FromStr for $name {
98 type Err = Error;
99
100 fn from_str(value: &str) -> Result<Self, Self::Err> {
101 match value.from_hex::<Vec<u8>>() {
102 Ok(ref hex) if hex.len() == $size => {
103 let mut hash = [0u8; $size];
104 hash.clone_from_slice(hex);
105 Ok($name(hash))
106 }
107 _ => Err(Error::InvalidH256),
108 }
109 }
110 }
111
112 impl From<&'static str> for $name {
113 fn from(s: &'static str) -> Self {
114 s.parse().expect(&format!(
115 "invalid string literal for {}: '{}'",
116 stringify!($name),
117 s
118 ))
119 }
120 }
121
122 impl From<[u8; $size]> for $name {
123 fn from(bytes: [u8; $size]) -> Self { $name(bytes) }
124 }
125
126 impl Into<[u8; $size]> for $name {
127 fn into(self) -> [u8; $size] { self.0 }
128 }
129 };
130}
131
132impl_hash!(H128, 16);
133impl_hash!(H160, 20);
134impl_hash!(H256, 32);
135
136impl PartialOrd for H160 {
138 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
139 Some(self.cmp(other))
140 }
141}
142
143impl Eq for H160 {}
144
145impl Ord for H160 {
146 fn cmp(&self, other: &Self) -> Ordering { self.0.cmp(&other.0) }
147}