strict_encoding/
macros.rs

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