zenoh_protocol/core/
cowstr.rs1use alloc::{borrow::ToOwned, boxed::Box, string::String, vec::Vec};
15use core::{
16 fmt::{Debug, Display, Formatter},
17 num::NonZeroUsize,
18};
19
20enum CowStrInner<'a> {
21 Borrowed(&'a str),
22 Owned { s: Box<str>, capacity: NonZeroUsize },
23}
24pub struct CowStr<'a>(CowStrInner<'a>);
25impl<'a> CowStr<'a> {
26 pub(crate) const fn borrowed(s: &'a str) -> Self {
27 Self(CowStrInner::Borrowed(s))
28 }
29 pub fn as_str(&self) -> &str {
30 self
31 }
32}
33impl<'a> From<alloc::borrow::Cow<'a, str>> for CowStr<'a> {
34 fn from(value: alloc::borrow::Cow<'a, str>) -> Self {
35 match value {
36 alloc::borrow::Cow::Borrowed(s) => CowStr::borrowed(s),
37 alloc::borrow::Cow::Owned(s) => s.into(),
38 }
39 }
40}
41impl<'a> From<&'a str> for CowStr<'a> {
42 fn from(value: &'a str) -> Self {
43 CowStr::borrowed(value)
44 }
45}
46impl From<String> for CowStr<'_> {
47 fn from(s: String) -> Self {
48 if s.is_empty() {
49 CowStr::borrowed("")
50 } else {
51 let capacity = unsafe { NonZeroUsize::new_unchecked(s.capacity()) };
52 Self(CowStrInner::Owned {
53 s: s.into_boxed_str(),
54 capacity,
55 })
56 }
57 }
58}
59impl AsRef<str> for CowStr<'_> {
60 fn as_ref(&self) -> &str {
61 self
62 }
63}
64impl core::ops::Deref for CowStr<'_> {
65 type Target = str;
66 fn deref(&self) -> &Self::Target {
67 match &self.0 {
68 CowStrInner::Borrowed(s) => s,
69 CowStrInner::Owned { s, .. } => s,
70 }
71 }
72}
73impl Clone for CowStr<'_> {
74 fn clone(&self) -> Self {
75 self.as_str().to_owned().into()
76 }
77}
78impl Debug for CowStr<'_> {
79 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
80 f.write_str(self)
81 }
82}
83impl Display for CowStr<'_> {
84 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
85 f.write_str(self)
86 }
87}
88impl PartialEq for CowStr<'_> {
89 fn eq(&self, other: &Self) -> bool {
90 self.as_str() == other.as_str()
91 }
92}
93impl Eq for CowStr<'_> {}
94impl core::ops::Add<&str> for CowStr<'_> {
95 type Output = String;
96 fn add(self, rhs: &str) -> Self::Output {
97 match self.0 {
98 CowStrInner::Borrowed(s) => {
99 let mut ans = String::with_capacity(s.len() + rhs.len());
100 ans.push_str(s);
101 ans.push_str(rhs);
102 ans
103 }
104 CowStrInner::Owned { mut s, capacity } => unsafe {
105 let mut s = String::from_utf8_unchecked(Vec::from_raw_parts(
106 s.as_mut_ptr(),
107 s.len(),
108 capacity.get(),
109 ));
110 s += rhs;
111 s
112 },
113 }
114 }
115}