diff options
Diffstat (limited to 'src/smol_str.rs')
-rw-r--r-- | src/smol_str.rs | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/src/smol_str.rs b/src/smol_str.rs index 2a330c343..abf69dce7 100644 --- a/src/smol_str.rs +++ b/src/smol_str.rs | |||
@@ -1,6 +1,7 @@ | |||
1 | use std::{sync::Arc}; | 1 | use std::{sync::Arc}; |
2 | 2 | ||
3 | const INLINE_CAP: usize = 22; | 3 | const INLINE_CAP: usize = 22; |
4 | const WS_TAG: u8 = (INLINE_CAP + 1) as u8; | ||
4 | 5 | ||
5 | #[derive(Clone, Debug)] | 6 | #[derive(Clone, Debug)] |
6 | pub(crate) enum SmolStr { | 7 | pub(crate) enum SmolStr { |
@@ -17,18 +18,34 @@ impl SmolStr { | |||
17 | if len <= INLINE_CAP { | 18 | if len <= INLINE_CAP { |
18 | let mut buf = [0; INLINE_CAP]; | 19 | let mut buf = [0; INLINE_CAP]; |
19 | buf[..len].copy_from_slice(text.as_bytes()); | 20 | buf[..len].copy_from_slice(text.as_bytes()); |
20 | SmolStr::Inline { len: len as u8, buf } | 21 | return SmolStr::Inline { len: len as u8, buf }; |
21 | } else { | ||
22 | SmolStr::Heap( | ||
23 | text.to_string().into_boxed_str().into() | ||
24 | ) | ||
25 | } | 22 | } |
23 | |||
24 | let newlines = text.bytes().take_while(|&b| b == b'\n').count(); | ||
25 | let spaces = text[newlines..].bytes().take_while(|&b| b == b' ').count(); | ||
26 | if newlines + spaces == len && newlines <= N_NEWLINES && spaces <= N_SPACES { | ||
27 | let mut buf = [0; INLINE_CAP]; | ||
28 | buf[0] = newlines as u8; | ||
29 | buf[1] = spaces as u8; | ||
30 | return SmolStr::Inline { len: WS_TAG, buf }; | ||
31 | } | ||
32 | |||
33 | SmolStr::Heap( | ||
34 | text.to_string().into_boxed_str().into() | ||
35 | ) | ||
26 | } | 36 | } |
27 | 37 | ||
28 | pub fn as_str(&self) -> &str { | 38 | pub fn as_str(&self) -> &str { |
29 | match self { | 39 | match self { |
30 | SmolStr::Heap(data) => &*data, | 40 | SmolStr::Heap(data) => &*data, |
31 | SmolStr::Inline { len, buf } => { | 41 | SmolStr::Inline { len, buf } => { |
42 | if *len == WS_TAG { | ||
43 | let newlines = buf[0] as usize; | ||
44 | let spaces = buf[1] as usize; | ||
45 | assert!(newlines <= N_NEWLINES && spaces <= N_SPACES); | ||
46 | return &WS[N_NEWLINES - newlines..N_NEWLINES + spaces] | ||
47 | } | ||
48 | |||
32 | let len = *len as usize; | 49 | let len = *len as usize; |
33 | let buf = &buf[..len]; | 50 | let buf = &buf[..len]; |
34 | unsafe { ::std::str::from_utf8_unchecked(buf) } | 51 | unsafe { ::std::str::from_utf8_unchecked(buf) } |
@@ -37,6 +54,12 @@ impl SmolStr { | |||
37 | } | 54 | } |
38 | } | 55 | } |
39 | 56 | ||
57 | const N_NEWLINES: usize = 32; | ||
58 | const N_SPACES: usize = 128; | ||
59 | const WS: &str = | ||
60 | "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n "; | ||
61 | |||
62 | |||
40 | #[cfg(test)] | 63 | #[cfg(test)] |
41 | mod tests { | 64 | mod tests { |
42 | use super::*; | 65 | use super::*; |