1use std::{
2 borrow::Borrow,
3 convert::TryFrom,
4 fmt::{Debug, Display},
5 hash::Hash,
6 ops::{Deref, RangeBounds},
7 str::Utf8Error,
8};
9
10use bytes::Bytes;
11
12use crate::TextMut;
13
14#[derive(Default, Clone)]
30pub struct Text(Bytes);
31
32impl Text {
33 pub fn new() -> Self {
43 Self(Bytes::new())
44 }
45
46 pub fn from_utf8(b: Bytes) -> Result<Self, Utf8Error> {
62 let _ = std::str::from_utf8(b.as_ref())?;
64 Ok(Self(b))
65 }
66
67 #[inline]
87 pub const unsafe fn from_utf8_unchecked(b: Bytes) -> Self {
88 Self(b)
89 }
90
91 pub fn copy_from(s: impl AsRef<str>) -> Self {
102 Self(Bytes::copy_from_slice(s.as_ref().as_bytes()))
105 }
106
107 pub const fn from_static(s: &'static str) -> Self {
121 Self(Bytes::from_static(s.as_bytes()))
122 }
123
124 pub fn len(&self) -> usize {
132 self.0.len()
133 }
134
135 pub fn is_empty(&self) -> bool {
145 self.0.is_empty()
146 }
147
148 pub const fn as_bytes(&self) -> &Bytes {
160 &self.0
161 }
162
163 pub fn into_bytes(self) -> Bytes {
175 self.0
176 }
177
178 pub fn get(&self, r: impl RangeBounds<usize>) -> Option<Text> {
192 let start = match r.start_bound() {
193 std::ops::Bound::Included(&i) => i,
194 std::ops::Bound::Excluded(&i) => i.checked_add(1)?,
195 std::ops::Bound::Unbounded => 0,
196 };
197 let end = match r.end_bound() {
198 std::ops::Bound::Included(&i) => i.checked_add(1)?,
199 std::ops::Bound::Excluded(&i) => i,
200 std::ops::Bound::Unbounded => self.len(),
201 };
202 soft_assert::soft_assert!(self.is_char_boundary(start) && self.is_char_boundary(end));
205 Some(Self(self.0.slice(start..end)))
206 }
207
208 pub fn split_at(mut self, index: usize) -> Result<(Self, Self), Self> {
222 soft_assert::soft_assert!(self.is_char_boundary(index), Err(self));
223 let right = self.0.split_off(index);
224 Ok((Self(self.0), Self(right)))
225 }
226
227 pub fn split_off(&mut self, index: usize) -> Option<Self> {
243 soft_assert::soft_assert!(self.is_char_boundary(index));
244 let right = self.0.split_off(index);
245 Some(Self(right))
246 }
247
248 pub fn split_to(&mut self, index: usize) -> Option<Self> {
264 soft_assert::soft_assert!(self.is_char_boundary(index));
265 let right = self.0.split_to(index);
266 Some(Self(right))
267 }
268
269 fn as_str(&self) -> &str {
270 unsafe { std::str::from_utf8_unchecked(self.0.as_ref()) }
271 }
272}
273
274impl AsRef<str> for Text {
277 fn as_ref(&self) -> &str {
278 self.as_str()
279 }
280}
281
282impl Borrow<str> for Text {
283 fn borrow(&self) -> &str {
284 self.as_str()
285 }
286}
287
288impl Deref for Text {
289 type Target = str;
290
291 fn deref(&self) -> &Self::Target {
292 self.as_str()
293 }
294}
295
296impl From<&'static str> for Text {
297 fn from(s: &'static str) -> Self {
298 Self::from_static(s)
299 }
300}
301
302impl From<String> for Text {
303 fn from(s: String) -> Self {
304 Self(Bytes::from(s.into_bytes()))
305 }
306}
307
308impl TryFrom<Bytes> for Text {
309 type Error = Utf8Error;
310
311 fn try_from(b: Bytes) -> Result<Self, Self::Error> {
312 Self::from_utf8(b)
313 }
314}
315
316impl From<Text> for Bytes {
317 fn from(t: Text) -> Self {
318 t.into_bytes()
319 }
320}
321
322impl Display for Text {
325 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
326 Display::fmt(self.as_str(), f)
327 }
328}
329
330impl Debug for Text {
331 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
332 Debug::fmt(self.as_str(), f)
333 }
334}
335
336impl PartialEq for Text {
341 fn eq(&self, other: &Self) -> bool {
342 (&**self).eq(&**other)
343 }
344}
345
346impl Eq for Text {}
347
348impl PartialEq<&Text> for Text {
349 fn eq(&self, other: &&Text) -> bool {
350 (&**self).eq(&***other)
351 }
352}
353
354impl PartialEq<&mut Text> for Text {
355 fn eq(&self, other: &&mut Text) -> bool {
356 (&**self).eq(&***other)
357 }
358}
359
360impl PartialOrd for Text {
361 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
362 Some(self.cmp(other))
363 }
364}
365
366impl Ord for Text {
367 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
368 (&**self).cmp(&**other)
369 }
370}
371impl PartialEq<str> for Text {
374 fn eq(&self, other: &str) -> bool {
375 (&**self).eq(other)
376 }
377}
378
379impl PartialEq<&str> for Text {
380 fn eq(&self, other: &&str) -> bool {
381 (&**self).eq(*other)
382 }
383}
384
385impl PartialEq<&mut str> for Text {
386 fn eq(&self, other: &&mut str) -> bool {
387 (&**self).eq(*other)
388 }
389}
390
391impl PartialOrd<str> for Text {
392 fn partial_cmp(&self, other: &str) -> Option<std::cmp::Ordering> {
393 (&**self).partial_cmp(other)
394 }
395}
396
397impl PartialOrd<&str> for Text {
398 fn partial_cmp(&self, other: &&str) -> Option<std::cmp::Ordering> {
399 (&**self).partial_cmp(*other)
400 }
401}
402
403impl PartialOrd<&mut str> for Text {
404 fn partial_cmp(&self, other: &&mut str) -> Option<std::cmp::Ordering> {
405 (&**self).partial_cmp(*other)
406 }
407}
408
409impl PartialEq<String> for Text {
412 fn eq(&self, other: &String) -> bool {
413 (&**self).eq(other)
414 }
415}
416
417impl PartialEq<&String> for Text {
418 fn eq(&self, other: &&String) -> bool {
419 (&**self).eq(*other)
420 }
421}
422
423impl PartialEq<&mut String> for Text {
424 fn eq(&self, other: &&mut String) -> bool {
425 (&**self).eq(*other)
426 }
427}
428
429impl PartialOrd<String> for Text {
430 fn partial_cmp(&self, other: &String) -> Option<std::cmp::Ordering> {
431 (&**self).partial_cmp(&**other)
432 }
433}
434
435impl PartialOrd<&String> for Text {
436 fn partial_cmp(&self, other: &&String) -> Option<std::cmp::Ordering> {
437 (&**self).partial_cmp(&***other)
438 }
439}
440
441impl PartialOrd<&mut String> for Text {
442 fn partial_cmp(&self, other: &&mut String) -> Option<std::cmp::Ordering> {
443 (&**self).partial_cmp(&***other)
444 }
445}
446
447impl PartialEq<TextMut> for Text {
450 fn eq(&self, other: &TextMut) -> bool {
451 (&**self).eq(&**other)
452 }
453}
454
455impl PartialEq<&TextMut> for Text {
456 fn eq(&self, other: &&TextMut) -> bool {
457 (&**self).eq(&***other)
458 }
459}
460
461impl PartialEq<&mut TextMut> for Text {
462 fn eq(&self, other: &&mut TextMut) -> bool {
463 (&**self).eq(&***other)
464 }
465}
466
467impl PartialOrd<TextMut> for Text {
468 fn partial_cmp(&self, other: &TextMut) -> Option<std::cmp::Ordering> {
469 (&**self).partial_cmp(&**other)
470 }
471}
472
473impl PartialOrd<&TextMut> for Text {
474 fn partial_cmp(&self, other: &&TextMut) -> Option<std::cmp::Ordering> {
475 (&**self).partial_cmp(&***other)
476 }
477}
478
479impl PartialOrd<&mut TextMut> for Text {
480 fn partial_cmp(&self, other: &&mut TextMut) -> Option<std::cmp::Ordering> {
481 (&**self).partial_cmp(&***other)
482 }
483}
484
485impl Hash for Text {
488 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
489 (&**self).hash(state);
490 }
491}