aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-08-08 18:25:35 +0100
committerAleksey Kladov <[email protected]>2018-08-08 18:25:35 +0100
commit1fa5b2ffbc0f1dd3cfc45adff0329e1bdd46c131 (patch)
tree5ebfc103a7d5c69705fdfc1166dbf60e61a9e441
parentcc4c90aa2cf4da819dd324a7bbf8b36f6a068a6d (diff)
smol strings
-rw-r--r--src/lib.rs1
-rw-r--r--src/smol_str.rs60
-rw-r--r--src/yellow/green.rs7
3 files changed, 65 insertions, 3 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 0ae8082f1..91b0c9c55 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -35,6 +35,7 @@ mod grammar;
35mod parser_impl; 35mod parser_impl;
36 36
37mod syntax_kinds; 37mod syntax_kinds;
38mod smol_str;
38mod yellow; 39mod yellow;
39/// Utilities for simple uses of the parser. 40/// Utilities for simple uses of the parser.
40pub mod utils; 41pub mod utils;
diff --git a/src/smol_str.rs b/src/smol_str.rs
new file mode 100644
index 000000000..2a330c343
--- /dev/null
+++ b/src/smol_str.rs
@@ -0,0 +1,60 @@
1use std::{sync::Arc};
2
3const INLINE_CAP: usize = 22;
4
5#[derive(Clone, Debug)]
6pub(crate) enum SmolStr {
7 Heap(Arc<str>),
8 Inline {
9 len: u8,
10 buf: [u8; INLINE_CAP],
11 },
12}
13
14impl SmolStr {
15 pub fn new(text: &str) -> SmolStr {
16 let len = text.len();
17 if len <= INLINE_CAP {
18 let mut buf = [0; INLINE_CAP];
19 buf[..len].copy_from_slice(text.as_bytes());
20 SmolStr::Inline { len: len as u8, buf }
21 } else {
22 SmolStr::Heap(
23 text.to_string().into_boxed_str().into()
24 )
25 }
26 }
27
28 pub fn as_str(&self) -> &str {
29 match self {
30 SmolStr::Heap(data) => &*data,
31 SmolStr::Inline { len, buf } => {
32 let len = *len as usize;
33 let buf = &buf[..len];
34 unsafe { ::std::str::from_utf8_unchecked(buf) }
35 }
36 }
37 }
38}
39
40#[cfg(test)]
41mod tests {
42 use super::*;
43
44 #[test]
45 #[cfg(target_pointer_width = "64")]
46 fn smol_str_is_smol() {
47 assert_eq!(::std::mem::size_of::<SmolStr>(), 8 + 8 + 8)
48 }
49
50 #[test]
51 fn test_round_trip() {
52 let mut text = String::new();
53 for n in 0..256 {
54 let smol = SmolStr::new(&text);
55 assert_eq!(smol.as_str(), text.as_str());
56 text.push_str(&n.to_string());
57 }
58 }
59}
60
diff --git a/src/yellow/green.rs b/src/yellow/green.rs
index 3ade46f45..26df76af6 100644
--- a/src/yellow/green.rs
+++ b/src/yellow/green.rs
@@ -1,5 +1,6 @@
1use std::sync::Arc; 1use std::sync::Arc;
2use { 2use {
3 smol_str::SmolStr,
3 SyntaxKind::{self, *}, 4 SyntaxKind::{self, *},
4 TextUnit, 5 TextUnit,
5}; 6};
@@ -116,7 +117,7 @@ pub(crate) enum GreenLeaf {
116 }, 117 },
117 Token { 118 Token {
118 kind: SyntaxKind, 119 kind: SyntaxKind,
119 text: Option<Arc<str>>, 120 text: Option<SmolStr>,
120 }, 121 },
121} 122}
122 123
@@ -137,7 +138,7 @@ impl GreenLeaf {
137 debug_assert_eq!(t, text); 138 debug_assert_eq!(t, text);
138 None 139 None
139 } 140 }
140 None => Some(text.to_owned().into_boxed_str().into()), 141 None => Some(SmolStr::new(text)),
141 }; 142 };
142 GreenLeaf::Token { kind, text } 143 GreenLeaf::Token { kind, text }
143 } 144 }
@@ -159,7 +160,7 @@ impl GreenLeaf {
159 } 160 }
160 GreenLeaf::Token { kind, text } => match text { 161 GreenLeaf::Token { kind, text } => match text {
161 None => kind.static_text().unwrap(), 162 None => kind.static_text().unwrap(),
162 Some(t) => t, 163 Some(t) => t.as_str(),
163 }, 164 },
164 } 165 }
165 } 166 }