diff --git a/Cargo.toml b/Cargo.toml
index 7b01f4c..834bec7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -28,5 +28,8 @@ implicit-clone-derive = { version = "0.1", optional = true, path = "./implicit-c
indexmap = { version = ">= 1, <= 2", optional = true }
serde = { version = "1", optional = true }
+[dev-dependencies]
+static_assertions = "1"
+
[workspace]
members = ["implicit-clone-derive"]
diff --git a/src/lib.rs b/src/lib.rs
index cee6e4d..c2141db 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -40,6 +40,95 @@
//! particularity: iterating on these types yields clones of the items and not references.** This
//! can be particularly handy when using a React-like framework.
//!
+//! ## Example
+//!
+//! As an example, here is an implementation of a macro called `html_input! {}` which allows its
+//! user to build an `` HTML node:
+//!
+//! ```
+//! // In the host library source code:
+//!
+//! use implicit_clone::ImplicitClone;
+//! use implicit_clone::unsync::{IArray, IString};
+//!
+//! macro_rules! html_input {
+//! () => {{
+//! let mut input = Input::new();
+//! $(input.set_type($ty);)*
+//! $(input.set_name($name);)*
+//! $(input.set_value($value);)*
+//! input
+//! }}
+//! }
+//!
+//! #[derive(Clone)]
+//! pub struct Input {
+//! ty: IString,
+//! name: Option,
+//! value: Option,
+//! }
+//!
+//! impl ImplicitClone for Input {}
+//!
+//! impl Input {
+//! pub fn new() -> Self {
+//! Self {
+//! ty: IString::Static("text"),
+//! name: None,
+//! value: None,
+//! }
+//! }
+//!
+//! pub fn set_type(&mut self, ty: impl Into) {
+//! self.ty = ty.into();
+//! }
+//!
+//! pub fn set_name(&mut self, name: impl Into) {
+//! self.name.replace(name.into());
+//! }
+//!
+//! pub fn set_value(&mut self, value: impl Into) {
+//! self.value.replace(value.into());
+//! }
+//! }
+//!
+//! impl std::fmt::Display for Input {
+//! fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+//! write!(f, "")
+//! }
+//! }
+//!
+//! // In the user's source code:
+//!
+//! fn component(age: &IString) -> IArray {
+//! // `age` is implicitly cloned to the 2 different inputs
+//! let input1 = html_input!();
+//! let input2 = html_input!();
+//!
+//! IArray::from(vec![input1, input2])
+//! }
+//!
+//! let age = IString::from(20.to_string());
+//! let output = component(&age);
+//! let output_str = output
+//! .iter()
+//! .map(|x| x.to_string())
+//! .collect::>()
+//! .join("");
+//!
+//! assert_eq!(
+//! output_str,
+//! r#""#,
+//! );
+//! ```
+//!
//! [std::marker::Copy]: https://doc.rust-lang.org/std/marker/trait.Copy.html
//! [std::clone::Clone]: https://doc.rust-lang.org/std/clone/trait.Clone.html
//! [std::rc::Rc]: https://doc.rust-lang.org/std/rc/struct.Rc.html
@@ -170,18 +259,7 @@ macro_rules! imap_deconstruct {
#[cfg(test)]
mod test {
use super::*;
-
- fn host_library(value: &T) -> T {
- value.clone()
- }
-
- macro_rules! host_library {
- ($a:expr) => {
- host_library(&$a)
- };
- }
-
- struct NonImplicitCloneType;
+ use static_assertions::*;
#[test]
fn custom() {
@@ -190,17 +268,14 @@ mod test {
impl ImplicitClone for ImplicitCloneType {}
- host_library!(ImplicitCloneType);
+ assert_impl_all!(ImplicitCloneType: ImplicitClone);
}
#[test]
fn copy_types() {
- fn assert_copy(_: T) {}
-
macro_rules! test_all {
($($t:ty),* $(,)?) => {
- $(host_library!(<$t>::default());)*
- $(assert_copy(<$t>::default());)*
+ $(assert_impl_all!($t: ImplicitClone, Copy);)*
};
}
@@ -212,36 +287,38 @@ mod test {
bool,
usize, isize, char,
(),
+ [u8; 4],
+ &[u8],
);
}
#[test]
fn ref_type() {
- host_library!(&NonImplicitCloneType);
- // `host_library!(NonImplicitCloneType)` doesn't compile
+ assert_impl_all!(&Vec: ImplicitClone);
+ assert_not_impl_all!(Vec: ImplicitClone);
}
#[test]
fn option() {
- host_library!(Some("foo"));
- // `host_library!(Some(NonImplicitCloneType));` doesn't compile
+ assert_impl_all!(Option<&'static str>: ImplicitClone);
+ assert_not_impl_all!(Option>: ImplicitClone);
}
#[test]
fn tuples() {
- host_library!((1,));
- host_library!((1, 2));
- host_library!((1, 2, 3));
- host_library!((1, 2, 3, 4));
- host_library!((1, 2, 3, 4, 5));
- host_library!((1, 2, 3, 4, 5, 6));
- host_library!((1, 2, 3, 4, 5, 6, 7));
- host_library!((1, 2, 3, 4, 5, 6, 7, 8));
- host_library!((1, 2, 3, 4, 5, 6, 7, 8, 9));
- host_library!((1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
- host_library!((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11));
- host_library!((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12));
- // `host_library!((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13));` doesn't compile
- // `host_library!((NonImplicitCloneType,));` doesn't compile
+ assert_impl_all!((u8,): ImplicitClone);
+ assert_impl_all!((u8, u8): ImplicitClone);
+ assert_impl_all!((u8, u8, u8): ImplicitClone);
+ assert_impl_all!((u8, u8, u8, u8): ImplicitClone);
+ assert_impl_all!((u8, u8, u8, u8, u8): ImplicitClone);
+ assert_impl_all!((u8, u8, u8, u8, u8, u8): ImplicitClone);
+ assert_impl_all!((u8, u8, u8, u8, u8, u8, u8): ImplicitClone);
+ assert_impl_all!((u8, u8, u8, u8, u8, u8, u8, u8): ImplicitClone);
+ assert_impl_all!((u8, u8, u8, u8, u8, u8, u8, u8, u8): ImplicitClone);
+ assert_impl_all!((u8, u8, u8, u8, u8, u8, u8, u8, u8, u8): ImplicitClone);
+ assert_impl_all!((u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8): ImplicitClone);
+ assert_impl_all!((u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8): ImplicitClone);
+ assert_not_impl_all!((u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8): ImplicitClone);
+ assert_not_impl_all!((Vec,): ImplicitClone);
}
}