|
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. |
5 | 6 | use crate::len_type::LenType;
|
6 | 7 | use crate::string::StringView;
|
7 | 8 | use crate::String;
|
8 | 9 | use core::borrow::Borrow;
|
9 | 10 |
|
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. |
15 | 12 | ///
|
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`. |
17 | 17 | ///
|
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>`. |
22 | 20 | #[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`. |
25 | 26 | Borrowed(&'a StringView<LenT>),
|
26 | 27 |
|
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`. |
28 | 32 | Owned(String<N, LenT>),
|
29 | 33 | }
|
30 | 34 |
|
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>`. |
33 | 40 | ///
|
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`. |
36 | 43 | pub fn to_owned(&self) -> String<N, LenT> {
|
37 | 44 | 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(), |
40 | 52 | }
|
41 | 53 | }
|
42 | 54 |
|
43 |
| - /// Returns the string as a `&str`. |
44 |
| - /// |
45 |
| - /// Works for both borrowed and owned variants. |
| 55 | + /// Return the inner value as `&str`. |
46 | 56 | pub fn as_str(&self) -> &str {
|
47 | 57 | 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(), |
50 | 61 | }
|
51 | 62 | }
|
52 | 63 |
|
53 |
| - /// Returns `true` if this `Cow` is a borrowed string. |
| 64 | + /// Is this a non-`'static` borrowed view? |
54 | 65 | pub fn is_borrowed(&self) -> bool {
|
55 |
| - matches!(self, Cow::Borrowed(_)) |
| 66 | + matches!(self, CowStr::Borrowed(_)) |
56 | 67 | }
|
57 | 68 |
|
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? |
59 | 75 | pub fn is_owned(&self) -> bool {
|
60 |
| - matches!(self, Cow::Owned(_)) |
| 76 | + matches!(self, CowStr::Owned(_)) |
61 | 77 | }
|
62 | 78 | }
|
63 | 79 |
|
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 | +{ |
66 | 84 | fn from(sv: &'a StringView<LenT>) -> Self {
|
67 |
| - Cow::Borrowed(sv) |
| 85 | + CowStr::Borrowed(sv) |
68 | 86 | }
|
69 | 87 | }
|
70 | 88 |
|
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 | +{ |
73 | 93 | fn from(s: String<N, LenT>) -> Self {
|
74 |
| - Cow::Owned(s) |
| 94 | + CowStr::Owned(s) |
75 | 95 | }
|
76 | 96 | }
|
77 | 97 |
|
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 | +{ |
82 | 112 | fn borrow(&self) -> &str {
|
83 | 113 | self.as_str()
|
84 | 114 | }
|
|
0 commit comments