copy_impl/lib.rs
1//Copyright (c) 2021-2024 #UlinProject (Denis Kotlyarov)
2
3
4//-----------------------------------------------------------------------------
5//Licensed under the Apache License, Version 2.0 (the "License");
6//you may not use this file except in compliance with the License.
7//You may obtain a copy of the License at
8
9// http://www.apache.org/licenses/LICENSE-2.0
10
11//Unless required by applicable law or agreed to in writing, software
12//distributed under the License is distributed on an "AS IS" BASIS,
13//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14//See the License for the specific language governing permissions and
15// limitations under the License.
16//-----------------------------------------------------------------------------
17
18// or
19
20//-----------------------------------------------------------------------------
21//Permission is hereby granted, free of charge, to any person obtaining a copy
22//of this software and associated documentation files (the "Software"), to deal
23//in the Software without restriction, including without limitation the rights
24//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25//copies of the Software, and to permit persons to whom the Software is
26//furnished to do so, subject to the following conditions:
27
28//The above copyright notice and this permission notice shall be included in all
29//copies or substantial portions of the Software.
30
31//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
37//SOFTWARE.
38
39/*!
40Macro for effortlessly duplicating impl block code across various types in Rust.
41
42## Example:
43
44```rust
45use std::{error::Error, fmt::Write};
46use copy_impl::copy_impl;
47
48struct CustomNum<T>(T);
49struct UncheckedCustomNum<T>(T);
50
51copy_impl! {
52 impl (CustomNum<i8>),
53 impl (CustomNum<i16>),
54 impl (CustomNum<i32>),
55 impl (UncheckedCustomNum<i8>),
56 impl (UncheckedCustomNum<i16>) {
57 pub fn write_to(&self, mut w: impl Write) -> Result<(), std::fmt::Error> {
58 write!(w, "{}", self.0)
59 }
60 }
61}
62
63fn main() -> Result<(), Box<dyn Error>> {
64 let mut tbuff = String::new();
65 CustomNum(1i8).write_to(&mut tbuff)?;
66 CustomNum(2i16).write_to(&mut tbuff)?;
67 CustomNum(3i32).write_to(&mut tbuff)?;
68
69 UncheckedCustomNum(4i8).write_to(&mut tbuff)?;
70 UncheckedCustomNum(5i16).write_to(&mut tbuff)?;
71 // UncheckedCustomNum(6i32).write_to(&mut tbuff)?;
72 /*
73 no method named `write_to` found for struct `UncheckedCustomNum<i32>` in the current scope
74 the method was found for
75 - `UncheckedCustomNum<i8>`
76 - `UncheckedCustomNum<i16>`
77 */
78
79 assert_eq!(tbuff, "12345");
80
81 Ok(())
82}
83```
84
85*/
86
87#![no_std]
88
89///
90/// Macro for easily copying impl block code for different types.
91/// ```rust
92/// use std::{error::Error, fmt::Write};
93/// use copy_impl::copy_impl;
94///
95/// struct CustomNum<T>(T);
96/// struct UncheckedCustomNum<T>(T);
97///
98/// copy_impl! {
99/// impl (CustomNum<i8>),
100/// impl (CustomNum<i16>),
101/// impl (CustomNum<i32>),
102/// impl (UncheckedCustomNum<i8>),
103/// impl (UncheckedCustomNum<i16>) {
104/// pub fn write_to(&self, mut w: impl Write) -> Result<(), std::fmt::Error> {
105/// write!(w, "{}", self.0)
106/// }
107/// }
108/// }
109/// ```
110#[macro_export]
111macro_rules! copy_impl {
112 [ /* COLD_START */
113 impl $(<$($p_impl:tt)*>)? ($($impl:tt)*) $(where ($($where:tt)*))?
114
115 $($all:tt)*
116 ] => {
117 $crate::copy_impl! {
118 [ // the COLD_START!
119 [
120 /* COPY_IMPL_DATA */
121 [
122 [ $($($p_impl)*)? ] // <T>
123 [ $($impl)* ] // impldata
124 [ $($($where)*)? ]
125 ]
126 ]
127 ]
128
129 $($all)*
130 }
131 };
132
133 [ /* HOT_CONTINUE */
134 [
135 [
136 /* COPY_IMPL_DATA */
137 $($all_copy_impl_data:tt)+
138 ]
139 ]
140
141 , impl $(<$($p_impl:tt)*>)? ($($impl:tt)*) $(where ($($where:tt)*))?
142
143 $($all:tt)*
144 ] => {
145 $crate::copy_impl! {
146 [
147 [
148 /* COPY_IMPL_DATA */
149 $($all_copy_impl_data)+
150
151 [
152 [ $($($p_impl)*)? ] // <T>
153 [ $($impl)* ] // impldata
154 [ $($($where)*)? ]
155 ]
156 /* all */
157 ]
158 ]
159
160 $($all)*
161 }
162 };
163
164 [ /* skip (,) */
165 [
166 [
167 /* COPY_IMPL_DATA */
168 $($all_copy_impl_data:tt)*
169 ]
170 ]
171 ,
172
173 $($all:tt)*
174 ] => {
175 $crate::copy_impl! {
176 [
177 [
178 /* COPY_IMPL_DATA */
179 $($all_copy_impl_data)*
180 ]
181 ]
182
183 $($all)*
184 }
185 };
186
187 [ // END HEADERS(IMPL), the CODE!
188 [
189 [ /* COPY_IMPL_DATA */
190 $([
191 [ $($p_impl:tt)* ]
192 [ $($impl:tt)* ]
193 [ $($where:tt)* ]
194 ])+
195 ]
196 ]
197 { $($code:tt)* }
198
199 $(
200 ; $($all:tt)*
201 )?
202 ] => {
203 $crate::__internal_make_copy_impl! {
204 []
205 [$($code)*] ->
206
207 $([
208 [$($p_impl)*] // <T>
209 [$($impl)*] // impldata
210 [$($where)*]
211 ])+
212 }
213
214 $(
215 $crate::copy_impl! {
216 $($all)*
217 }
218 )?
219 };
220
221 [ $(;)? ] => {};
222
223 [ /* UNK */ $($all:tt)+ ] => {
224 compile_error!(stringify!(
225 $($all)+
226 ));
227 }
228}
229
230#[macro_export]
231#[doc(hidden)]
232macro_rules! __internal_make_copy_impl {
233 [
234 [
235 /* RARRAY */
236 $($rarray:tt)*
237 ]
238 [$($code:tt)*] ->
239
240 [ [$($p_impl:tt)*][$($impl:tt)*][$($where:tt)*] ]
241 $($unk:tt)*
242 ] => {
243 $crate::__internal_make_copy_impl! {
244 [
245 $($rarray)*
246 [
247 [$($p_impl)*]
248 [$($impl)*]
249 [$($where)*]
250 [$($code)*]
251 ]
252 ]
253 [$($code)*] ->
254
255 $($unk)*
256 }
257 };
258 [
259 [
260 $([
261 [$($p_impl:tt)*]
262 [$($impl:tt)*]
263 [$($where:tt)*]
264 [$($code:tt)*]
265 ])*
266 ]
267 [$($_code:tt)*] ->
268 ] => {
269 $(
270 impl $(<$($p_impl)*>)? $($impl)* $(where $($where)*)? {
271 $($code)*
272 }
273 )*
274 }
275}