proc_macro_assertions/
maybe_borrowed.rs

1use std::hash::Hash;
2use std::ops::Deref;
3
4use better_any::{Tid, TidAble};
5use quote::ToTokens;
6
7/// Some type that is eiher borrowed or owned
8#[derive(Debug, Tid)]
9pub enum MaybeBorrowed<'a, T> {
10    /// Some borrowed type
11    Borrowed(&'a T),
12    /// Some owned type
13    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    /// Check if `Self` contains a borrowed type
67    /// Inverse of [`MaybeBorrowed::is_owned`].
68    pub const fn is_borrowed(&self) -> bool {
69        match self {
70            Self::Borrowed(_) => true,
71            Self::Owned(_) => false,
72        }
73    }
74
75    /// Check if `Self` contains a owned type.
76    /// Inverse of [`MaybeBorrowed::is_borrowed`].
77    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}