cheap_clone/
lib.rs

1// `CheapClone` trait is inspired by https://github.com/graphprotocol/graph-node/blob/master/graph/src/cheap_clone.rs
2
3//! A trait which indicates that such type can be cloned cheaply.
4#![cfg_attr(not(any(feature = "std", test)), no_std)]
5#![cfg_attr(docsrs, feature(doc_cfg))]
6#![cfg_attr(docsrs, allow(unused_attributes))]
7#![deny(missing_docs)]
8#![forbid(unsafe_code)]
9
10#[cfg(any(feature = "std", test))]
11extern crate std;
12
13#[cfg(all(not(feature = "std"), feature = "alloc"))]
14extern crate alloc as std;
15
16macro_rules! impl_cheap_clone_for_copy {
17  ($($ty: ty), +$(,)?) => {
18    $(
19      impl crate::CheapClone for $ty {
20        fn cheap_clone(&self) -> Self {
21          *self
22        }
23      }
24    )*
25  };
26}
27
28/// Things that are fast to clone in the context of an application.
29///
30/// The purpose of this API is to reduce the number of calls to .clone() which need to
31/// be audited for performance.
32///
33/// As a rule of thumb, only constant-time `Clone` impls should also implement CheapClone.
34/// Eg:
35/// - ✔ [`Arc<T>`](std::sync::Arc)
36/// - ✔ [`Rc<T>`](std::rc::Rc)
37/// - ✔ [`Bytes`](bytes1::Bytes)
38/// - ✗ [`Vec<T>`](std::vec::Vec)
39/// - ✔ [`SmolStr`](smol_str03::SmolStr)
40/// - ✔ [`FastStr`](faststr02::FastStr)
41/// - ✗ [`String`]
42pub trait CheapClone: Clone {
43  /// Returns a copy of the value.
44  fn cheap_clone(&self) -> Self {
45    self.clone()
46  }
47}
48
49#[cfg(feature = "bytes1")]
50#[cfg_attr(docsrs, doc(cfg(feature = "bytes1")))]
51impl CheapClone for bytes1::Bytes {}
52
53#[cfg(feature = "smol_str03")]
54#[cfg_attr(docsrs, doc(cfg(feature = "smol_str03")))]
55impl CheapClone for smol_str03::SmolStr {}
56
57#[cfg(feature = "smol_str02")]
58#[cfg_attr(docsrs, doc(cfg(feature = "smol_str02")))]
59impl CheapClone for smol_str02::SmolStr {}
60
61#[cfg(feature = "faststr02")]
62#[cfg_attr(docsrs, doc(cfg(feature = "faststr02")))]
63impl CheapClone for faststr02::FastStr {}
64
65#[cfg(feature = "triomphe01")]
66#[cfg_attr(docsrs, doc(cfg(feature = "triomphe01")))]
67impl<T> CheapClone for triomphe01::Arc<T> {}
68
69#[cfg(any(feature = "alloc", feature = "std"))]
70mod a {
71  use super::CheapClone;
72
73  impl<T: ?Sized> CheapClone for std::rc::Rc<T> {}
74  impl<T: ?Sized> CheapClone for std::sync::Arc<T> {}
75}
76
77#[cfg(feature = "std")]
78mod s {
79  use super::CheapClone;
80
81  impl<T: CheapClone> CheapClone for std::pin::Pin<T> {}
82
83  impl_cheap_clone_for_copy!(
84    std::net::IpAddr,
85    std::net::Ipv4Addr,
86    std::net::Ipv6Addr,
87    std::net::SocketAddr,
88    std::net::SocketAddrV4,
89    std::net::SocketAddrV6,
90  );
91}
92
93impl<T: CheapClone> CheapClone for core::cmp::Reverse<T> {
94  #[inline]
95  fn cheap_clone(&self) -> Self {
96    core::cmp::Reverse(self.0.cheap_clone())
97  }
98}
99impl<T: CheapClone> CheapClone for Option<T> {
100  #[inline]
101  fn cheap_clone(&self) -> Self {
102    self.as_ref().map(CheapClone::cheap_clone)
103  }
104}
105impl<T: CheapClone, E: CheapClone> CheapClone for Result<T, E> {
106  #[inline]
107  fn cheap_clone(&self) -> Self {
108    match self {
109      Ok(ok) => Ok(ok.cheap_clone()),
110      Err(err) => Err(err.cheap_clone()),
111    }
112  }
113}
114#[cfg(feature = "either")]
115impl<L: CheapClone, R: CheapClone> CheapClone for either::Either<L, R> {
116  #[inline]
117  fn cheap_clone(&self) -> Self {
118    match self {
119      either::Either::Left(left) => either::Either::Left(left.cheap_clone()),
120      either::Either::Right(right) => either::Either::Right(right.cheap_clone()),
121    }
122  }
123}
124#[cfg(feature = "among")]
125impl<L: CheapClone, M: CheapClone, R: CheapClone> CheapClone for among::Among<L, M, R> {
126  #[inline]
127  fn cheap_clone(&self) -> Self {
128    match self {
129      among::Among::Left(left) => among::Among::Left(left.cheap_clone()),
130      among::Among::Middle(middle) => among::Among::Middle(middle.cheap_clone()),
131      among::Among::Right(right) => among::Among::Right(right.cheap_clone()),
132    }
133  }
134}
135
136impl_cheap_clone_for_copy! {
137  (),
138  bool, char, f32, f64, i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize,
139  core::num::NonZeroI8,
140  core::num::NonZeroI16,
141  core::num::NonZeroI32,
142  core::num::NonZeroI64,
143  core::num::NonZeroI128,
144  core::num::NonZeroIsize,
145  core::num::NonZeroU8,
146  core::num::NonZeroU16,
147  core::num::NonZeroU32,
148  core::num::NonZeroU64,
149  core::num::NonZeroU128,
150  core::num::NonZeroUsize,
151  &str
152}
153
154impl<T: Copy, const N: usize> CheapClone for [T; N] {
155  fn cheap_clone(&self) -> Self {
156    *self
157  }
158}
159
160impl<T> CheapClone for &T {
161  fn cheap_clone(&self) -> Self {
162    self
163  }
164}
165
166macro_rules! impl_cheap_clone_for_tuple {
167  ($($param:literal),+ $(,)?) => {
168    ::paste::paste! {
169      impl<$([< T $param >]: CheapClone),+> CheapClone for ($([< T $param >],)+) {
170        fn cheap_clone(&self) -> Self {
171          ($(self.$param.cheap_clone(),)+)
172        }
173      }
174    }
175  };
176}
177
178impl_cheap_clone_for_tuple!(0);
179impl_cheap_clone_for_tuple!(0, 1);
180impl_cheap_clone_for_tuple!(0, 1, 2);
181impl_cheap_clone_for_tuple!(0, 1, 2, 3);
182impl_cheap_clone_for_tuple!(0, 1, 2, 3, 4);
183impl_cheap_clone_for_tuple!(0, 1, 2, 3, 4, 5);
184impl_cheap_clone_for_tuple!(0, 1, 2, 3, 4, 5, 6);
185impl_cheap_clone_for_tuple!(0, 1, 2, 3, 4, 5, 6, 7);
186impl_cheap_clone_for_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8);
187impl_cheap_clone_for_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
188impl_cheap_clone_for_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
189impl_cheap_clone_for_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
190impl_cheap_clone_for_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
191impl_cheap_clone_for_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);
192impl_cheap_clone_for_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);
193impl_cheap_clone_for_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
194impl_cheap_clone_for_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
195impl_cheap_clone_for_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17);
196impl_cheap_clone_for_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18);
197impl_cheap_clone_for_tuple!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19);
198impl_cheap_clone_for_tuple!(
199  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20
200);
201impl_cheap_clone_for_tuple!(
202  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21
203);
204impl_cheap_clone_for_tuple!(
205  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22
206);
207impl_cheap_clone_for_tuple!(
208  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23
209);