1use crate::counter::Counter;
2use crate::Vec;
3use alloc::boxed::Box;
4use core::fmt;
5use core::ops::{Deref, RangeBounds};
6use core::str::Utf8Error;
7
8pub struct String<C: Counter<usize>> {
18 vec: Vec<C, u8>,
19}
20
21impl<C: Counter<usize>> String<C> {
22 #[inline]
24 pub fn new() -> Self {
25 Self { vec: Vec::new() }
26 }
27
28 #[inline]
34 pub fn from_utf8(bytes: Box<[u8]>) -> Result<Self, Utf8Error> {
35 str::from_utf8(&bytes)?;
36 Ok(Self {
37 vec: Vec::from_boxed_slice(bytes),
38 })
39 }
40
41 #[inline]
47 pub unsafe fn from_utf8_unchecked(bytes: Box<[u8]>) -> Self {
48 Self {
49 vec: Vec::from_boxed_slice(bytes),
50 }
51 }
52
53 #[inline]
55 pub fn from_boxed_str(bytes: Box<str>) -> Self {
56 unsafe { Self::from_utf8_unchecked(bytes.into_boxed_bytes()) }
57 }
58}
59
60impl<C: Counter<usize>> Default for String<C> {
61 fn default() -> Self {
62 Self::new()
63 }
64}
65
66impl<C: Counter<usize>> Clone for String<C> {
67 #[inline]
69 fn clone(&self) -> Self {
70 Self {
71 vec: self.vec.clone(),
72 }
73 }
74}
75
76impl<C: Counter<usize>> Deref for String<C> {
77 type Target = str;
78
79 #[inline]
80 fn deref(&self) -> &Self::Target {
81 unsafe { str::from_utf8_unchecked(&self.vec) }
82 }
83}
84
85impl<C: Counter<usize>> fmt::Debug for String<C> {
86 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87 <str as fmt::Debug>::fmt(&**self, f)
88 }
89}
90
91impl<C: Counter<usize>> String<C> {
92 #[inline]
94 pub const fn len(&self) -> usize {
95 self.vec.len()
96 }
97
98 #[inline]
100 pub const fn is_empty(&self) -> bool {
101 self.vec.is_empty()
102 }
103
104 #[inline]
106 pub fn bytes(&self) -> &[u8] {
107 &self.vec
108 }
109
110 #[inline]
112 pub fn as_str(&self) -> &str {
113 self
114 }
115
116 #[inline]
118 pub fn as_original_str(&self) -> &str {
119 unsafe { str::from_utf8_unchecked(self.vec.as_original_slice()) }
120 }
121
122 #[inline]
124 pub(crate) fn convert_range_unchecked(&self, range: impl RangeBounds<usize>) -> (usize, usize) {
125 self.vec.convert_range_unchecked(range)
126 }
127
128 #[inline]
130 pub(crate) fn validate_range(&self, range: impl RangeBounds<usize>) -> Option<(usize, usize)> {
131 let cap = self.len();
132 let start = match range.start_bound() {
133 core::ops::Bound::Included(&s) => s,
134 core::ops::Bound::Excluded(&s) => s.checked_add(1)?,
135 core::ops::Bound::Unbounded => 0,
136 };
137 let end = match range.end_bound() {
138 core::ops::Bound::Included(&e) => e.checked_add(1)?,
139 core::ops::Bound::Excluded(&e) => e,
140 core::ops::Bound::Unbounded => cap,
141 };
142 if end > cap {
143 return None;
144 }
145 let s = self.as_str();
146 if !s.is_char_boundary(start) || !s.is_char_boundary(end) {
147 return None;
148 }
149 (end.checked_sub(start)).map(|len| (start, len))
150 }
151
152 #[inline]
154 pub fn is_valid_range(&self, range: impl RangeBounds<usize>) -> bool {
155 self.validate_range(range).is_some()
156 }
157
158 #[inline]
160 pub fn get(&self, range: impl RangeBounds<usize>) -> Option<Self> {
161 let (start, len) = self.validate_range(range)?;
162 Some(Self {
163 vec: unsafe { self.vec.slice(start, len) },
164 })
165 }
166
167 #[inline]
173 pub fn idx(&self, range: impl RangeBounds<usize>) -> Self {
174 self.get(range).expect("Invalid range")
175 }
176
177 #[inline]
183 pub unsafe fn get_unchecked(&self, range: impl RangeBounds<usize>) -> Self {
184 let (start, len) = self.convert_range_unchecked(range);
185 let vec = self.vec.slice(start, len);
186 Self { vec }
187 }
188}
189
190impl<C: Counter<usize>> fmt::Display for String<C> {
191 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192 <str as fmt::Display>::fmt(self, f)
193 }
194}