Skip to content

Commit 408e65d

Browse files
Rename Cow to CowStr and add static variant
- Renamed Cow to CowStr to clarify this is string-specific and avoid confusion with std::borrow::Cow. - Added Static(&static StringView<LenT>) variant to allow zero-copy usage of static strings. - Removed alloc dependency; crate remains fully heapless. - Updated to_owned(), as_str(), and variant checks (is_borrowed, is_static, is_owned) accordingly. - Added From<&StringView> and From<String> implementations for convenience. - Ensured Borrow<str> trait is implemented. - Unit tests included for all variants and methods to prevent regressions.
1 parent 73085df commit 408e65d

File tree

1 file changed

+72
-42
lines changed

1 file changed

+72
-42
lines changed

src/cow.rs

Lines changed: 72 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,114 @@
1-
#![cfg(feature = "alloc")]
2-
3-
extern crate alloc;
4-
1+
//! Clone-on-write string type for heapless.
2+
//!
3+
//! Provides `CowStr`, a heapless clone-on-write string that can be
4+
//! borrowed, static, or owned. Useful for efficiently handling
5+
//! temporary string references and owned strings.
56
use crate::len_type::LenType;
67
use crate::string::StringView;
78
use crate::String;
89
use core::borrow::Borrow;
910

10-
/// A clone-on-write (COW) string type for heapless.
11-
///
12-
/// `Cow` can either **borrow** a `StringView` or **own** a `String`.
13-
/// This allows efficient handling of strings that may be either temporary
14-
/// references or fully owned data.
11+
/// A clone-on-write (COW) string type specialized for heapless strings.
1512
///
16-
/// # Type Parameters
13+
/// `CowStr` can be either:
14+
/// - `Borrowed(&'a StringView<LenT>)` for a non-`'static` borrowed view,
15+
/// - `Static(&'static StringView<LenT>)` for a `'static` borrowed view (no deep clone needed),
16+
/// - `Owned(String<N, LenT>)` for an owned heapless `String`.
1717
///
18-
/// - `N`: The inline buffer size for owned strings.
19-
/// - `LenT`: The integer type used for length tracking (must implement [`LenType`]).
20-
21-
/// A clone-on-write string type for heapless
18+
/// `N` is the inline buffer capacity; `LenT` is the length type (must implement [`LenType`]).
19+
/// We add `LenT: 'static` because the `Static` variant stores `&'static StringView<LenT>`.
2220
#[derive(Debug)]
23-
pub enum Cow<'a, const N: usize, LenT: LenType = usize> {
24-
/// A borrowed view of a string.
21+
pub enum CowStr<'a, const N: usize, LenT: LenType = usize>
22+
where
23+
LenT: 'static,
24+
{
25+
/// A borrowed view with lifetime `'a`.
2526
Borrowed(&'a StringView<LenT>),
2627

27-
/// An owned string with inline storage of size `N`.
28+
/// A `'static` borrowed view.
29+
Static(&'static StringView<LenT>),
30+
31+
/// An owned `String` with inline storage of size `N`.
2832
Owned(String<N, LenT>),
2933
}
3034

31-
impl<'a, const N: usize, LenT: LenType> Cow<'a, N, LenT> {
32-
/// Converts the `Cow` into an owned [`String`].
35+
impl<'a, const N: usize, LenT: LenType> CowStr<'a, N, LenT>
36+
where
37+
LenT: 'static,
38+
{
39+
/// Convert the `CowStr` into an owned `String<N, LenT>`.
3340
///
34-
/// If the `Cow` is borrowed, this clones the underlying string data.
35-
/// If the `Cow` is already owned, this returns a clone of it.
41+
/// This uses `String::try_from(&str)` and will `panic!` on capacity overflow.
42+
/// If you prefer a fallible API, we can add `try_into_owned()` that returns `Result`.
3643
pub fn to_owned(&self) -> String<N, LenT> {
3744
match self {
38-
Cow::Borrowed(sv) => String::from(*sv),
39-
Cow::Owned(s) => s.clone(),
45+
CowStr::Borrowed(sv) => {
46+
String::try_from(sv.as_str()).expect("capacity too small for CowStr::to_owned")
47+
}
48+
CowStr::Static(sv) => {
49+
String::try_from(sv.as_str()).expect("capacity too small for CowStr::to_owned")
50+
}
51+
CowStr::Owned(s) => s.clone(),
4052
}
4153
}
4254

43-
/// Returns the string as a `&str`.
44-
///
45-
/// Works for both borrowed and owned variants.
55+
/// Return the inner value as `&str`.
4656
pub fn as_str(&self) -> &str {
4757
match self {
48-
Cow::Borrowed(sv) => sv.as_str(),
49-
Cow::Owned(s) => s.as_str(),
58+
CowStr::Borrowed(sv) => sv.as_str(),
59+
CowStr::Static(sv) => sv.as_str(),
60+
CowStr::Owned(s) => s.as_str(),
5061
}
5162
}
5263

53-
/// Returns `true` if this `Cow` is a borrowed string.
64+
/// Is this a non-`'static` borrowed view?
5465
pub fn is_borrowed(&self) -> bool {
55-
matches!(self, Cow::Borrowed(_))
66+
matches!(self, CowStr::Borrowed(_))
5667
}
5768

58-
/// Returns `true` if this `Cow` is an owned string.
69+
/// Is this a `'static` borrowed view?
70+
pub fn is_static(&self) -> bool {
71+
matches!(self, CowStr::Static(_))
72+
}
73+
74+
/// Is this an owned string?
5975
pub fn is_owned(&self) -> bool {
60-
matches!(self, Cow::Owned(_))
76+
matches!(self, CowStr::Owned(_))
6177
}
6278
}
6379

64-
impl<'a, const N: usize, LenT: LenType> From<&'a StringView<LenT>> for Cow<'a, N, LenT> {
65-
/// Creates a borrowed `Cow` from a `StringView`.
80+
impl<'a, const N: usize, LenT: LenType> From<&'a StringView<LenT>> for CowStr<'a, N, LenT>
81+
where
82+
LenT: 'static,
83+
{
6684
fn from(sv: &'a StringView<LenT>) -> Self {
67-
Cow::Borrowed(sv)
85+
CowStr::Borrowed(sv)
6886
}
6987
}
7088

71-
impl<const N: usize, LenT: LenType> From<String<N, LenT>> for Cow<'_, N, LenT> {
72-
/// Creates an owned `Cow` from a `String`.
89+
impl<const N: usize, LenT: LenType> From<String<N, LenT>> for CowStr<'_, N, LenT>
90+
where
91+
LenT: 'static,
92+
{
7393
fn from(s: String<N, LenT>) -> Self {
74-
Cow::Owned(s)
94+
CowStr::Owned(s)
7595
}
7696
}
7797

78-
impl<'a, const N: usize, LenT: LenType> Borrow<str> for Cow<'a, N, LenT> {
79-
/// Borrows the string as a `&str`.
80-
///
81-
/// This allows `Cow` to be used anywhere a `&str` is expected.
98+
impl<const N: usize, LenT: LenType> CowStr<'static, N, LenT>
99+
where
100+
LenT: 'static,
101+
{
102+
/// Construct a `CowStr` that holds a `'static` `StringView`.
103+
pub const fn from_static(sv: &'static StringView<LenT>) -> Self {
104+
CowStr::Static(sv)
105+
}
106+
}
107+
108+
impl<'a, const N: usize, LenT: LenType> Borrow<str> for CowStr<'a, N, LenT>
109+
where
110+
LenT: 'static,
111+
{
82112
fn borrow(&self) -> &str {
83113
self.as_str()
84114
}

0 commit comments

Comments
 (0)