proc_macro_assertions/
maybe_borrowed.rs1use std::hash::Hash;
2use std::ops::Deref;
3
4use better_any::{Tid, TidAble};
5use quote::ToTokens;
6
7#[derive(Debug, Tid)]
9pub enum MaybeBorrowed<'a, T> {
10 Borrowed(&'a T),
12 Owned(T),
14}
15
16impl<'a, T> ToTokens for MaybeBorrowed<'a, T>
17where
18 T: ToTokens,
19{
20 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
21 (**self).to_tokens(tokens);
22 }
23
24 fn to_token_stream(&self) -> proc_macro2::TokenStream {
25 (**self).to_token_stream()
26 }
27
28 fn into_token_stream(self) -> proc_macro2::TokenStream
29 where
30 Self: Sized,
31 {
32 self.to_token_stream()
33 }
34}
35
36impl<'a, T> PartialEq for MaybeBorrowed<'a, T>
37where
38 T: PartialEq,
39{
40 fn eq(&self, other: &Self) -> bool {
41 PartialEq::eq(&**self, &**other)
42 }
43}
44
45impl<'a, T> Eq for MaybeBorrowed<'a, T> where T: Eq {}
46
47impl<'a, T> PartialOrd for MaybeBorrowed<'a, T>
48where
49 T: PartialOrd,
50{
51 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
52 PartialOrd::partial_cmp(&**self, &**other)
53 }
54}
55
56impl<'a, T> Ord for MaybeBorrowed<'a, T>
57where
58 T: Ord,
59{
60 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
61 Ord::cmp(&**self, &**other)
62 }
63}
64
65impl<'a, T> MaybeBorrowed<'a, T> {
66 pub const fn is_borrowed(&self) -> bool {
69 match self {
70 Self::Borrowed(_) => true,
71 Self::Owned(_) => false,
72 }
73 }
74
75 pub const fn is_owned(&self) -> bool {
78 !self.is_borrowed()
79 }
80}
81
82impl<'a, T> Hash for MaybeBorrowed<'a, T>
83where
84 T: Hash,
85{
86 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
87 (**self).hash(state);
88 }
89}
90
91impl<'a, T> Deref for MaybeBorrowed<'a, T> {
92 type Target = T;
93
94 fn deref(&self) -> &Self::Target {
95 match self {
96 MaybeBorrowed::Borrowed(val) => val,
97 MaybeBorrowed::Owned(ref val) => val,
98 }
99 }
100}
101
102impl<'a, T> From<T> for MaybeBorrowed<'a, T> {
103 fn from(value: T) -> Self {
104 Self::Owned(value)
105 }
106}
107
108impl<'a, T> From<&'a T> for MaybeBorrowed<'a, T> {
109 fn from(value: &'a T) -> Self {
110 Self::Borrowed(value)
111 }
112}
113
114#[allow(clippy::module_name_repetitions)]
115pub trait FromMaybeBorrowed<'a, T: 'a> {
116 fn from_maybe_borrowed(from: MaybeBorrowed<'a, T>) -> Self;
117
118 fn from_owned(from: T) -> Self
119 where
120 Self: Sized,
121 {
122 Self::from_maybe_borrowed(from.into())
123 }
124
125 fn from_borrowed(from: &'a T) -> Self
126 where
127 Self: Sized,
128 {
129 Self::from_maybe_borrowed(from.into())
130 }
131}
132
133#[cfg(test)]
134mod test {
135 use super::MaybeBorrowed;
136
137 #[test]
138 fn is_borrowed() {
139 let test_data = String::from("Test Data");
140 let maybe_borrowed: MaybeBorrowed<String> = (&test_data).into();
141
142 assert!(maybe_borrowed.is_borrowed());
143 assert!(!maybe_borrowed.is_owned());
144 }
145
146 #[test]
147 fn is_owned() {
148 let test_data = String::from("Test Data");
149 let maybe_borrowed: MaybeBorrowed<String> = test_data.into();
150
151 assert!(!maybe_borrowed.is_borrowed());
152 assert!(maybe_borrowed.is_owned());
153 }
154
155 #[test]
156 fn from_reference() {
157 let test_data = String::from("Test Data");
158 let maybe_borrowed: MaybeBorrowed<String> = (&test_data).into();
159
160 assert_eq!(maybe_borrowed, MaybeBorrowed::Borrowed(&test_data));
161 }
162
163 #[test]
164 fn from_owned() {
165 let test_data = String::from("Test Data");
166 let maybe_borrowed: MaybeBorrowed<String> = test_data.clone().into();
167
168 assert_eq!(maybe_borrowed, MaybeBorrowed::Owned(test_data));
169 }
170}