1#![doc = include_str!("../README.md")]
5#![no_std]
6
7extern crate alloc;
8
9#[cfg(feature = "std")]
10extern crate std;
11
12use alloc::string::String;
13use core::{
14 borrow::Borrow,
15 fmt::{Debug, Display},
16 hash::Hash,
17 ops::Deref,
18};
19
20#[cfg(feature = "std")]
21use std::path::{Path, PathBuf};
22
23#[cfg(target_has_atomic = "ptr")]
24use alloc::sync::Arc;
25
26#[cfg(not(target_has_atomic = "ptr"))]
27use portable_atomic_util::Arc;
28
29pub enum CowArc<'a, T: ?Sized + 'static> {
41 Borrowed(&'a T),
43 Static(&'static T),
49 Owned(Arc<T>),
51}
52
53impl<T: ?Sized + 'static> CowArc<'static, T> {
54 pub fn new_owned(value: T) -> Self
61 where
62 T: Sized,
63 {
64 CowArc::Owned(Arc::new(value))
65 }
66
67 pub fn new_owned_from_arc(value: impl Into<Arc<T>>) -> Self {
71 CowArc::Owned(value.into())
72 }
73}
74
75impl<T: ?Sized> CowArc<'static, T> {
76 #[inline]
82 pub fn as_static(self) -> Self {
83 match self {
84 Self::Borrowed(value) | Self::Static(value) => Self::Static(value),
85 Self::Owned(value) => Self::Owned(value),
86 }
87 }
88}
89
90impl<T: ?Sized> Deref for CowArc<'_, T> {
91 type Target = T;
92
93 #[inline]
94 fn deref(&self) -> &Self::Target {
95 match self {
96 CowArc::Borrowed(v) | CowArc::Static(v) => v,
97 CowArc::Owned(v) => v,
98 }
99 }
100}
101
102impl<T: ?Sized> Borrow<T> for CowArc<'_, T> {
103 #[inline]
104 fn borrow(&self) -> &T {
105 self
106 }
107}
108
109impl<T: ?Sized> AsRef<T> for CowArc<'_, T> {
110 #[inline]
111 fn as_ref(&self) -> &T {
112 self
113 }
114}
115
116impl<'a, T: ?Sized> CowArc<'a, T>
117where
118 &'a T: Into<Arc<T>>,
119{
120 #[inline]
125 pub fn into_owned(self) -> CowArc<'static, T> {
126 match self {
127 CowArc::Borrowed(value) => CowArc::Owned(value.into()),
128 CowArc::Static(value) => CowArc::Static(value),
129 CowArc::Owned(value) => CowArc::Owned(value),
130 }
131 }
132
133 #[inline]
139 pub fn clone_owned(&self) -> CowArc<'static, T> {
140 self.clone().into_owned()
141 }
142}
143
144impl<T: ?Sized> Clone for CowArc<'_, T> {
145 #[inline]
146 fn clone(&self) -> Self {
147 match self {
148 Self::Borrowed(value) => Self::Borrowed(value),
149 Self::Static(value) => Self::Static(value),
150 Self::Owned(value) => Self::Owned(value.clone()),
151 }
152 }
153}
154
155impl<T: PartialEq + ?Sized> PartialEq for CowArc<'_, T> {
156 #[inline]
157 fn eq(&self, other: &Self) -> bool {
158 self.deref().eq(other.deref())
159 }
160}
161
162impl<T: PartialEq + ?Sized> Eq for CowArc<'_, T> {}
163
164impl<T: Hash + ?Sized> Hash for CowArc<'_, T> {
165 #[inline]
166 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
167 self.deref().hash(state);
168 }
169}
170
171impl<T: Debug + ?Sized> Debug for CowArc<'_, T> {
172 #[inline]
173 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
174 Debug::fmt(self.deref(), f)
175 }
176}
177
178impl<T: Display + ?Sized> Display for CowArc<'_, T> {
179 #[inline]
180 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
181 Display::fmt(self.deref(), f)
182 }
183}
184
185impl<T: PartialOrd + ?Sized> PartialOrd for CowArc<'_, T> {
186 #[inline]
187 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
188 self.deref().partial_cmp(other.deref())
189 }
190}
191
192impl Default for CowArc<'static, str> {
193 fn default() -> Self {
194 CowArc::Static(Default::default())
195 }
196}
197
198#[cfg(feature = "std")]
199impl Default for CowArc<'static, Path> {
201 fn default() -> Self {
205 CowArc::Static(Path::new(""))
206 }
207}
208
209impl<T: Ord + ?Sized> Ord for CowArc<'_, T> {
210 #[inline]
211 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
212 self.deref().cmp(other.deref())
213 }
214}
215
216#[cfg(feature = "std")]
217impl From<PathBuf> for CowArc<'static, Path> {
218 #[inline]
219 fn from(value: PathBuf) -> Self {
220 CowArc::Owned(value.into())
221 }
222}
223
224#[cfg(feature = "std")]
225impl From<&'static str> for CowArc<'static, Path> {
226 #[inline]
227 fn from(value: &'static str) -> Self {
228 CowArc::Static(Path::new(value))
229 }
230}
231
232impl From<String> for CowArc<'static, str> {
233 #[inline]
234 fn from(value: String) -> Self {
235 CowArc::Owned(value.into())
236 }
237}
238
239impl<'a> From<&'a String> for CowArc<'a, str> {
240 #[inline]
241 fn from(value: &'a String) -> Self {
242 CowArc::Borrowed(value)
243 }
244}
245
246impl<T: ?Sized> From<&'static T> for CowArc<'static, T> {
247 #[inline]
248 fn from(value: &'static T) -> Self {
249 CowArc::Static(value)
250 }
251}
252
253impl<T> From<Arc<T>> for CowArc<'static, T> {
254 #[inline]
255 fn from(value: Arc<T>) -> Self {
256 CowArc::Owned(value)
257 }
258}