Skip to main content

stefans_utils/
as_copy.rs

1pub trait AsCopy<T> {
2    #[allow(clippy::wrong_self_convention)]
3    fn as_copy(self) -> T;
4}
5
6impl<T: Copy> AsCopy<T> for T {
7    fn as_copy(self) -> T {
8        self
9    }
10}
11
12impl<T: Copy + AsCopy<T>> AsCopy<T> for &T {
13    fn as_copy(self) -> T {
14        (*self).as_copy()
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        #[allow(clippy::non_canonical_clone_impl)]
32        fn clone(&self) -> Self {
33            Self(self.0 + 1)
34        }
35    }
36
37    impl Copy for MyStruct {}
38
39    #[test]
40    fn as_copy_should_call_copy_on_a_reference() {
41        let source = MyStruct::default();
42        let copied = source;
43
44        fn takes_impl<T>(arg: impl AsCopy<T>) -> T {
45            arg.as_copy()
46        }
47
48        assert_eq!(
49            copied,
50            takes_impl(
51                #[allow(clippy::needless_borrows_for_generic_args)]
52                &source
53            )
54        );
55    }
56
57    #[test]
58    fn as_copy_should_return_an_owned_value_unchanged() {
59        let source = MyStruct::default();
60        let equal = MyStruct::default();
61
62        fn takes_impl<T>(arg: impl AsCopy<T>) -> T {
63            arg.as_copy()
64        }
65
66        assert_eq!(equal, takes_impl(source));
67    }
68
69    #[test]
70    fn as_copy_should_work_with_any_copyable_type() {
71        fn case(value: impl Copy + Debug + PartialEq) {
72            assert_eq!(value, value.as_copy());
73        }
74
75        case("Hello, world!");
76        case(123);
77        case(IpAddr::V4(Ipv4Addr::new(192, 168, 0, 1)));
78    }
79}