use std::borrow::Borrow;
use std::ops::Deref;
use std::ptr;
use std::str;
use smallvec::SmallVec;
#[derive(Clone, Default)]
pub struct SmallString {
buffer: SmallVec<[u8; 8]>,
}
impl SmallString {
#[inline(always)]
pub fn new() -> Self {
SmallString {
buffer: SmallVec::new(),
}
}
#[inline(always)]
pub fn with_capacity(capacity: usize) -> Self {
SmallString {
buffer: SmallVec::with_capacity(capacity),
}
}
pub fn from_str(text: &str) -> Self {
let mut string = SmallString::with_capacity(text.len());
unsafe { string.insert_bytes(0, text.as_bytes()) };
string
}
pub fn push_str(&mut self, string: &str) {
let len = self.len();
unsafe {
self.insert_bytes(len, string.as_bytes());
}
}
pub fn truncate(&mut self, idx: usize) {
assert!(self.is_char_boundary(idx));
debug_assert!(idx <= self.len());
self.buffer.truncate(idx);
}
pub fn clear(&mut self) {
self.truncate(0);
}
#[inline(always)]
unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) {
assert!(idx <= self.len());
let len = self.len();
let amt = bytes.len();
self.buffer.reserve(amt);
ptr::copy(
self.buffer.as_ptr().add(idx),
self.buffer.as_mut_ptr().add(idx + amt),
len - idx,
);
ptr::copy(bytes.as_ptr(), self.buffer.as_mut_ptr().add(idx), amt);
self.buffer.set_len(len + amt);
}
}
impl std::cmp::PartialEq for SmallString {
fn eq(&self, other: &Self) -> bool {
let (s1, s2): (&str, &str) = (self, other);
s1 == s2
}
}
impl<'a> PartialEq<SmallString> for &'a str {
fn eq(&self, other: &SmallString) -> bool {
*self == (other as &str)
}
}
impl<'a> PartialEq<&'a str> for SmallString {
fn eq(&self, other: &&'a str) -> bool {
(self as &str) == *other
}
}
impl std::fmt::Display for SmallString {
fn fmt(&self, fm: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
SmallString::deref(self).fmt(fm)
}
}
impl std::fmt::Debug for SmallString {
fn fmt(&self, fm: &mut std::fmt::Formatter) -> std::fmt::Result {
SmallString::deref(self).fmt(fm)
}
}
impl<'a> From<&'a str> for SmallString {
fn from(s: &str) -> Self {
Self::from_str(s)
}
}
impl Deref for SmallString {
type Target = str;
fn deref(&self) -> &str {
unsafe { str::from_utf8_unchecked(self.buffer.as_ref()) }
}
}
impl AsRef<str> for SmallString {
fn as_ref(&self) -> &str {
unsafe { str::from_utf8_unchecked(self.buffer.as_ref()) }
}
}
impl Borrow<str> for SmallString {
fn borrow(&self) -> &str {
unsafe { str::from_utf8_unchecked(self.buffer.as_ref()) }
}
}