defuse_near_utils/
panic_on_clone.rs1use impl_tools::autoimpl;
2use near_sdk::{env, near};
3
4#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
9#[autoimpl(Deref using self.0)]
10#[autoimpl(DerefMut using self.0)]
11#[autoimpl(AsRef using self.0)]
12#[autoimpl(AsMut using self.0)]
13#[near(serializers = [borsh])]
14#[repr(transparent)] pub struct PanicOnClone<T: ?Sized>(T);
16
17impl<T> PanicOnClone<T> {
18 #[inline]
19 pub const fn new(value: T) -> Self {
20 Self(value)
21 }
22
23 #[inline]
24 pub const fn from_ref(value: &T) -> &Self {
25 unsafe { ::core::mem::transmute::<&T, &Self>(value) }
27 }
28
29 #[inline]
30 pub fn into_inner(self) -> T {
31 self.0
32 }
33}
34
35impl<T> From<T> for PanicOnClone<T> {
36 fn from(value: T) -> Self {
37 Self::new(value)
38 }
39}
40
41impl<T> Clone for PanicOnClone<T> {
42 #[track_caller]
43 fn clone(&self) -> Self {
44 env::panic_str("PanicOnClone")
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51
52 use core::ptr;
53
54 #[test]
55 fn from_ref() {
56 let value = "example".to_string();
57 let poc = PanicOnClone::from_ref(&value);
58 assert!(ptr::eq(&**poc, &value));
59 assert_eq!(&**poc, &value);
60 }
61
62 #[test]
63 #[should_panic(expected = "PanicOnClone")]
64 #[allow(clippy::redundant_clone)]
65 fn panics_on_clone() {
66 struct NotClonable;
67
68 let _ = PanicOnClone::new(
69 NotClonable,
71 )
72 .clone();
73 }
74}