maybe_owned_trait/
lib.rs

1#![doc = include_str!("../README.md")]
2
3/// Either an owned or a borrowed value.
4pub trait MaybeOwned {
5    /// The owned type.
6    type Owned;
7    /// The borrowed type.
8    type Borrowed<'a>
9    where
10        Self: 'a;
11    /// Convert to owned type. A no-op if already owned.
12    fn to_owned(self) -> Self::Owned;
13    /// Borrow as borrowed type.
14    fn borrow(&self) -> Self::Borrowed<'_>;
15}
16
17impl<'s> MaybeOwned for &'s str {
18    type Owned = String;
19    type Borrowed<'a> = &'a str
20    where
21        's: 'a;
22    fn to_owned(self) -> Self::Owned {
23        self.to_string()
24    }
25    fn borrow(&self) -> Self::Borrowed<'_> {
26        self
27    }
28}
29
30impl MaybeOwned for String {
31    type Owned = String;
32    type Borrowed<'a> = &'a str;
33    fn to_owned(self) -> Self::Owned {
34        self
35    }
36    fn borrow(&self) -> Self::Borrowed<'_> {
37        self.as_str()
38    }
39}
40
41impl<'s> MaybeOwned for std::borrow::Cow<'s, str> {
42    type Owned = String;
43    type Borrowed<'a> = &'a str
44    where
45        's: 'a;
46    fn to_owned(self) -> <Self as MaybeOwned>::Owned {
47        self.into_owned()
48    }
49    fn borrow(&self) -> <Self as MaybeOwned>::Borrowed<'_> {
50        self.as_ref()
51    }
52}
53
54#[cfg(feature = "beef")]
55impl<'s> MaybeOwned for beef::Cow<'s, str> {
56    type Owned = String;
57    type Borrowed<'a> = &'a str
58    where
59        's: 'a;
60    fn to_owned(self) -> <Self as MaybeOwned>::Owned {
61        self.into_owned()
62    }
63    fn borrow(&self) -> <Self as MaybeOwned>::Borrowed<'_> {
64        self.as_ref()
65    }
66}
67
68#[cfg(all(feature = "beef", target_pointer_width = "64"))]
69impl<'s> MaybeOwned for beef::lean::Cow<'s, str> {
70    type Owned = String;
71    type Borrowed<'a> = &'a str
72    where
73        's: 'a;
74    fn to_owned(self) -> <Self as MaybeOwned>::Owned {
75        self.into_owned()
76    }
77    fn borrow(&self) -> <Self as MaybeOwned>::Borrowed<'_> {
78        self.as_ref()
79    }
80}
81
82impl<'a, T: Clone> MaybeOwned for &'a [T] {
83    type Owned = Vec<T>;
84    type Borrowed<'b> = &'b [T]
85    where
86        T: 'b,
87        Self: 'b;
88
89    fn to_owned(self) -> Self::Owned {
90        self.to_vec()
91    }
92
93    fn borrow(&self) -> Self::Borrowed<'_> {
94        self
95    }
96}
97
98impl<T> MaybeOwned for Vec<T> {
99    type Owned = Vec<T>;
100    type Borrowed<'a> = &'a [T]
101    where T: 'a;
102
103    fn to_owned(self) -> Self::Owned {
104        self
105    }
106
107    fn borrow(&self) -> Self::Borrowed<'_> {
108        self.as_slice()
109    }
110}
111
112impl<'s> MaybeOwned for &'s std::path::Path {
113    type Owned = std::path::PathBuf;
114    type Borrowed<'a> = &'a std::path::Path
115    where
116        's: 'a;
117
118    fn to_owned(self) -> Self::Owned {
119        self.to_path_buf()
120    }
121
122    fn borrow(&self) -> Self::Borrowed<'_> {
123        self
124    }
125}
126
127impl MaybeOwned for std::path::PathBuf {
128    type Owned = std::path::PathBuf;
129    type Borrowed<'a> = &'a std::path::Path;
130
131    fn to_owned(self) -> Self::Owned {
132        self
133    }
134
135    fn borrow(&self) -> Self::Borrowed<'_> {
136        self.as_path()
137    }
138}
139
140#[cfg(test)]
141mod tests {
142    use rand::Rng;
143    use std::path::{Path, PathBuf};
144
145    use super::MaybeOwned;
146
147    #[test]
148    #[ignore = "This test exists to ensure that the code compiles"]
149    fn simple_test() {
150        fn my_fn(path: impl MaybeOwned<Owned = PathBuf>) {
151            let path = path.to_owned();
152            println!("{:?}", path);
153        }
154
155        my_fn(PathBuf::from("hello"));
156    }
157
158    #[test]
159    #[ignore = "This test exists to ensure that the code compiles"]
160    fn complicated_test() {
161        fn my_fn(path: impl for<'a> MaybeOwned<Owned = PathBuf, Borrowed<'a> = &'a Path>) {
162            if rand::thread_rng().gen::<bool>() {
163                let path_buf: PathBuf = path.to_owned();
164                println!("Owned buf: {:?}", path_buf);
165            } else {
166                let path: &Path = path.borrow();
167                println!("Borrowed path: {:?}", path);
168            };
169        }
170
171        my_fn(PathBuf::from("hello"));
172        my_fn(Path::new("hello"));
173    }
174}