Skip to main content

stefans_utils/
as_clone.rs

1pub trait AsClone<T> {
2    #[allow(clippy::wrong_self_convention)]
3    fn as_clone(self) -> T;
4}
5
6impl<T: Clone> AsClone<T> for T {
7    fn as_clone(self) -> T {
8        self
9    }
10}
11
12impl<T: Clone + AsClone<T>> AsClone<T> for &T {
13    fn as_clone(self) -> T {
14        (*self).clone()
15    }
16}
17
18#[cfg(test)]
19mod tests {
20    use std::{
21        fmt::Debug,
22        net::{IpAddr, Ipv4Addr},
23    };
24
25    use super::*;
26
27    #[derive(Debug, PartialEq, Default)]
28    struct MyStruct(usize);
29
30    impl Clone for MyStruct {
31        fn clone(&self) -> Self {
32            Self(self.0 + 1)
33        }
34    }
35
36    #[test]
37    fn as_clone_should_call_clone_on_a_reference() {
38        let source = MyStruct::default();
39        let cloned = source.clone();
40
41        fn takes_impl<T>(arg: impl AsClone<T>) -> T {
42            arg.as_clone()
43        }
44
45        assert_eq!(cloned, takes_impl(&source));
46    }
47
48    #[test]
49    fn as_clone_should_return_an_owned_value_unchanged() {
50        let source = MyStruct::default();
51        let equal = MyStruct::default();
52
53        fn takes_impl<T>(arg: impl AsClone<T>) -> T {
54            arg.as_clone()
55        }
56
57        assert_eq!(equal, takes_impl(source));
58    }
59
60    #[test]
61    fn as_clone_should_work_with_any_clonable_type() {
62        fn case(value: impl Clone + Debug + PartialEq) {
63            assert_eq!(value.clone(), value.as_clone());
64        }
65
66        case(String::from("Hello, world!"));
67        case("Hello, world!");
68        case(123);
69        case(IpAddr::V4(Ipv4Addr::new(192, 168, 0, 1)));
70    }
71}