strict_encoding/
macros.rs

1// Strict encoding library for deterministic binary serialization.
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Designed in 2019-2025 by Dr Maxim Orlovsky <orlovsky@ubideco.org>
6// Written in 2024-2025 by Dr Maxim Orlovsky <orlovsky@ubideco.org>
7//
8// Copyright (C) 2019-2022 LNP/BP Standards Association.
9// Copyright (C) 2022-2025 Laboratories for Ubiquitous Deterministic Computing (UBIDECO),
10//                         Institute for Distributed and Cognitive Systems (InDCS), Switzerland.
11// Copyright (C) 2019-2025 Dr Maxim Orlovsky.
12// All rights under the above copyrights are reserved.
13//
14// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
15// in compliance with the License. You may obtain a copy of the License at
16//
17//        http://www.apache.org/licenses/LICENSE-2.0
18//
19// Unless required by applicable law or agreed to in writing, software distributed under the License
20// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
21// or implied. See the License for the specific language governing permissions and limitations under
22// the License.
23
24#[macro_export]
25macro_rules! strict_dumb {
26    () => {
27        $crate::StrictDumb::strict_dumb()
28    };
29}
30
31#[macro_export]
32macro_rules! impl_strict_newtype {
33    ($ty:ident, $lib:expr) => {
34        impl_strict_newtype!($ty, $lib, Self($crate::StrictDumb::strict_dumb()));
35    };
36    ($ty:ident, $lib:expr, $dumb:expr) => {
37        impl $crate::StrictDumb for $ty {
38            fn strict_dumb() -> Self { Self::from($dumb) }
39        }
40        impl $crate::StrictType for $ty {
41            const STRICT_LIB_NAME: &'static str = $lib;
42        }
43        impl $crate::StrictProduct for $ty {}
44        impl $crate::StrictTuple for $ty {
45            const FIELD_COUNT: u8 = 1;
46        }
47        impl $crate::StrictEncode for $ty {
48            fn strict_encode<W: $crate::TypedWrite>(&self, writer: W) -> ::std::io::Result<W> {
49                writer.write_newtype::<Self>(&self.0)
50            }
51        }
52        impl $crate::StrictDecode for $ty {
53            fn strict_decode(
54                reader: &mut impl $crate::TypedRead,
55            ) -> Result<Self, $crate::DecodeError> {
56                use $crate::ReadTuple;
57                reader.read_tuple(|r| Ok(Self(r.read_field()?)))
58            }
59        }
60    };
61}
62
63#[macro_export]
64macro_rules! impl_strict_struct {
65    ($ty:ty, $lib:expr; $($field:ident),+ $(,)?) => {
66        impl_strict_struct!($ty, $lib; $($field => $crate::strict_dumb!()),+);
67    };
68    ($ty:ty, $lib:expr; $($field:ident => $dumb:expr),+ $(,)?) => {
69        impl $crate::StrictDumb for $ty {
70            fn strict_dumb() -> Self {
71                Self {
72                    $($field: $dumb),+
73                }
74            }
75        }
76        impl $crate::StrictType for $ty {
77            const STRICT_LIB_NAME: &'static str = $lib;
78        }
79        impl $crate::StrictProduct for $ty {}
80        impl $crate::StrictStruct for $ty {
81            const ALL_FIELDS: &'static [&'static str] = &[$(stringify!($field)),+];
82        }
83        impl $crate::StrictEncode for $ty {
84            fn strict_encode<W: $crate::TypedWrite>(&self, writer: W) -> io::Result<W> {
85                writer.write_struct::<Self>(|w| {
86                    Ok(w
87                        $(.write_field(fname!(stringify!($field)), &self.$field)?)+
88                        .complete())
89                })
90            }
91        }
92        impl $crate::StrictDecode for $ty {
93            fn strict_decode(reader: &mut impl $crate::TypedRead) -> Result<Self, $crate::DecodeError> {
94                reader.read_struct(|r| {
95                    $(let $field = r.read_field(fname!(stringify!($field)))?;)+
96                    Ok(Self { $($field),+ })
97                })
98            }
99        }
100    };
101}
102
103#[macro_export]
104macro_rules! ident {
105    ($name:literal) => {
106        $crate::Ident::from($name)
107    };
108    ($name:expr) => {
109        $crate::Ident::try_from($name).expect("hardcoded parameter is not a valid identifier name")
110    };
111    ($fmt:literal, $($arg:expr),+) => {{
112        $crate::Ident::try_from(format!($fmt, $($arg),+))
113            .unwrap_or_else(|_| panic!("invalid identifier from formatter"))
114    }};
115}
116
117#[macro_export]
118macro_rules! tn {
119    ($name:literal) => {
120        $crate::TypeName::from($name)
121    };
122    ($name:expr) => {
123        $crate::TypeName::try_from($name).expect("hardcoded parameter is not a valid type name")
124    };
125    ($name:literal, $($arg:expr),+) => {{
126        $crate::Ident::try_from(format!($fmt, $($arg),+))
127            .unwrap_or_else(|_| panic!("invalid type name from formatter"))
128    }};
129}
130
131#[macro_export]
132macro_rules! vname {
133    ($name:literal) => {
134        $crate::VariantName::from($name)
135    };
136    ($name:expr) => {
137        $crate::VariantName::try_from($name)
138            .expect("hardcoded parameter is not a valid variant name")
139    };
140}
141
142#[macro_export]
143macro_rules! fname {
144    ($name:literal) => {
145        $crate::FieldName::from($name)
146    };
147    ($name:expr) => {
148        $crate::FieldName::try_from($name).expect("hardcoded parameter is not a valid field name")
149    };
150}
151
152#[macro_export]
153macro_rules! libname {
154    ($name:literal) => {
155        $crate::LibName::from($name)
156    };
157    ($name:expr) => {
158        $crate::LibName::try_from($name).expect("hardcoded parameter is not a valid library name")
159    };
160}