40
40
//! particularity: iterating on these types yields clones of the items and not references.** This
41
41
//! can be particularly handy when using a React-like framework.
42
42
//!
43
+ //! ## Example
44
+ //!
45
+ //! As an example, here is an implementation of a macro called `html_input! {}` which allows its
46
+ //! user to build an `<input>` HTML node:
47
+ //!
48
+ //! ```
49
+ //! // In the host library source code:
50
+ //!
51
+ //! use implicit_clone::ImplicitClone;
52
+ //! use implicit_clone::unsync::{IArray, IString};
53
+ //!
54
+ //! macro_rules! html_input {
55
+ //! (<input $(type={$ty:expr})? $(name={$name:expr})? $(value={$value:expr})?>) => {{
56
+ //! let mut input = Input::new();
57
+ //! $(input.set_type($ty);)*
58
+ //! $(input.set_name($name);)*
59
+ //! $(input.set_value($value);)*
60
+ //! input
61
+ //! }}
62
+ //! }
63
+ //!
64
+ //! #[derive(Clone)]
65
+ //! pub struct Input {
66
+ //! ty: IString,
67
+ //! name: Option<IString>,
68
+ //! value: Option<IString>,
69
+ //! }
70
+ //!
71
+ //! impl ImplicitClone for Input {}
72
+ //!
73
+ //! impl Input {
74
+ //! pub fn new() -> Self {
75
+ //! Self {
76
+ //! ty: IString::Static("text"),
77
+ //! name: None,
78
+ //! value: None,
79
+ //! }
80
+ //! }
81
+ //!
82
+ //! pub fn set_type(&mut self, ty: impl Into<IString>) {
83
+ //! self.ty = ty.into();
84
+ //! }
85
+ //!
86
+ //! pub fn set_name(&mut self, name: impl Into<IString>) {
87
+ //! self.name.replace(name.into());
88
+ //! }
89
+ //!
90
+ //! pub fn set_value(&mut self, value: impl Into<IString>) {
91
+ //! self.value.replace(value.into());
92
+ //! }
93
+ //! }
94
+ //!
95
+ //! impl std::fmt::Display for Input {
96
+ //! fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97
+ //! write!(f, "<input type=\"{}\"", self.ty)?;
98
+ //! if let Some(name) = self.name.as_ref() {
99
+ //! write!(f, " name=\"{}\"", name)?;
100
+ //! }
101
+ //! if let Some(value) = self.value.as_ref() {
102
+ //! write!(f, " value=\"{}\"", value)?;
103
+ //! }
104
+ //! write!(f, ">")
105
+ //! }
106
+ //! }
107
+ //!
108
+ //! // In the user's source code:
109
+ //!
110
+ //! fn component(age: &IString) -> IArray<Input> {
111
+ //! // `age` is implicitly cloned to the 2 different inputs
112
+ //! let input1 = html_input!(<input name={"age"} value={age}>);
113
+ //! let input2 = html_input!(<input name={"age"} value={age}>);
114
+ //!
115
+ //! IArray::from(vec![input1, input2])
116
+ //! }
117
+ //!
118
+ //! let age = IString::from(20.to_string());
119
+ //! let output = component(&age);
120
+ //! let output_str = output
121
+ //! .iter()
122
+ //! .map(|x| x.to_string())
123
+ //! .collect::<Vec<_>>()
124
+ //! .join("");
125
+ //!
126
+ //! assert_eq!(
127
+ //! output_str,
128
+ //! r#"<input type="text" name="age" value="20"><input type="text" name="age" value="20">"#,
129
+ //! );
130
+ //! ```
131
+ //!
43
132
//! [std::marker::Copy]: https://doc.rust-lang.org/std/marker/trait.Copy.html
44
133
//! [std::clone::Clone]: https://doc.rust-lang.org/std/clone/trait.Clone.html
45
134
//! [std::rc::Rc]: https://doc.rust-lang.org/std/rc/struct.Rc.html
@@ -170,18 +259,7 @@ macro_rules! imap_deconstruct {
170
259
#[ cfg( test) ]
171
260
mod test {
172
261
use super :: * ;
173
-
174
- fn host_library < T : ImplicitClone > ( value : & T ) -> T {
175
- value. clone ( )
176
- }
177
-
178
- macro_rules! host_library {
179
- ( $a: expr) => {
180
- host_library( & $a)
181
- } ;
182
- }
183
-
184
- struct NonImplicitCloneType ;
262
+ use static_assertions:: * ;
185
263
186
264
#[ test]
187
265
fn custom ( ) {
@@ -190,17 +268,14 @@ mod test {
190
268
191
269
impl ImplicitClone for ImplicitCloneType { }
192
270
193
- host_library ! ( ImplicitCloneType ) ;
271
+ assert_impl_all ! ( ImplicitCloneType : ImplicitClone ) ;
194
272
}
195
273
196
274
#[ test]
197
275
fn copy_types ( ) {
198
- fn assert_copy < T : Copy > ( _: T ) { }
199
-
200
276
macro_rules! test_all {
201
277
( $( $t: ty) ,* $( , ) ?) => {
202
- $( host_library!( <$t>:: default ( ) ) ; ) *
203
- $( assert_copy( <$t>:: default ( ) ) ; ) *
278
+ $( assert_impl_all!( $t: ImplicitClone , Copy ) ; ) *
204
279
} ;
205
280
}
206
281
@@ -212,36 +287,38 @@ mod test {
212
287
bool ,
213
288
usize , isize , char ,
214
289
( ) ,
290
+ [ u8 ; 4 ] ,
291
+ & [ u8 ] ,
215
292
) ;
216
293
}
217
294
218
295
#[ test]
219
296
fn ref_type ( ) {
220
- host_library ! ( & NonImplicitCloneType ) ;
221
- // `host_library!(NonImplicitCloneType)` doesn't compile
297
+ assert_impl_all ! ( & Vec < u8 > : ImplicitClone ) ;
298
+ assert_not_impl_all ! ( Vec < u8 > : ImplicitClone ) ;
222
299
}
223
300
224
301
#[ test]
225
302
fn option ( ) {
226
- host_library ! ( Some ( "foo" ) ) ;
227
- // `host_library!(Some(NonImplicitCloneType));` doesn't compile
303
+ assert_impl_all ! ( Option < & ' static str > : ImplicitClone ) ;
304
+ assert_not_impl_all ! ( Option < Vec < u8 >> : ImplicitClone ) ;
228
305
}
229
306
230
307
#[ test]
231
308
fn tuples ( ) {
232
- host_library ! ( ( 1 , ) ) ;
233
- host_library ! ( ( 1 , 2 ) ) ;
234
- host_library ! ( ( 1 , 2 , 3 ) ) ;
235
- host_library ! ( ( 1 , 2 , 3 , 4 ) ) ;
236
- host_library ! ( ( 1 , 2 , 3 , 4 , 5 ) ) ;
237
- host_library ! ( ( 1 , 2 , 3 , 4 , 5 , 6 ) ) ;
238
- host_library ! ( ( 1 , 2 , 3 , 4 , 5 , 6 , 7 ) ) ;
239
- host_library ! ( ( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ) ) ;
240
- host_library ! ( ( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ) ) ;
241
- host_library ! ( ( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ) ) ;
242
- host_library ! ( ( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 ) ) ;
243
- host_library ! ( ( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 ) ) ;
244
- // `host_library !((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13));` doesn't compile
245
- // `host_library !((NonImplicitCloneType,));` doesn't compile
309
+ assert_impl_all ! ( ( u8 , ) : ImplicitClone ) ;
310
+ assert_impl_all ! ( ( u8 , u8 ) : ImplicitClone ) ;
311
+ assert_impl_all ! ( ( u8 , u8 , u8 ) : ImplicitClone ) ;
312
+ assert_impl_all ! ( ( u8 , u8 , u8 , u8 ) : ImplicitClone ) ;
313
+ assert_impl_all ! ( ( u8 , u8 , u8 , u8 , u8 ) : ImplicitClone ) ;
314
+ assert_impl_all ! ( ( u8 , u8 , u8 , u8 , u8 , u8 ) : ImplicitClone ) ;
315
+ assert_impl_all ! ( ( u8 , u8 , u8 , u8 , u8 , u8 , u8 ) : ImplicitClone ) ;
316
+ assert_impl_all ! ( ( u8 , u8 , u8 , u8 , u8 , u8 , u8 , u8 ) : ImplicitClone ) ;
317
+ assert_impl_all ! ( ( u8 , u8 , u8 , u8 , u8 , u8 , u8 , u8 , u8 ) : ImplicitClone ) ;
318
+ assert_impl_all ! ( ( u8 , u8 , u8 , u8 , u8 , u8 , u8 , u8 , u8 , u8 ) : ImplicitClone ) ;
319
+ assert_impl_all ! ( ( u8 , u8 , u8 , u8 , u8 , u8 , u8 , u8 , u8 , u8 , u8 ) : ImplicitClone ) ;
320
+ assert_impl_all ! ( ( u8 , u8 , u8 , u8 , u8 , u8 , u8 , u8 , u8 , u8 , u8 , u8 ) : ImplicitClone ) ;
321
+ assert_not_impl_all ! ( ( u8 , u8 , u8 , u8 , u8 , u8 , u8 , u8 , u8 , u8 , u8 , u8 , u8 ) : ImplicitClone ) ;
322
+ assert_not_impl_all ! ( ( Vec < u8 > , ) : ImplicitClone ) ;
246
323
}
247
324
}
0 commit comments