diff options
author | Aleksey Kladov <[email protected]> | 2018-08-10 20:33:29 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-08-10 20:33:29 +0100 |
commit | 7c67612b8a894187fa3b64725531a5459f9211bf (patch) | |
tree | 9e2a536efa0c880d921fd8d4d74423afc9451fd4 /src/smol_str.rs | |
parent | 26262aaf05983c5b7f41cc438e287523268fe1eb (diff) |
organizize
Diffstat (limited to 'src/smol_str.rs')
-rw-r--r-- | src/smol_str.rs | 83 |
1 files changed, 0 insertions, 83 deletions
diff --git a/src/smol_str.rs b/src/smol_str.rs deleted file mode 100644 index abf69dce7..000000000 --- a/src/smol_str.rs +++ /dev/null | |||
@@ -1,83 +0,0 @@ | |||
1 | use std::{sync::Arc}; | ||
2 | |||
3 | const INLINE_CAP: usize = 22; | ||
4 | const WS_TAG: u8 = (INLINE_CAP + 1) as u8; | ||
5 | |||
6 | #[derive(Clone, Debug)] | ||
7 | pub(crate) enum SmolStr { | ||
8 | Heap(Arc<str>), | ||
9 | Inline { | ||
10 | len: u8, | ||
11 | buf: [u8; INLINE_CAP], | ||
12 | }, | ||
13 | } | ||
14 | |||
15 | impl SmolStr { | ||
16 | pub fn new(text: &str) -> SmolStr { | ||
17 | let len = text.len(); | ||
18 | if len <= INLINE_CAP { | ||
19 | let mut buf = [0; INLINE_CAP]; | ||
20 | buf[..len].copy_from_slice(text.as_bytes()); | ||
21 | return SmolStr::Inline { len: len as u8, buf }; | ||
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 | ) | ||
36 | } | ||
37 | |||
38 | pub fn as_str(&self) -> &str { | ||
39 | match self { | ||
40 | SmolStr::Heap(data) => &*data, | ||
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 | |||
49 | let len = *len as usize; | ||
50 | let buf = &buf[..len]; | ||
51 | unsafe { ::std::str::from_utf8_unchecked(buf) } | ||
52 | } | ||
53 | } | ||
54 | } | ||
55 | } | ||
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 | |||
63 | #[cfg(test)] | ||
64 | mod tests { | ||
65 | use super::*; | ||
66 | |||
67 | #[test] | ||
68 | #[cfg(target_pointer_width = "64")] | ||
69 | fn smol_str_is_smol() { | ||
70 | assert_eq!(::std::mem::size_of::<SmolStr>(), 8 + 8 + 8) | ||
71 | } | ||
72 | |||
73 | #[test] | ||
74 | fn test_round_trip() { | ||
75 | let mut text = String::new(); | ||
76 | for n in 0..256 { | ||
77 | let smol = SmolStr::new(&text); | ||
78 | assert_eq!(smol.as_str(), text.as_str()); | ||
79 | text.push_str(&n.to_string()); | ||
80 | } | ||
81 | } | ||
82 | } | ||
83 | |||