smol strings

This commit is contained in:
Aleksey Kladov 2018-08-08 20:25:35 +03:00
parent cc4c90aa2c
commit 1fa5b2ffbc
3 changed files with 65 additions and 3 deletions

View file

@ -35,6 +35,7 @@ mod grammar;
mod parser_impl;
mod syntax_kinds;
mod smol_str;
mod yellow;
/// Utilities for simple uses of the parser.
pub mod utils;

60
src/smol_str.rs Normal file
View file

@ -0,0 +1,60 @@
use std::{sync::Arc};
const INLINE_CAP: usize = 22;
#[derive(Clone, Debug)]
pub(crate) enum SmolStr {
Heap(Arc<str>),
Inline {
len: u8,
buf: [u8; INLINE_CAP],
},
}
impl SmolStr {
pub fn new(text: &str) -> SmolStr {
let len = text.len();
if len <= INLINE_CAP {
let mut buf = [0; INLINE_CAP];
buf[..len].copy_from_slice(text.as_bytes());
SmolStr::Inline { len: len as u8, buf }
} else {
SmolStr::Heap(
text.to_string().into_boxed_str().into()
)
}
}
pub fn as_str(&self) -> &str {
match self {
SmolStr::Heap(data) => &*data,
SmolStr::Inline { len, buf } => {
let len = *len as usize;
let buf = &buf[..len];
unsafe { ::std::str::from_utf8_unchecked(buf) }
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[cfg(target_pointer_width = "64")]
fn smol_str_is_smol() {
assert_eq!(::std::mem::size_of::<SmolStr>(), 8 + 8 + 8)
}
#[test]
fn test_round_trip() {
let mut text = String::new();
for n in 0..256 {
let smol = SmolStr::new(&text);
assert_eq!(smol.as_str(), text.as_str());
text.push_str(&n.to_string());
}
}
}

View file

@ -1,5 +1,6 @@
use std::sync::Arc;
use {
smol_str::SmolStr,
SyntaxKind::{self, *},
TextUnit,
};
@ -116,7 +117,7 @@ pub(crate) enum GreenLeaf {
},
Token {
kind: SyntaxKind,
text: Option<Arc<str>>,
text: Option<SmolStr>,
},
}
@ -137,7 +138,7 @@ impl GreenLeaf {
debug_assert_eq!(t, text);
None
}
None => Some(text.to_owned().into_boxed_str().into()),
None => Some(SmolStr::new(text)),
};
GreenLeaf::Token { kind, text }
}
@ -159,7 +160,7 @@ impl GreenLeaf {
}
GreenLeaf::Token { kind, text } => match text {
None => kind.static_text().unwrap(),
Some(t) => t,
Some(t) => t.as_str(),
},
}
}