bitcoin_ext/
serde.rs

1
2pub mod encodable {
3	//! Module to bytes- or hex-encode bitcoin objects using the bitcoin encoding
4	//!
5	//! It is not recommended to use this for types that already have a string-based
6	//! serde encoding like `PublicKey` or the hashes like `Txid`.
7
8	use std::fmt;
9	use std::borrow::Cow;
10	use std::marker::PhantomData;
11
12	use serde::{de, ser, Deserialize, Deserializer, Serialize, Serializer};
13
14	use bitcoin::consensus::encode::{self, Decodable, Encodable};
15
16	struct SerWrapper<'a, T>(&'a T);
17
18	impl<'a, T: Encodable> Serialize for SerWrapper<'a, T> {
19		fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
20			if s.is_human_readable() {
21				s.serialize_str(&encode::serialize_hex(&self.0))
22			} else {
23				s.serialize_bytes(&encode::serialize(&self.0))
24			}
25		}
26	}
27
28	struct DeWrapper<T>(T);
29
30	impl<'de, T: Decodable> Deserialize<'de> for DeWrapper<T> {
31		fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
32			if d.is_human_readable() {
33				let s = <Cow<'de, str>>::deserialize(d)?;
34				Ok(DeWrapper(encode::deserialize_hex(s.as_ref())
35					.map_err(serde::de::Error::custom)?))
36			} else {
37				let b = <Cow<'de, [u8]>>::deserialize(d)?;
38				Ok(DeWrapper(encode::deserialize(b.as_ref())
39					.map_err(serde::de::Error::custom)?))
40			}
41		}
42	}
43
44	pub fn serialize<T, S>(v: &T, s: S) -> Result<S::Ok, S::Error>
45	where
46		T: Encodable + Clone,
47		S: Serializer,
48	{
49		SerWrapper(v).serialize(s)
50	}
51
52	pub fn deserialize<'d, T: Decodable, D: Deserializer<'d>>(d: D) -> Result<T, D::Error> {
53		Ok(DeWrapper::<T>::deserialize(d)?.0)
54	}
55
56	pub mod vec {
57		use super::*;
58
59		pub fn serialize<T: Encodable, S: Serializer>(v: &[T], s: S) -> Result<S::Ok, S::Error> {
60			let mut seq = s.serialize_seq(Some(v.len()))?;
61			for item in v {
62				ser::SerializeSeq::serialize_element(&mut seq, &SerWrapper(item))?;
63			}
64			ser::SerializeSeq::end(seq)
65		}
66
67		pub fn deserialize<'d, T: Decodable, D: Deserializer<'d>>(d: D) -> Result<Vec<T>, D::Error> {
68			struct Visitor<T>(PhantomData<T>);
69
70			impl<'de, T: Decodable> de::Visitor<'de> for Visitor<T> {
71				type Value = Vec<T>;
72
73				fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
74					f.write_str("a vector of bitcoin-encoded objects")
75				}
76
77				fn visit_seq<A: de::SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
78					let mut ret = Vec::with_capacity(seq.size_hint().unwrap_or_default());
79					while let Some(v) = seq.next_element::<DeWrapper<T>>()? {
80						ret.push(v.0);
81					}
82					Ok(ret)
83				}
84			}
85			d.deserialize_seq(Visitor(PhantomData))
86		}
87	}
88
89	pub mod cow {
90		use super::*;
91
92		pub fn serialize<'a, T, S>(v: &Cow<'a, T>, s: S) -> Result<S::Ok, S::Error>
93		where
94			T: Encodable + Clone,
95			S: Serializer,
96		{
97			SerWrapper(v.as_ref()).serialize(s)
98		}
99
100		pub fn deserialize<'d, T, D>(d: D) -> Result<Cow<'static, T>, D::Error>
101		where
102			T: Decodable + Clone,
103			D: Deserializer<'d>,
104		{
105			Ok(Cow::Owned(DeWrapper::<T>::deserialize(d)?.0))
106		}
107	}
108}
109
110
111#[cfg(test)]
112mod test {
113	use bitcoin::Transaction;
114
115	#[test]
116	fn test_serde_encodable() {
117		let hex = "0200000000010151d0aa3be0ee0a27b2400f1eb9ddc692aace09c5d197475bceca711e0ba7ce320000000000ffffffff03ca2f03000000000022512043445259f5c414ce3fb6bd43d7caf8048f410351818fe4f0a26f95d010f653b7791b08000000000022512043445259f5c414ce3fb6bd43d7caf8048f410351818fe4f0a26f95d010f653b74a010000000000002200204ae81572f06e1b88fd5ced7a1a000945432e83e1551e6f721ee9c00b8cc3326001408abb6b9c0a21c90d3b42e059f94536588b1a99288abfdb79bbcfd548f7e3bb105e52c5cd8cff388679df825a7d5f93004dd416b81cfa0af1c814df79d381994c00000000";
118		let tx = bitcoin::consensus::encode::deserialize_hex::<Transaction>(&hex).unwrap();
119		let raw = bitcoin::consensus::encode::serialize(&tx);
120		assert_eq!(raw.len(), 248);
121
122		#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
123		struct S {
124			#[serde(with = "crate::serde::encodable")]
125			tx: Transaction,
126		}
127
128		let s = S { tx };
129		let json = serde_json::to_string(&s).unwrap();
130		assert_eq!(json.len(), 505);
131		assert_eq!(json, "{\"tx\":\"0200000000010151d0aa3be0ee0a27b2400f1eb9ddc692aace09c5d197475bceca711e0ba7ce320000000000ffffffff03ca2f03000000000022512043445259f5c414ce3fb6bd43d7caf8048f410351818fe4f0a26f95d010f653b7791b08000000000022512043445259f5c414ce3fb6bd43d7caf8048f410351818fe4f0a26f95d010f653b74a010000000000002200204ae81572f06e1b88fd5ced7a1a000945432e83e1551e6f721ee9c00b8cc3326001408abb6b9c0a21c90d3b42e059f94536588b1a99288abfdb79bbcfd548f7e3bb105e52c5cd8cff388679df825a7d5f93004dd416b81cfa0af1c814df79d381994c00000000\"}");
132
133		let s_from_json = serde_json::from_str(&json).unwrap();
134		assert_eq!(s, s_from_json);
135
136		let rmp = rmp_serde::to_vec(&s).unwrap();
137		assert_eq!(rmp.len(), 251);
138		let s_from_rmp = rmp_serde::from_slice(&rmp).unwrap();
139		assert_eq!(s, s_from_rmp);
140
141		let nrmp = rmp_serde::to_vec_named(&s).unwrap();
142		assert_eq!(nrmp.len(), 254);
143		let s_from_nrmp = rmp_serde::from_slice(&nrmp).unwrap();
144		assert_eq!(s, s_from_nrmp);
145	}
146}
147