aboutsummaryrefslogtreecommitdiff
path: root/src/smol_str.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-08-09 00:26:22 +0100
committerAleksey Kladov <[email protected]>2018-08-09 00:26:22 +0100
commit08475a690ccc26ab5fd5e809a8cd3a19fcf5aff4 (patch)
tree81a7395c814dc97ada0e1065896c73e3b1bb2cee /src/smol_str.rs
parent7974c6b1a0b2d07c5a337c89a70a51e01f629778 (diff)
Simplify string optimizations
Diffstat (limited to 'src/smol_str.rs')
-rw-r--r--src/smol_str.rs33
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 @@
1use std::{sync::Arc}; 1use std::{sync::Arc};
2 2
3const INLINE_CAP: usize = 22; 3const INLINE_CAP: usize = 22;
4const WS_TAG: u8 = (INLINE_CAP + 1) as u8;
4 5
5#[derive(Clone, Debug)] 6#[derive(Clone, Debug)]
6pub(crate) enum SmolStr { 7pub(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
57const N_NEWLINES: usize = 32;
58const N_SPACES: usize = 128;
59const 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)]
41mod tests { 64mod tests {
42 use super::*; 65 use super::*;