Skip to main content

ark/
util.rs

1
2/// Implement a bunch of useful traits for any newtype around 32 bytes.
3macro_rules! impl_byte_newtype {
4	($name:ident, $n:expr) => {
5		impl std::fmt::Debug for $name {
6			fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7				std::fmt::Display::fmt(self, f)
8			}
9		}
10
11		impl std::fmt::Display for $name {
12			fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13				let case = $crate::bitcoin::hex::Case::Lower;
14				$crate::bitcoin::hex::fmt_hex_exact!(f, $n, &self.0, case)
15			}
16		}
17
18		impl std::str::FromStr for $name {
19			type Err = bitcoin::hashes::hex::HexToArrayError;
20
21			fn from_str(s: &str) -> Result<Self, Self::Err> {
22				$crate::bitcoin::hex::FromHex::from_hex(s).map($name)
23			}
24		}
25
26		impl From<[u8; $n]> for $name {
27			fn from(inner: [u8; $n]) -> Self {
28				$name(inner)
29			}
30		}
31
32		impl From<$name> for [u8; $n] {
33			fn from(p: $name) -> Self {
34				p.0
35			}
36		}
37
38		impl std::convert::TryFrom<&[u8]> for $name {
39			type Error = std::array::TryFromSliceError;
40
41			fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
42				<&[u8; $n]>::try_from(slice).map(|arr| $name(*arr))
43			}
44		}
45
46		impl TryFrom<Vec<u8>> for $name {
47			type Error = std::array::TryFromSliceError;
48
49			fn try_from(vec: Vec<u8>) -> Result<Self, Self::Error> {
50				$name::try_from(vec.as_slice())
51			}
52		}
53
54		impl AsRef<[u8]> for $name {
55			fn as_ref(&self) -> &[u8] {
56				&self.0
57			}
58		}
59
60		impl<'a> $crate::bitcoin::hex::DisplayHex for &'a $name {
61			type Display = <&'a [u8; $n] as $crate::bitcoin::hex::DisplayHex>::Display;
62
63			fn as_hex(self) -> Self::Display {
64				$crate::bitcoin::hex::DisplayHex::as_hex(&self.0)
65			}
66		}
67
68		impl serde::Serialize for $name {
69			fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
70				if s.is_human_readable() {
71					s.collect_str(self)
72				} else {
73					s.serialize_bytes(self.as_ref())
74				}
75			}
76		}
77
78		impl<'de> serde::Deserialize<'de> for $name {
79			fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
80				struct Visitor;
81				impl<'de> serde::de::Visitor<'de> for Visitor {
82					type Value = $name;
83					fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
84						write!(f, concat!("a ", stringify!($name)))
85					}
86					fn visit_bytes<E: serde::de::Error>(self, v: &[u8]) -> Result<Self::Value, E> {
87						TryFrom::try_from(v).map_err(serde::de::Error::custom)
88					}
89					fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
90						std::str::FromStr::from_str(v).map_err(serde::de::Error::custom)
91					}
92				}
93
94				if d.is_human_readable() {
95					d.deserialize_str(Visitor)
96				} else {
97					d.deserialize_bytes(Visitor)
98				}
99			}
100		}
101
102		impl $name {
103			/// Convert into underlying byte array.
104			pub fn to_byte_array(self) -> [u8; $n] {
105				self.0
106			}
107
108			/// Convert from byte array.
109			pub fn from_byte_array(bytes: [u8; $n]) -> Self {
110				Self(bytes)
111			}
112
113			/// Create from byte slice.
114			pub fn from_slice(slice: &[u8]) -> Result<Self, std::array::TryFromSliceError> {
115				Self::try_from(slice)
116			}
117
118			/// Convert into a byte vector.
119			pub fn to_vec(&self) -> Vec<u8> {
120				self.0.to_vec()
121			}
122		}
123	};
124}
125
126/// Extension trait for iterators to add utility methods
127pub trait IteratorExt: Iterator {
128	/// Checks if all elements in the iterator have the same value when passed through the closure.
129	///
130	/// Returns `Some(value)` if all extracted values are equal, `None` otherwise.
131	/// For empty iterators, returns `None`.
132	///
133	/// # Examples
134	/// ```
135	/// use ark::util::IteratorExt;
136	///
137	/// let vec = vec![(1, "a"), (2, "a"), (3, "a")];
138	/// assert_eq!(vec.iter().all_same(|(_, s)| s), Some(&"a"));
139	///
140	/// let vec = vec![(1, "a"), (2, "b"), (3, "c")];
141	/// assert_eq!(vec.iter().all_same(|(_, s)| s), None);
142	/// ```
143	fn all_same<F, T>(self, mut f: F) -> Option<T>
144	where
145		Self: Sized,
146		F: FnMut(&Self::Item) -> T,
147		T: Eq,
148	{
149		let mut iter = self.peekable();
150		let first_item = match iter.next() {
151			None => return None,
152			Some(item) => item,
153		};
154		let first = f(&first_item);
155		if iter.all(|item| f(&item) == first) {
156			Some(first)
157		} else {
158			None
159		}
160	}
161}
162
163impl<I: Iterator> IteratorExt for I {}