1use crate::Cow;
2use alloc::string::{String, ToString};
3
4pub enum Shard<'a> {
5 Borrowed { whole: &'a str, slen: usize },
6 Owned(String),
7}
8
9impl<'a> Shard<'a> {
10 #[inline]
11 pub fn new(whole: &'a str) -> Self {
12 Self::Borrowed { whole, slen: 0 }
13 }
14
15 #[inline]
16 pub fn len(&self) -> usize {
17 match self {
18 Self::Borrowed { ref slen, .. } => *slen,
19 Self::Owned(ref owned) => owned.len(),
20 }
21 }
22
23 #[inline]
24 pub fn is_empty(&self) -> bool {
25 self.len() == 0
26 }
27
28 fn to_mut(&mut self) -> &mut String {
29 if let Self::Borrowed { whole, slen } = *self {
30 *self = Self::Owned(whole[..slen].to_string());
31 }
32 match *self {
33 Self::Borrowed { .. } => unreachable!(),
34 Self::Owned(ref mut x) => x,
35 }
36 }
37
38 #[inline]
39 pub fn skip(&mut self, len: usize) {
40 if let Self::Borrowed { whole, slen: 0 } = self {
41 *whole = &whole[len..];
42 }
43 }
44
45 #[inline]
47 pub fn push_owned(&mut self, ch: char) {
48 self.to_mut().push(ch);
49 }
50
51 pub fn push(&mut self, ch: char) {
52 match self {
53 Self::Borrowed { whole, slen } => {
54 let slen = *slen;
55 let new_len = slen + ch.len_utf8();
56 *self = if !whole[slen..].starts_with(ch) {
57 let mut owned = whole[..slen].to_string();
59 owned.push(ch);
60 Self::Owned(owned)
61 } else {
62 Self::Borrowed {
64 whole,
65 slen: new_len,
66 }
67 };
68 }
69 Self::Owned(ref mut x) => x.push(ch),
70 }
71 }
72
73 pub fn finish(self) -> Cow<'a, str> {
74 if self.is_empty() {
75 Cow::Borrowed("")
76 } else {
77 match self {
78 Self::Borrowed { whole, slen } => Cow::Borrowed(&whole[..slen]),
79 Self::Owned(x) => Cow::Owned(x),
80 }
81 }
82 }
83
84 pub(crate) fn finish_cvg(self) -> Option<Cow<'a, str>> {
85 if self.is_empty() {
86 None
87 } else {
88 Some(self.finish())
89 }
90 }
91}