#![doc = include_str!("lib_readme.md")]
#[allow(unused_imports)]
#[macro_use]
extern crate dupit_derive;
#[doc(hidden)]
pub use dupit_derive::Duplicate;
#[doc(hidden)]
pub mod impls {
pub struct Wrapper<T>(pub T);
pub trait DuplicateImpl<T> {
fn duplicate_impl(&self) -> T;
}
impl<T: Clone> DuplicateImpl<T> for Wrapper<&T> {
#[inline(always)]
fn duplicate_impl(&self) -> T {
self.0.clone()
}
}
impl<T: Copy> DuplicateImpl<T> for &Wrapper<&T> {
#[inline(always)]
fn duplicate_impl(&self) -> T {
*self.0
}
}
}
pub trait Duplicate {
fn dup(&self) -> Self;
}
#[macro_export]
#[doc(hidden)]
macro_rules! copy_or_clone {
($val_ref: expr) => {{
use $crate::impls::DuplicateImpl;
(&&$crate::impls::Wrapper($val_ref)).duplicate_impl()
}};
}
#[cfg(test)]
mod tests {
use crate::Duplicate;
struct Cloneable(bool);
impl Clone for Cloneable {
fn clone(&self) -> Self {
Cloneable(true)
}
}
impl Duplicate for Cloneable {
fn dup(&self) -> Self {
copy_or_clone!(self)
}
}
#[derive(Copy)]
struct Copyable(bool);
impl Clone for Copyable {
#[allow(clippy::non_canonical_clone_impl)]
fn clone(&self) -> Self {
Copyable(true)
}
}
impl Duplicate for Copyable {
fn dup(&self) -> Self {
copy_or_clone!(self)
}
}
#[test]
fn test_foo() {
let a = Cloneable(false).dup();
assert!(a.0, "cloned, duplicated via Clone");
let b = Copyable(false).dup();
assert!(!b.0, "not cloned duplicated via Copy");
}
}