stefans_utils/
as_clone.rs1pub 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}