metrics/cow.rs
1use std::{
2 borrow::Borrow,
3 cmp::Ordering,
4 fmt,
5 hash::{Hash, Hasher},
6 marker::PhantomData,
7 mem::ManuallyDrop,
8 ops::Deref,
9 ptr::{slice_from_raw_parts, NonNull},
10 sync::Arc,
11};
12
13#[derive(Clone, Copy)]
14enum Kind {
15 Owned,
16 Borrowed,
17 Shared,
18}
19
20/// A clone-on-write smart pointer with an optimized memory layout, based on `beef`.
21///
22/// # Strings, strings everywhere
23///
24/// In `metrics`, strings are arguably the most common data type used despite the fact that metrics
25/// are measuring numerical values. Both the name of a metric, and its labels, are strings: emitting
26/// a metric may involve one string, or 10 strings. Many of these strings tend to be used over and
27/// over during the life of the process, as well.
28///
29/// In order to achieve and maintain a high level of performance, we use a "clone-on-write" smart
30/// pointer to handle passing these strings around. Doing so allows us to potentially avoid having
31/// to allocate entire copies of a string, instead using a lightweight smart pointer that can live
32/// on the stack.
33///
34/// # Why not `std::borrow::Cow`?
35///
36/// The standard library already provides a clone-on-write smart pointer, `std::borrow::Cow`, which
37/// works well in many cases. However, `metrics` strives to provide minimal overhead where possible,
38/// and so `std::borrow::Cow` falls down in one particular way: it uses an enum representation which
39/// consumes an additional word of storage.
40///
41/// As an example, let's look at strings. A string in `std::borrow::Cow` implies that `T` is `str`,
42/// and the owned version of `str` is simply `String`. Thus, for `std::borrow::Cow`, the in-memory
43/// layout looks like this:
44///
45/// ```text
46/// Padding
47/// |
48/// v
49/// +--------------+-------------+--------------+--------------+
50/// stdlib Cow::Borrowed: | Enum Tag | Pointer | Length | XXXXXXXX |
51/// +--------------+-------------+--------------+--------------+
52/// +--------------+-------------+--------------+--------------+
53/// stdlib Cow::Owned: | Enum Tag | Pointer | Length | Capacity |
54/// +--------------+-------------+--------------+--------------+
55/// ```
56///
57/// As you can see, you pay a memory size penalty to be able to wrap an owned string. This
58/// additional word adds minimal overhead, but we can easily avoid it with some clever logic around
59/// the values of the length and capacity fields.
60///
61/// There is an existing crate that does just that: `beef`. Instead of using an enum, it is simply a
62/// struct that encodes the discriminant values in the length and capacity fields directly. If we're
63/// wrapping a borrowed value, we can infer that the "capacity" will always be zero, as we only need
64/// to track the capacity when we're wrapping an owned value, in order to be able to recreate the
65/// underlying storage when consuming the smart pointer, or dropping it. Instead of the above
66/// layout, `beef` looks like this:
67///
68/// ```text
69/// +-------------+--------------+----------------+
70/// `beef` Cow (borrowed): | Pointer | Length (N) | Capacity (0) |
71/// +-------------+--------------+----------------+
72/// +-------------+--------------+----------------+
73/// `beef` Cow (owned): | Pointer | Length (N) | Capacity (M) |
74/// +-------------+--------------+----------------+
75/// ```
76///
77/// # Why not `beef`?
78///
79/// Up until this point, it might not be clear why we didn't just use `beef`. In truth, our design
80/// is fundamentally based on `beef`. Crucially, however, `beef` did not/still does not support
81/// `const` construction for generic slices. Remember how we mentioned labels? The labels of a
82/// metric are `[Label]` under-the-hood, and so without a way to construct them in a `const`
83/// fashion, our previous work to allow entirely static keys would not be possible.
84///
85/// Thus, we forked `beef` and copied into directly into `metrics` so that we could write a
86/// specialized `const` constructor for `[Label]`.
87///
88/// This is why we have our own `Cow` bundled into `metrics` directly, which is based on `beef`. In
89/// doing so, we can experiment with more interesting optimizations, and, as mentioned above, we can
90/// add const methods to support all of the types involved in statically building metrics keys.
91///
92/// # What we do that `beef` doesn't do
93///
94/// It was already enough to use our own implementation for the specialized `const` capabilities,
95/// but we've taken things even further in a key way: support for `Arc`-wrapped values.
96///
97/// ## `Arc`-wrapped values
98///
99/// For many strings, there is still a desire to share them cheaply even when they are constructed
100/// at run-time. Remember, cloning a `Cow` of an owned value means cloning the value itself, so we
101/// need another level of indirection to allow the cheap sharing, which is where `Arc<T>` can
102/// provide value.
103///
104/// Users can construct a `Arc<T>`, where `T` is lined up with the `T` of `metrics::Cow`, and use
105/// that as the initial value instead. When `Cow` is cloned, we end up cloning the underlying
106/// `Arc<T>` instead, avoiding a new allocation. `Arc<T>` still handles all of the normal logic
107/// necessary to know when the wrapped value must be dropped, and how many live references to the
108/// value that there are, and so on.
109///
110/// We handle this by relying on an invariant of `Vec<T>`: it never allocates more than `isize::MAX`
111/// [1]. This lets us derive the following truth table of the valid combinations of length/capacity:
112///
113/// ```text
114/// Length (N) Capacity (M)
115/// +---------------+----------------+
116/// Borrowed (&T): | N | 0 |
117/// +---------------+----------------+
118/// Owned (T::ToOwned): | N | M < usize::MAX |
119/// +---------------+----------------+
120/// Shared (Arc<T>): | N | usize::MAX |
121/// +---------------+----------------+
122/// ```
123///
124/// As we only implement `Cow` for types where their owned variants are either explicitly or
125/// implicitly backed by `Vec<_>`, we know that our capacity will never be `usize::MAX`, as it is
126/// limited to `isize::MAX`, and thus we can safely encode our "shared" state within the capacity
127/// field.
128///
129/// # Notes
130///
131/// [1] - technically, `Vec<T>` can have a capacity greater than `isize::MAX` when storing
132/// zero-sized types, but we don't do that here, so we always enforce that an owned version's
133/// capacity cannot be `usize::MAX` when constructing `Cow`.
134pub struct Cow<'a, T: Cowable + ?Sized + 'a> {
135 ptr: NonNull<T::Pointer>,
136 metadata: Metadata,
137 _lifetime: PhantomData<&'a T>,
138}
139
140impl<T> Cow<'_, T>
141where
142 T: Cowable + ?Sized,
143{
144 fn from_parts(ptr: NonNull<T::Pointer>, metadata: Metadata) -> Self {
145 Self { ptr, metadata, _lifetime: PhantomData }
146 }
147
148 /// Creates a pointer to an owned value, consuming it.
149 pub fn from_owned(owned: T::Owned) -> Self {
150 let (ptr, metadata) = T::owned_into_parts(owned);
151
152 // This check is partially to guard against the semantics of `Vec<T>` changing in the
153 // future, and partially to ensure that we don't somehow implement `Cowable` for a type
154 // where its owned version is backed by a vector of ZSTs, where the capacity could
155 // _legitimately_ be `usize::MAX`.
156 if metadata.capacity() == usize::MAX {
157 panic!("Invalid capacity of `usize::MAX` for owned value.");
158 }
159
160 Self::from_parts(ptr, metadata)
161 }
162
163 /// Creates a pointer to a shared value.
164 pub fn from_shared(arc: Arc<T>) -> Self {
165 let (ptr, metadata) = T::shared_into_parts(arc);
166 Self::from_parts(ptr, metadata)
167 }
168
169 /// Extracts the owned data.
170 ///
171 /// Clones the data if it is not already owned.
172 pub fn into_owned(self) -> <T as ToOwned>::Owned {
173 // We need to ensure that our own `Drop` impl does _not_ run because we're simply
174 // transferring ownership of the value back to the caller. For borrowed values, this is
175 // naturally a no-op because there's nothing to drop, but for owned values, like `String` or
176 // `Arc<T>`, we wouldn't want to double drop.
177 let cow = ManuallyDrop::new(self);
178
179 T::owned_from_parts(cow.ptr, &cow.metadata)
180 }
181}
182
183impl<'a, T> Cow<'a, T>
184where
185 T: Cowable + ?Sized,
186{
187 /// Creates a pointer to a borrowed value.
188 pub fn from_borrowed(borrowed: &'a T) -> Self {
189 let (ptr, metadata) = T::borrowed_into_parts(borrowed);
190
191 Self::from_parts(ptr, metadata)
192 }
193}
194
195impl<'a, T> Cow<'a, [T]>
196where
197 T: Clone,
198{
199 pub const fn const_slice(val: &'a [T]) -> Cow<'a, [T]> {
200 // SAFETY: We can never create a null pointer by casting a reference to a pointer.
201 let ptr = unsafe { NonNull::new_unchecked(val.as_ptr() as *mut _) };
202 let metadata = Metadata::borrowed(val.len());
203
204 Self { ptr, metadata, _lifetime: PhantomData }
205 }
206}
207
208impl<T> Cow<'static, [T]>
209where
210 T: Clone,
211{
212 pub(crate) fn to_retained(&self) -> Self {
213 match self.metadata.kind() {
214 Kind::Borrowed | Kind::Shared => self.clone(),
215 Kind::Owned => Cow::from_shared(Arc::<[T]>::from(self.deref())),
216 }
217 }
218}
219
220impl<'a> Cow<'a, str> {
221 pub const fn const_str(val: &'a str) -> Self {
222 // SAFETY: We can never create a null pointer by casting a reference to a pointer.
223 let ptr = unsafe { NonNull::new_unchecked(val.as_ptr() as *mut _) };
224 let metadata = Metadata::borrowed(val.len());
225
226 Self { ptr, metadata, _lifetime: PhantomData }
227 }
228}
229
230impl Cow<'static, str> {
231 pub(crate) fn to_retained(&self) -> Self {
232 match self.metadata.kind() {
233 Kind::Borrowed | Kind::Shared => self.clone(),
234 Kind::Owned => Cow::from_shared(Arc::<str>::from(self.deref())),
235 }
236 }
237}
238
239impl<T> Deref for Cow<'_, T>
240where
241 T: Cowable + ?Sized,
242{
243 type Target = T;
244
245 fn deref(&self) -> &Self::Target {
246 let borrowed_ptr = T::borrowed_from_parts(self.ptr, &self.metadata);
247
248 // SAFETY: We only ever hold a pointer to a borrowed value of at least the lifetime of
249 // `Self`, or an owned value which we have ownership of (albeit indirectly when using
250 // `Arc<T>`), so our pointer is always valid and live for dereferencing.
251 unsafe { borrowed_ptr.as_ref().unwrap() }
252 }
253}
254
255impl<T> Clone for Cow<'_, T>
256where
257 T: Cowable + ?Sized,
258{
259 fn clone(&self) -> Self {
260 let (ptr, metadata) = T::clone_from_parts(self.ptr, &self.metadata);
261 Self { ptr, metadata, _lifetime: PhantomData }
262 }
263}
264
265impl<T> Drop for Cow<'_, T>
266where
267 T: Cowable + ?Sized,
268{
269 fn drop(&mut self) {
270 T::drop_from_parts(self.ptr, &self.metadata);
271 }
272}
273
274impl<T> Hash for Cow<'_, T>
275where
276 T: Hash + Cowable + ?Sized,
277{
278 #[inline]
279 fn hash<H: Hasher>(&self, state: &mut H) {
280 self.deref().hash(state)
281 }
282}
283
284impl<'a, T> Default for Cow<'a, T>
285where
286 T: Cowable + ?Sized,
287 &'a T: Default,
288{
289 #[inline]
290 fn default() -> Self {
291 Cow::from_borrowed(Default::default())
292 }
293}
294
295impl<T> Eq for Cow<'_, T> where T: Eq + Cowable + ?Sized {}
296
297impl<A, B> PartialOrd<Cow<'_, B>> for Cow<'_, A>
298where
299 A: Cowable + ?Sized + PartialOrd<B>,
300 B: Cowable + ?Sized,
301{
302 #[inline]
303 fn partial_cmp(&self, other: &Cow<'_, B>) -> Option<Ordering> {
304 PartialOrd::partial_cmp(self.deref(), other.deref())
305 }
306}
307
308impl<T> Ord for Cow<'_, T>
309where
310 T: Ord + Cowable + ?Sized,
311{
312 #[inline]
313 fn cmp(&self, other: &Self) -> Ordering {
314 Ord::cmp(self.deref(), other.deref())
315 }
316}
317
318impl<'a, T> From<&'a T> for Cow<'a, T>
319where
320 T: Cowable + ?Sized,
321{
322 #[inline]
323 fn from(val: &'a T) -> Self {
324 Cow::from_borrowed(val)
325 }
326}
327
328impl<'a, T> From<Arc<T>> for Cow<'a, T>
329where
330 T: Cowable + ?Sized,
331{
332 #[inline]
333 fn from(val: Arc<T>) -> Self {
334 Cow::from_shared(val)
335 }
336}
337
338impl<'a> From<std::borrow::Cow<'a, str>> for Cow<'a, str> {
339 #[inline]
340 fn from(s: std::borrow::Cow<'a, str>) -> Self {
341 match s {
342 std::borrow::Cow::Borrowed(bs) => Cow::from_borrowed(bs),
343 std::borrow::Cow::Owned(os) => Cow::from_owned(os),
344 }
345 }
346}
347
348impl<'a, T: Cowable + ?Sized> From<Cow<'a, T>> for std::borrow::Cow<'a, T> {
349 #[inline]
350 fn from(value: Cow<'a, T>) -> Self {
351 match value.metadata.kind() {
352 Kind::Owned | Kind::Shared => Self::Owned(value.into_owned()),
353 Kind::Borrowed => {
354 // SAFETY: We know the contained data is borrowed from 'a, we're simply
355 // restoring the original immutable reference and returning a copy of it.
356 Self::Borrowed(unsafe { &*T::borrowed_from_parts(value.ptr, &value.metadata) })
357 }
358 }
359 }
360}
361
362impl From<String> for Cow<'_, str> {
363 #[inline]
364 fn from(s: String) -> Self {
365 Cow::from_owned(s)
366 }
367}
368
369impl<T> From<Vec<T>> for Cow<'_, [T]>
370where
371 T: Clone,
372{
373 #[inline]
374 fn from(v: Vec<T>) -> Self {
375 Cow::from_owned(v)
376 }
377}
378
379impl<T> AsRef<T> for Cow<'_, T>
380where
381 T: Cowable + ?Sized,
382{
383 #[inline]
384 fn as_ref(&self) -> &T {
385 self.borrow()
386 }
387}
388
389impl<T> Borrow<T> for Cow<'_, T>
390where
391 T: Cowable + ?Sized,
392{
393 #[inline]
394 fn borrow(&self) -> &T {
395 self.deref()
396 }
397}
398
399impl<A, B> PartialEq<Cow<'_, B>> for Cow<'_, A>
400where
401 A: Cowable + ?Sized,
402 B: Cowable + ?Sized,
403 A: PartialEq<B>,
404{
405 fn eq(&self, other: &Cow<B>) -> bool {
406 self.deref() == other.deref()
407 }
408}
409
410impl<T> fmt::Debug for Cow<'_, T>
411where
412 T: Cowable + fmt::Debug + ?Sized,
413{
414 #[inline]
415 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
416 self.deref().fmt(f)
417 }
418}
419
420impl<T> fmt::Display for Cow<'_, T>
421where
422 T: Cowable + fmt::Display + ?Sized,
423{
424 #[inline]
425 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
426 self.deref().fmt(f)
427 }
428}
429
430// SAFETY: `NonNull<T>` is not `Send` or `Sync` by default, but we're asserting that `Cow` is so
431// long as the underlying `T` is.
432unsafe impl<T: Cowable + Sync + ?Sized> Sync for Cow<'_, T> {}
433unsafe impl<T: Cowable + Send + ?Sized> Send for Cow<'_, T> {}
434
435#[repr(C)]
436#[derive(Clone, Copy, Debug, PartialEq, Eq)]
437pub struct Metadata(usize, usize);
438
439impl Metadata {
440 #[inline]
441 const fn len(&self) -> usize {
442 self.0
443 }
444
445 #[inline]
446 const fn capacity(&self) -> usize {
447 self.1
448 }
449
450 #[inline]
451 const fn kind(&self) -> Kind {
452 match (self.0, self.1) {
453 (_, usize::MAX) => Kind::Shared,
454 (_, 0) => Kind::Borrowed,
455 _ => Kind::Owned,
456 }
457 }
458
459 #[inline]
460 const fn shared(len: usize) -> Metadata {
461 Metadata(len, usize::MAX)
462 }
463
464 #[inline]
465 const fn borrowed(len: usize) -> Metadata {
466 Metadata(len, 0)
467 }
468
469 #[inline]
470 const fn owned(len: usize, capacity: usize) -> Metadata {
471 Metadata(len, capacity)
472 }
473}
474
475pub trait Cowable: ToOwned {
476 type Pointer;
477
478 fn borrowed_into_parts(&self) -> (NonNull<Self::Pointer>, Metadata);
479 fn owned_into_parts(owned: <Self as ToOwned>::Owned) -> (NonNull<Self::Pointer>, Metadata);
480 fn shared_into_parts(arc: Arc<Self>) -> (NonNull<Self::Pointer>, Metadata);
481
482 fn borrowed_from_parts(ptr: NonNull<Self::Pointer>, metadata: &Metadata) -> *const Self;
483 fn owned_from_parts(
484 ptr: NonNull<Self::Pointer>,
485 metadata: &Metadata,
486 ) -> <Self as ToOwned>::Owned;
487 fn clone_from_parts(
488 ptr: NonNull<Self::Pointer>,
489 metadata: &Metadata,
490 ) -> (NonNull<Self::Pointer>, Metadata);
491 fn drop_from_parts(ptr: NonNull<Self::Pointer>, metadata: &Metadata);
492}
493
494impl Cowable for str {
495 type Pointer = u8;
496
497 #[inline]
498 fn borrowed_into_parts(&self) -> (NonNull<Self::Pointer>, Metadata) {
499 // SAFETY: We know that it's safe to take and hold a pointer to a reference to `Self` since
500 // `Cow` can only live as long as the input reference does, and an invalid pointer cannot
501 // be taken from a live reference.
502 let ptr = unsafe { NonNull::new_unchecked(self.as_ptr() as *mut _) };
503 let metadata = Metadata::borrowed(self.len());
504 (ptr, metadata)
505 }
506
507 #[inline]
508 fn owned_into_parts(owned: Self::Owned) -> (NonNull<Self::Pointer>, Metadata) {
509 // SAFETY: We know that it's safe to take and hold a pointer to a reference to `owned` since
510 // we own the allocation by virtue of consuming it here without dropping it.
511 let mut owned = ManuallyDrop::new(owned.into_bytes());
512 let ptr = unsafe { NonNull::new_unchecked(owned.as_mut_ptr()) };
513 let metadata = Metadata::owned(owned.len(), owned.capacity());
514 (ptr, metadata)
515 }
516
517 #[inline]
518 fn shared_into_parts(arc: Arc<Self>) -> (NonNull<Self::Pointer>, Metadata) {
519 let metadata = Metadata::shared(arc.len());
520 // SAFETY: We know that the pointer given back by `Arc::into_raw` is valid.
521 let ptr = unsafe { NonNull::new_unchecked(Arc::into_raw(arc) as *mut _) };
522 (ptr, metadata)
523 }
524
525 #[inline]
526 fn borrowed_from_parts(ptr: NonNull<Self::Pointer>, metadata: &Metadata) -> *const Self {
527 slice_from_raw_parts(ptr.as_ptr(), metadata.len()) as *const _
528 }
529
530 #[inline]
531 fn owned_from_parts(
532 ptr: NonNull<Self::Pointer>,
533 metadata: &Metadata,
534 ) -> <Self as ToOwned>::Owned {
535 match metadata.kind() {
536 Kind::Borrowed => {
537 // SAFETY: We know that it's safe to take and hold a pointer to a reference to
538 // `Self` since `Cow` can only live as long as the input reference does, and an
539 // invalid pointer cannot be taken from a live reference.
540 let s = unsafe { &*Self::borrowed_from_parts(ptr, metadata) };
541 s.to_owned()
542 }
543
544 // SAFETY: We know that the pointer is valid because it could have only been constructed
545 // from a valid `String` handed to `Cow::from_owned`, which we assumed ownership of.
546 Kind::Owned => unsafe {
547 String::from_raw_parts(ptr.as_ptr(), metadata.len(), metadata.capacity())
548 },
549 Kind::Shared => {
550 // SAFETY: We know that the pointer is valid because it could have only been
551 // constructed from a valid `Arc<str>` handed to `Cow::from_shared`, which we
552 // assumed ownership of, also ensuring that the strong count is at least one.
553 let s = unsafe { Arc::from_raw(Self::borrowed_from_parts(ptr, metadata)) };
554 s.to_string()
555 }
556 }
557 }
558
559 #[inline]
560 fn clone_from_parts(
561 ptr: NonNull<Self::Pointer>,
562 metadata: &Metadata,
563 ) -> (NonNull<Self::Pointer>, Metadata) {
564 match metadata.kind() {
565 Kind::Borrowed => (ptr, *metadata),
566 Kind::Owned => {
567 // SAFETY: We know that the pointer is valid because it could have only been constructed
568 // from a valid `String` handed to `Cow::from_owned`, which we assumed ownership of.
569 let s = unsafe { &*Self::borrowed_from_parts(ptr, metadata) };
570
571 Self::owned_into_parts(s.to_string())
572 }
573 Kind::Shared => clone_shared::<Self>(ptr, metadata),
574 }
575 }
576
577 #[inline]
578 fn drop_from_parts(ptr: NonNull<Self::Pointer>, metadata: &Metadata) {
579 match metadata.kind() {
580 Kind::Borrowed => {}
581
582 // SAFETY: We know that the pointer is valid because it could have only been constructed
583 // from a valid `String` handed to `Cow::from_owned`, which we assumed ownership of.
584 Kind::Owned => unsafe {
585 drop(Vec::from_raw_parts(ptr.as_ptr(), metadata.len(), metadata.capacity()));
586 },
587
588 // SAFETY: We know that the pointer is valid because it could have only been constructed
589 // from a valid `Arc<str>` handed to `Cow::from_shared`, which we assumed ownership of,
590 // also ensuring that the strong count is at least one.
591 Kind::Shared => unsafe {
592 drop(Arc::from_raw(Self::borrowed_from_parts(ptr, metadata)));
593 },
594 }
595 }
596}
597
598impl<T> Cowable for [T]
599where
600 T: Clone,
601{
602 type Pointer = T;
603
604 #[inline]
605 fn borrowed_into_parts(&self) -> (NonNull<Self::Pointer>, Metadata) {
606 // SAFETY: We know that it's safe to take and hold a pointer to a reference to `Self` since
607 // `Cow` can only live as long as the input reference does, and an invalid pointer cannot
608 // be taken from a live reference.
609 let ptr = unsafe { NonNull::new_unchecked(self.as_ptr() as *mut _) };
610 let metadata = Metadata::borrowed(self.len());
611 (ptr, metadata)
612 }
613
614 #[inline]
615 fn owned_into_parts(owned: <Self as ToOwned>::Owned) -> (NonNull<Self::Pointer>, Metadata) {
616 let mut owned = ManuallyDrop::new(owned);
617
618 // SAFETY: We know that it's safe to take and hold a pointer to a reference to `owned` since
619 // we own the allocation by virtue of consuming it here without dropping it.
620 let ptr = unsafe { NonNull::new_unchecked(owned.as_mut_ptr()) };
621 let metadata = Metadata::owned(owned.len(), owned.capacity());
622 (ptr, metadata)
623 }
624
625 #[inline]
626 fn shared_into_parts(arc: Arc<Self>) -> (NonNull<Self::Pointer>, Metadata) {
627 let metadata = Metadata::shared(arc.len());
628 // SAFETY: We know that the pointer given back by `Arc::into_raw` is valid.
629 let ptr = unsafe { NonNull::new_unchecked(Arc::into_raw(arc) as *mut _) };
630 (ptr, metadata)
631 }
632
633 #[inline]
634 fn borrowed_from_parts(ptr: NonNull<Self::Pointer>, metadata: &Metadata) -> *const Self {
635 slice_from_raw_parts(ptr.as_ptr(), metadata.len()) as *const _
636 }
637
638 #[inline]
639 fn owned_from_parts(
640 ptr: NonNull<Self::Pointer>,
641 metadata: &Metadata,
642 ) -> <Self as ToOwned>::Owned {
643 match metadata.kind() {
644 Kind::Borrowed => {
645 // SAFETY: We know that it's safe to take and hold a pointer to a reference to
646 // `Self` since `Cow` can only live as long as the input reference does, and an
647 // invalid pointer cannot be taken from a live reference.
648 let data = unsafe { &*Self::borrowed_from_parts(ptr, metadata) };
649 data.to_vec()
650 }
651
652 // SAFETY: We know that the pointer is valid because it could have only been
653 // constructed from a valid `Vec<T>` handed to `Cow::from_owned`, which we
654 // assumed ownership of.
655 Kind::Owned => unsafe {
656 Vec::from_raw_parts(ptr.as_ptr(), metadata.len(), metadata.capacity())
657 },
658
659 Kind::Shared => {
660 // SAFETY: We know that the pointer is valid because it could have only been
661 // constructed from a valid `Arc<[T]>` handed to `Cow::from_shared`, which we
662 // assumed ownership of, also ensuring that the strong count is at least one.
663 let arc = unsafe { Arc::from_raw(Self::borrowed_from_parts(ptr, metadata)) };
664 arc.to_vec()
665 }
666 }
667 }
668
669 #[inline]
670 fn clone_from_parts(
671 ptr: NonNull<Self::Pointer>,
672 metadata: &Metadata,
673 ) -> (NonNull<Self::Pointer>, Metadata) {
674 match metadata.kind() {
675 Kind::Borrowed => (ptr, *metadata),
676 Kind::Owned => {
677 let vec_ptr = Self::borrowed_from_parts(ptr, metadata);
678
679 // SAFETY: We know that the pointer is valid because it could have only been
680 // constructed from a valid `Vec<T>` handed to `Cow::from_owned`, which we assumed
681 // ownership of.
682 let new_vec = unsafe { vec_ptr.as_ref().unwrap().to_vec() };
683
684 Self::owned_into_parts(new_vec)
685 }
686 Kind::Shared => clone_shared::<Self>(ptr, metadata),
687 }
688 }
689
690 #[inline]
691 fn drop_from_parts(ptr: NonNull<Self::Pointer>, metadata: &Metadata) {
692 match metadata.kind() {
693 Kind::Borrowed => {}
694
695 // SAFETY: We know that the pointer is valid because it could have only been constructed
696 // from a valid `Vec<T>` handed to `Cow::from_owned`, which we assumed ownership of.
697 Kind::Owned => unsafe {
698 drop(Vec::from_raw_parts(ptr.as_ptr(), metadata.len(), metadata.capacity()));
699 },
700
701 // SAFETY: We know that the pointer is valid because it could have only been constructed
702 // from a valid `Arc<[T]>` handed to `Cow::from_shared`, which we assumed ownership of,
703 // also ensuring that the strong count is at least one.
704 Kind::Shared => unsafe {
705 drop(Arc::from_raw(Self::borrowed_from_parts(ptr, metadata)));
706 },
707 }
708 }
709}
710
711fn clone_shared<T: Cowable + ?Sized>(
712 ptr: NonNull<T::Pointer>,
713 metadata: &Metadata,
714) -> (NonNull<T::Pointer>, Metadata) {
715 let arc_ptr = T::borrowed_from_parts(ptr, metadata);
716
717 // SAFETY: We know that the pointer is valid because it could have only been
718 // constructed from a valid `Arc<T>` handed to `Cow::from_shared`, which we assumed
719 // ownership of, also ensuring that the strong count is at least one.
720 unsafe {
721 Arc::increment_strong_count(arc_ptr);
722 }
723
724 (ptr, *metadata)
725}
726
727/// These implementations should be identical to Deref, but enable dereferencing in a `const`
728/// environment for `Key` hashing.
729pub(crate) mod const_cow {
730 use super::*;
731 use crate::Label;
732 use std::ptr::slice_from_raw_parts;
733
734 impl Cow<'static, str> {
735 pub(crate) const fn as_const_str(&self) -> &str {
736 let borrowed_ptr =
737 slice_from_raw_parts(self.ptr.as_ptr(), self.metadata.len()) as *const str;
738
739 // SAFETY: We only ever hold a pointer to a borrowed value of at least the lifetime of
740 // `Self`, or an owned value which we have ownership of (albeit indirectly when using
741 // `Arc<T>`), so our pointer is always valid and live for dereferencing.
742 //
743 // self.ptr is also `NonNull<T>`, and so borrowed_ptr is guaranteed to not be null.
744 unsafe { &*borrowed_ptr }
745 }
746 }
747
748 impl Cow<'static, [Label]> {
749 pub(crate) const fn as_const_slice(&self) -> &[Label] {
750 let borrowed_ptr =
751 slice_from_raw_parts(self.ptr.as_ptr(), self.metadata.len()) as *const [Label];
752
753 // SAFETY: We only ever hold a pointer to a borrowed value of at least the lifetime of
754 // `Self`, or an owned value which we have ownership of (albeit indirectly when using
755 // `Arc<T>`), so our pointer is always valid and live for dereferencing.
756 //
757 // self.ptr is also `NonNull<T>`, and so borrowed_ptr is guaranteed to not be null.
758 unsafe { &*borrowed_ptr }
759 }
760 }
761
762 #[cfg(test)]
763 mod tests {
764 use super::*;
765 use std::sync::Arc;
766
767 #[test]
768 fn test_as_const_str() {
769 // Borrowed
770 let cow = Cow::const_str("hello");
771 assert_eq!(cow.as_const_str(), "hello");
772
773 // Owned
774 let cow: Cow<'static, str> = Cow::from_owned(String::from("hello"));
775 assert_eq!(cow.as_const_str(), "hello");
776
777 // Shared
778 let arc: Arc<str> = Arc::from("hello");
779 let cow: Cow<'static, str> = Cow::from_shared(arc);
780 assert_eq!(cow.as_const_str(), "hello");
781 }
782
783 #[test]
784 fn test_as_const_slice() {
785 // Borrowed
786 {
787 static LABELS: [Label; 2] = [
788 Label::from_static_parts("key1", "value1"),
789 Label::from_static_parts("key2", "value2"),
790 ];
791 let cow = Cow::const_slice(&LABELS);
792 let slice = cow.as_const_slice();
793 assert_eq!(slice.len(), 2);
794 assert_eq!(slice[0].key(), "key1");
795 assert_eq!(slice[0].value(), "value1");
796 assert_eq!(slice[1].key(), "key2");
797 assert_eq!(slice[1].value(), "value2");
798 }
799
800 // Owned
801 {
802 let labels = vec![
803 Label::from_static_parts("key1", "value1"),
804 Label::from_static_parts("key2", "value2"),
805 ];
806 let cow: Cow<'static, [Label]> = Cow::from_owned(labels);
807 let slice = cow.as_const_slice();
808 assert_eq!(slice.len(), 2);
809 assert_eq!(slice[0].key(), "key1");
810 assert_eq!(slice[0].value(), "value1");
811 assert_eq!(slice[1].key(), "key2");
812 assert_eq!(slice[1].value(), "value2");
813 }
814
815 // Shared
816 {
817 let labels: Arc<[Label]> = Arc::from([
818 Label::from_static_parts("key1", "value1"),
819 Label::from_static_parts("key2", "value2"),
820 ]);
821 let cow: Cow<'static, [Label]> = Cow::from_shared(labels);
822 let slice = cow.as_const_slice();
823 assert_eq!(slice.len(), 2);
824 assert_eq!(slice[0].key(), "key1");
825 assert_eq!(slice[0].value(), "value1");
826 assert_eq!(slice[1].key(), "key2");
827 assert_eq!(slice[1].value(), "value2");
828 }
829 }
830
831 #[test]
832 fn test_to_retained_str() {
833 let borrowed = Cow::const_str("hello").to_retained();
834 assert!(matches!(borrowed.metadata.kind(), Kind::Borrowed));
835
836 let owned: Cow<'static, str> = Cow::from_owned(String::from("hello"));
837 let retained = owned.to_retained();
838 assert!(matches!(retained.metadata.kind(), Kind::Shared));
839
840 let shared = Cow::from_shared(Arc::<str>::from("hello")).to_retained();
841 assert!(matches!(shared.metadata.kind(), Kind::Shared));
842 }
843
844 #[test]
845 fn test_to_retained_slice() {
846 static LABELS: [Label; 2] = [
847 Label::from_static_parts("key1", "value1"),
848 Label::from_static_parts("key2", "value2"),
849 ];
850
851 let borrowed = Cow::const_slice(&LABELS).to_retained();
852 assert!(matches!(borrowed.metadata.kind(), Kind::Borrowed));
853
854 let owned: Cow<'static, [Label]> = Cow::from_owned(LABELS.to_vec());
855 let retained = owned.to_retained();
856 assert!(matches!(retained.metadata.kind(), Kind::Shared));
857
858 let shared = Cow::from_shared(Arc::<[Label]>::from(&LABELS[..])).to_retained();
859 assert!(matches!(shared.metadata.kind(), Kind::Shared));
860 }
861 }
862}