bitcoin/util/psbt/
macros.rs

1// Rust Bitcoin Library
2// Written by
3//   The Rust Bitcoin developers
4//
5// To the extent possible under law, the author(s) have dedicated all
6// copyright and related and neighboring rights to this software to
7// the public domain worldwide. This software is distributed without
8// any warranty.
9//
10// You should have received a copy of the CC0 Public Domain Dedication
11// along with this software.
12// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
13//
14
15#[allow(unused_macros)]
16macro_rules! hex_psbt {
17    ($s:expr) => { $crate::consensus::deserialize(&<Vec<u8> as $crate::hashes::hex::FromHex>::from_hex($s).unwrap()) };
18}
19
20macro_rules! merge {
21    ($thing:ident, $slf:ident, $other:ident) => {
22        if let (&None, Some($thing)) = (&$slf.$thing, $other.$thing) {
23            $slf.$thing = Some($thing);
24        }
25    };
26}
27
28macro_rules! impl_psbt_de_serialize {
29    ($thing:ty) => {
30        impl_psbt_serialize!($thing);
31        impl_psbt_deserialize!($thing);
32    };
33}
34
35macro_rules! impl_psbt_deserialize {
36    ($thing:ty) => {
37        impl $crate::util::psbt::serialize::Deserialize for $thing {
38            fn deserialize(bytes: &[u8]) -> Result<Self, $crate::consensus::encode::Error> {
39                $crate::consensus::deserialize(&bytes[..])
40            }
41        }
42    };
43}
44
45macro_rules! impl_psbt_serialize {
46    ($thing:ty) => {
47        impl $crate::util::psbt::serialize::Serialize for $thing {
48            fn serialize(&self) -> Vec<u8> {
49                $crate::consensus::serialize(self)
50            }
51        }
52    };
53}
54
55macro_rules! impl_psbtmap_consensus_encoding {
56    ($thing:ty) => {
57        impl $crate::consensus::Encodable for $thing {
58            fn consensus_encode<S: ::std::io::Write>(
59                &self,
60                mut s: S,
61            ) -> Result<usize, ::std::io::Error> {
62                let mut len = 0;
63                for pair in $crate::util::psbt::Map::get_pairs(self)? {
64                    len += $crate::consensus::Encodable::consensus_encode(
65                        &pair,
66                        &mut s,
67                    )?;
68                }
69
70                Ok(len + $crate::consensus::Encodable::consensus_encode(&0x00_u8, s)?)
71            }
72        }
73    };
74}
75
76macro_rules! impl_psbtmap_consensus_decoding {
77    ($thing:ty) => {
78        impl $crate::consensus::Decodable for $thing {
79            fn consensus_decode<D: ::std::io::Read>(
80                mut d: D,
81            ) -> Result<Self, $crate::consensus::encode::Error> {
82                let mut rv: Self = ::std::default::Default::default();
83
84                loop {
85                    match $crate::consensus::Decodable::consensus_decode(&mut d) {
86                        Ok(pair) => $crate::util::psbt::Map::insert_pair(&mut rv, pair)?,
87                        Err($crate::consensus::encode::Error::Psbt($crate::util::psbt::Error::NoMorePairs)) => return Ok(rv),
88                        Err(e) => return Err(e),
89                    }
90                }
91            }
92        }
93    };
94}
95
96macro_rules! impl_psbtmap_consensus_enc_dec_oding {
97    ($thing:ty) => {
98        impl_psbtmap_consensus_decoding!($thing);
99        impl_psbtmap_consensus_encoding!($thing);
100    };
101}
102
103#[cfg_attr(rustfmt, rustfmt_skip)]
104macro_rules! impl_psbt_insert_pair {
105    ($slf:ident.$unkeyed_name:ident <= <$raw_key:ident: _>|<$raw_value:ident: $unkeyed_value_type:ty>) => {
106        if $raw_key.key.is_empty() {
107            if $slf.$unkeyed_name.is_none() {
108                let val: $unkeyed_value_type = $crate::util::psbt::serialize::Deserialize::deserialize(&$raw_value)?;
109                $slf.$unkeyed_name = Some(val)
110            } else {
111                return Err($crate::util::psbt::Error::DuplicateKey($raw_key).into());
112            }
113        } else {
114            return Err($crate::util::psbt::Error::InvalidKey($raw_key).into());
115        }
116    };
117    ($slf:ident.$keyed_name:ident <= <$raw_key:ident: $keyed_key_type:ty>|<$raw_value:ident: $keyed_value_type:ty>) => {
118        if !$raw_key.key.is_empty() {
119            let key_val: $keyed_key_type = $crate::util::psbt::serialize::Deserialize::deserialize(&$raw_key.key)?;
120            match $slf.$keyed_name.entry(key_val) {
121                ::std::collections::btree_map::Entry::Vacant(empty_key) => {
122                    let val: $keyed_value_type = $crate::util::psbt::serialize::Deserialize::deserialize(&$raw_value)?;
123                    empty_key.insert(val);
124                }
125                ::std::collections::btree_map::Entry::Occupied(_) => return Err($crate::util::psbt::Error::DuplicateKey($raw_key).into()),
126            }
127        } else {
128            return Err($crate::util::psbt::Error::InvalidKey($raw_key).into());
129        }
130    };
131}
132
133
134#[cfg_attr(rustfmt, rustfmt_skip)]
135macro_rules! impl_psbt_get_pair {
136    ($rv:ident.push($slf:ident.$unkeyed_name:ident as <$unkeyed_typeval:expr, _>|<$unkeyed_value_type:ty>)) => {
137        if let Some(ref $unkeyed_name) = $slf.$unkeyed_name {
138            $rv.push($crate::util::psbt::raw::Pair {
139                key: $crate::util::psbt::raw::Key {
140                    type_value: $unkeyed_typeval,
141                    key: vec![],
142                },
143                value: $crate::util::psbt::serialize::Serialize::serialize($unkeyed_name),
144            });
145        }
146    };
147    ($rv:ident.push($slf:ident.$keyed_name:ident as <$keyed_typeval:expr, $keyed_key_type:ty>|<$keyed_value_type:ty>)) => {
148        for (key, val) in &$slf.$keyed_name {
149            $rv.push($crate::util::psbt::raw::Pair {
150                key: $crate::util::psbt::raw::Key {
151                    type_value: $keyed_typeval,
152                    key: $crate::util::psbt::serialize::Serialize::serialize(key),
153                },
154                value: $crate::util::psbt::serialize::Serialize::serialize(val),
155            });
156        }
157    };
158}
159
160// macros for serde of hashes
161macro_rules! impl_psbt_hash_de_serialize {
162    ($hash_type:ty) => {
163        impl_psbt_hash_serialize!($hash_type);
164        impl_psbt_hash_deserialize!($hash_type);
165    };
166}
167
168macro_rules! impl_psbt_hash_deserialize {
169    ($hash_type:ty) => {
170        impl $crate::util::psbt::serialize::Deserialize for $hash_type {
171            fn deserialize(bytes: &[u8]) -> Result<Self, $crate::consensus::encode::Error> {
172                <$hash_type>::from_slice(&bytes[..]).map_err(|e| {
173                    $crate::util::psbt::Error::from(e).into()
174                })
175            }
176        }
177    };
178}
179
180macro_rules! impl_psbt_hash_serialize {
181    ($hash_type:ty) => {
182        impl $crate::util::psbt::serialize::Serialize for $hash_type {
183            fn serialize(&self) -> Vec<u8> {
184                self.into_inner().to_vec()
185            }
186        }
187    };
188}