Skip to content

Commit a3636d8

Browse files
authored
Attempt to improve the documentation (#45)
1 parent 00aed91 commit a3636d8

File tree

2 files changed

+115
-35
lines changed

2 files changed

+115
-35
lines changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,8 @@ implicit-clone-derive = { version = "0.1", optional = true, path = "./implicit-c
2828
indexmap = { version = ">= 1, <= 2", optional = true }
2929
serde = { version = "1", optional = true }
3030

31+
[dev-dependencies]
32+
static_assertions = "1"
33+
3134
[workspace]
3235
members = ["implicit-clone-derive"]

src/lib.rs

Lines changed: 112 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,95 @@
4040
//! particularity: iterating on these types yields clones of the items and not references.** This
4141
//! can be particularly handy when using a React-like framework.
4242
//!
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+
//!
43132
//! [std::marker::Copy]: https://doc.rust-lang.org/std/marker/trait.Copy.html
44133
//! [std::clone::Clone]: https://doc.rust-lang.org/std/clone/trait.Clone.html
45134
//! [std::rc::Rc]: https://doc.rust-lang.org/std/rc/struct.Rc.html
@@ -170,18 +259,7 @@ macro_rules! imap_deconstruct {
170259
#[cfg(test)]
171260
mod test {
172261
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::*;
185263

186264
#[test]
187265
fn custom() {
@@ -190,17 +268,14 @@ mod test {
190268

191269
impl ImplicitClone for ImplicitCloneType {}
192270

193-
host_library!(ImplicitCloneType);
271+
assert_impl_all!(ImplicitCloneType: ImplicitClone);
194272
}
195273

196274
#[test]
197275
fn copy_types() {
198-
fn assert_copy<T: Copy>(_: T) {}
199-
200276
macro_rules! test_all {
201277
($($t:ty),* $(,)?) => {
202-
$(host_library!(<$t>::default());)*
203-
$(assert_copy(<$t>::default());)*
278+
$(assert_impl_all!($t: ImplicitClone, Copy);)*
204279
};
205280
}
206281

@@ -212,36 +287,38 @@ mod test {
212287
bool,
213288
usize, isize, char,
214289
(),
290+
[u8; 4],
291+
&[u8],
215292
);
216293
}
217294

218295
#[test]
219296
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);
222299
}
223300

224301
#[test]
225302
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);
228305
}
229306

230307
#[test]
231308
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);
246323
}
247324
}

0 commit comments

Comments
 (0)