ddk_messages/
ser_macros.rs

1//! Set of macro to help implementing the [`lightning::util::ser::Writeable`] trait.
2
3/// Writes a field to a writer.
4#[macro_export]
5macro_rules! field_write {
6    ($stream: expr, $field: expr, writeable) => {
7        $field.write($stream)?;
8    };
9    ($stream: expr, $field: expr, {cb_writeable, $w_cb: expr, $r_cb: expr}) => {
10        $w_cb(&$field, $stream)?;
11    };
12    ($stream: expr, $field: expr, string) => {
13        $crate::ser_impls::write_string(&$field, $stream)?;
14    };
15    ($stream: expr, $field: expr, vec) => {
16        $crate::ser_impls::write_vec(&$field, $stream)?;
17    };
18    ($stream: expr, $field: expr, {vec_cb, $w_cb: expr, $r_cb: expr}) => {
19        $crate::ser_impls::write_vec_cb(&$field, $stream, &$w_cb)?;
20    };
21    ($stream: expr, $field: expr, {vec_u16_cb, $w_cb: expr, $r_cb: expr}) => {
22        $crate::ser_impls::write_vec_u16_cb(&$field, $stream, &$w_cb)?;
23    };
24    ($stream: expr, $field: expr, float) => {
25        $crate::ser_impls::write_f64($field, $stream)?;
26    };
27    ($stream: expr, $field: expr, usize) => {
28        $crate::ser_impls::write_usize(&$field, $stream)?;
29    };
30    ($stream: expr, $field: expr, SignedAmount) => {
31        $crate::ser_impls::write_signed_amount(&$field, $stream)?;
32    };
33    ($stream: expr, $field: expr, {option_cb, $w_cb: expr, $r_cb: expr}) => {
34        $crate::ser_impls::write_option_cb(&$field, $stream, &$w_cb)?;
35    };
36    ($stream: expr, $field: expr, option) => {
37        $crate::ser_impls::write_option(&$field, $stream)?;
38    };
39}
40
41/// Reads a field from a reader.
42#[macro_export]
43macro_rules! field_read {
44    ($stream: expr, writeable) => {
45        Readable::read($stream)?
46    };
47    ($stream: expr, {cb_writeable, $w_cb: expr, $r_cb: expr}) => {
48        $r_cb($stream)?
49    };
50    ($stream: expr, string) => {
51        $crate::ser_impls::read_string($stream)?
52    };
53    ($stream: expr, vec) => {
54        $crate::ser_impls::read_vec($stream)?
55    };
56    ($stream: expr, {vec_cb, $w_cb: expr, $r_cb: expr}) => {
57        $crate::ser_impls::read_vec_cb($stream, &$r_cb)?
58    };
59    ($stream: expr, {vec_u16_cb, $w_cb: expr, $r_cb: expr}) => {
60        $crate::ser_impls::read_vec_u16_cb($stream, &$r_cb)?
61    };
62    ($stream: expr, float) => {
63        $crate::ser_impls::read_f64($stream)?
64    };
65    ($stream: expr, usize) => {
66        $crate::ser_impls::read_usize($stream)?
67    };
68    ($stream: expr, SignedAmount) => {
69        $crate::ser_impls::read_signed_amount($stream)?
70    };
71    ($stream: expr, {option_cb, $w_cb: expr, $r_cb: expr}) => {
72        $crate::ser_impls::read_option_cb($stream, &$r_cb)?
73    };
74    ($stream: expr, option) => {
75        $crate::ser_impls::read_option($stream)?
76    };
77}
78
79/// Implements the [`lightning::util::ser::Writeable`] trait for a struct available
80/// in this crate.
81#[macro_export]
82macro_rules! impl_dlc_writeable {
83    ($st:ident, {$(($field: ident, $fieldty: tt)), *} ) => {
84        impl Writeable for $st {
85			fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::lightning::io::Error> {
86				$(
87                    field_write!(w, self.$field, $fieldty);
88                )*
89				Ok(())
90            }
91        }
92
93        impl Readable for $st {
94			fn read<R: lightning::io::Read>(r: &mut R) -> Result<Self, DecodeError> {
95                Ok(Self {
96                    $(
97                        $field: field_read!(r, $fieldty),
98                    )*
99                })
100            }
101        }
102    };
103    // Version with type_id - writes/reads type_id as first field
104    ($st:ident, $type_const:ident, {$(($field: ident, $fieldty: tt)), *} ) => {
105        impl Writeable for $st {
106			fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::lightning::io::Error> {
107                // Write type_id first
108                $type_const.write(w)?;
109				$(
110                    field_write!(w, self.$field, $fieldty);
111                )*
112				Ok(())
113            }
114        }
115
116        impl Readable for $st {
117			fn read<R: lightning::io::Read>(r: &mut R) -> Result<Self, DecodeError> {
118                // Read and verify type_id first
119                let type_id: u16 = Readable::read(r)?;
120                if type_id != $type_const {
121                    return Err(DecodeError::UnknownRequiredFeature);
122                }
123                Ok(Self {
124                    $(
125                        $field: field_read!(r, $fieldty),
126                    )*
127                })
128            }
129        }
130    };
131}
132
133/// Implements the [`lightning::util::ser::Writeable`] trait for a struct external
134/// to this crate.
135#[macro_export]
136macro_rules! impl_dlc_writeable_external {
137    ($st: ident $(< $gen: ident $(< $gen2: ident >)?> )? , $name: ident, {$(($field: ident, $fieldty: tt)), *} ) => {
138        /// Module containing write and read functions for $name
139        pub mod $name {
140            use super::*;
141            use lightning::ln::msgs::DecodeError;
142            use lightning::util::ser::Writer;
143            /// Function to write $name
144            pub fn write<W: Writer>($name: &$st<$($gen$(<$gen2>)?)?>, w: &mut W) -> Result<(), ::lightning::io::Error> {
145                $(
146                    field_write!(w, $name.$field, $fieldty);
147                )*
148                Ok(())
149            }
150
151            /// Function to read $name
152            pub fn read<R: lightning::io::Read>(r: &mut R) -> Result<$st<$($gen$(<$gen2>)?)?>, DecodeError> {
153                Ok($st {
154                    $(
155                        $field: field_read!(r, $fieldty),
156                    )*
157                })
158            }
159        }
160    };
161}
162
163/// Implements the [`lightning::util::ser::Writeable`] trait for an enum external
164/// to this crate.
165#[macro_export]
166macro_rules! impl_dlc_writeable_external_enum {
167    ($st:ident $(<$gen: ident>)?, $name: ident, $(($variant_id: expr, $variant_name: ident, $variant_mod: ident)), * ) => {
168        mod $name {
169            use super::*;
170
171			pub fn write<W: Writer>($name: &$st$(<$gen>)?, w: &mut W) -> Result<(), ::lightning::io::Error> {
172                match $name {
173                    $($st::$variant_name(ref field) => {
174                        let id : u8 = $variant_id;
175                        id.write(w)?;
176                        $variant_mod::write(field, w)?;
177                    }),*
178                };
179				Ok(())
180            }
181
182			pub fn read<R: lightning::io::Read>(r: &mut R) -> Result<$st$(<$gen>)?, DecodeError> {
183                let id: u8 = Readable::read(r)?;
184                match id {
185                    $($variant_id => {
186						Ok($st::$variant_name($variant_mod::read(r)?))
187					}),*
188					_ => {
189						Err(DecodeError::UnknownRequiredFeature)
190					},
191                }
192            }
193        }
194    };
195}
196
197/// Implements the [`lightning::util::ser::Writeable`] trait for an enum as a TLV.
198#[macro_export]
199macro_rules! impl_dlc_writeable_enum_as_tlv {
200    ($st:ident, $(($variant_id: expr, $variant_name: ident)), *;) => {
201        impl Writeable for $st {
202			fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::lightning::io::Error> {
203                match self {
204                    $($st::$variant_name(ref field) => {
205                        $crate::ser_impls::BigSize($variant_id as u64).write(w)?;
206                        $crate::ser_impls::BigSize(field.serialized_length() as u64).write(w)?;
207                        field.write(w)?;
208                    }),*
209                };
210				Ok(())
211            }
212        }
213
214        impl Readable for $st {
215			fn read<R: lightning::io::Read>(r: &mut R) -> Result<Self, DecodeError> {
216                let id: $crate::ser_impls::BigSize = Readable::read(r)?;
217                match id.0 {
218                    $($variant_id => {
219                        let _ : $crate::ser_impls::BigSize = Readable::read(r)?;
220						Ok($st::$variant_name(Readable::read(r)?))
221					}),*
222					_ => {
223						Err(DecodeError::UnknownRequiredFeature)
224					},
225                }
226            }
227        }
228    };
229}
230
231/// Implements the [`lightning::util::ser::Writeable`] trait for an enum.
232#[macro_export]
233macro_rules! impl_dlc_writeable_enum {
234    ($st:ident, $(($tuple_variant_id: expr, $tuple_variant_name: ident)), *;
235    $(($variant_id: expr, $variant_name: ident, {$(($field: ident, $fieldty: tt)),*})), *;
236    $(($external_variant_id: expr, $external_variant_name: ident, $write_cb: expr, $read_cb: expr)), *;
237    $(($simple_variant_id: expr, $simple_variant_name: ident)), *) => {
238        impl Writeable for $st {
239			fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::lightning::io::Error> {
240                match self {
241                    $($st::$tuple_variant_name(ref field) => {
242                        let id : u8 = $tuple_variant_id;
243                        id.write(w)?;
244                        field.write(w)?;
245                    }),*
246                    $($st::$variant_name { $(ref $field),* } => {
247                        let id : u8 = $variant_id;
248                        id.write(w)?;
249                        $(
250                            field_write!(w, $field, $fieldty);
251                        )*
252                    }),*
253                    $($st::$external_variant_name(ref field) => {
254                        let id : u8 = $external_variant_id;
255                        id.write(w)?;
256                        $write_cb(field, w)?;
257                    }),*
258                    $($st::$simple_variant_name => {
259                        let id : u8 = $simple_variant_id;
260                        id.write(w)?;
261                    }),*
262                };
263				Ok(())
264            }
265        }
266
267        impl Readable for $st {
268			fn read<R: lightning::io::Read>(r: &mut R) -> Result<Self, DecodeError> {
269                let id: u8 = Readable::read(r)?;
270                match id {
271                    $($tuple_variant_id => {
272						Ok($st::$tuple_variant_name(Readable::read(r)?))
273					}),*
274                    $($variant_id => {
275                        Ok($st::$variant_name {
276                            $(
277                                $field: field_read!(r, $fieldty)
278                            ),*
279                        })
280                    }),*
281                    $($external_variant_id => {
282						Ok($st::$external_variant_name($read_cb(r)?))
283					}),*
284                    $($simple_variant_id => {
285						Ok($st::$simple_variant_name)
286					}),*
287					_ => {
288						Err(DecodeError::UnknownRequiredFeature)
289					},
290                }
291            }
292        }
293    };
294}