use crate::collections::str::lossy;
use crate::collections::vec::Vec;
use crate::Bump;
use core::borrow::{Borrow, BorrowMut};
use core::char::decode_utf16;
use core::fmt;
use core::hash;
use core::iter::FusedIterator;
use core::mem;
use core::ops::Bound::{Excluded, Included, Unbounded};
use core::ops::{self, Add, AddAssign, Index, IndexMut, RangeBounds};
use core::ptr;
use core::str::{self, Chars, Utf8Error};
use core_alloc::borrow::Cow;
#[macro_export]
macro_rules! format {
( in $bump:expr, $fmt:expr, $($args:expr),* ) => {{
use $crate::core_alloc::fmt::Write;
let bump = $bump;
let mut s = $crate::collections::String::new_in(bump);
let _ = write!(&mut s, $fmt, $($args),*);
s
}};
( in $bump:expr, $fmt:expr, $($args:expr,)* ) => {
$crate::format!(in $bump, $fmt, $($args),*)
};
}
#[derive(PartialOrd, Eq, Ord)]
pub struct String<'bump> {
vec: Vec<'bump, u8>,
}
#[derive(Debug)]
pub struct FromUtf8Error<'bump> {
bytes: Vec<'bump, u8>,
error: Utf8Error,
}
#[derive(Debug)]
pub struct FromUtf16Error(());
impl<'bump> String<'bump> {
#[inline]
pub fn new_in(bump: &'bump Bump) -> String<'bump> {
String {
vec: Vec::new_in(bump),
}
}
#[inline]
pub fn with_capacity_in(capacity: usize, bump: &'bump Bump) -> String<'bump> {
String {
vec: Vec::with_capacity_in(capacity, bump),
}
}
#[inline]
pub fn from_utf8(vec: Vec<'bump, u8>) -> Result<String<'bump>, FromUtf8Error<'bump>> {
match str::from_utf8(&vec) {
Ok(..) => Ok(String { vec }),
Err(e) => Err(FromUtf8Error {
bytes: vec,
error: e,
}),
}
}
pub fn from_utf8_lossy_in(v: &[u8], bump: &'bump Bump) -> String<'bump> {
let mut iter = lossy::Utf8Lossy::from_bytes(v).chunks();
let (first_valid, first_broken) = if let Some(chunk) = iter.next() {
let lossy::Utf8LossyChunk { valid, broken } = chunk;
if valid.len() == v.len() {
debug_assert!(broken.is_empty());
unsafe {
return String::from_utf8_unchecked(Vec::from_iter_in(v.iter().cloned(), bump));
}
}
(valid, broken)
} else {
return String::from_str_in("", bump);
};
const REPLACEMENT: &str = "\u{FFFD}";
let mut res = String::with_capacity_in(v.len(), bump);
res.push_str(first_valid);
if !first_broken.is_empty() {
res.push_str(REPLACEMENT);
}
for lossy::Utf8LossyChunk { valid, broken } in iter {
res.push_str(valid);
if !broken.is_empty() {
res.push_str(REPLACEMENT);
}
}
res
}
pub fn from_utf16_in(v: &[u16], bump: &'bump Bump) -> Result<String<'bump>, FromUtf16Error> {
let mut ret = String::with_capacity_in(v.len(), bump);
for c in decode_utf16(v.iter().cloned()) {
if let Ok(c) = c {
ret.push(c);
} else {
return Err(FromUtf16Error(()));
}
}
Ok(ret)
}
#[inline]
pub fn from_str_in(s: &str, bump: &'bump Bump) -> String<'bump> {
let len = s.len();
let mut t = String::with_capacity_in(len, bump);
unsafe { ptr::copy_nonoverlapping(s.as_ptr(), t.vec.as_mut_ptr(), len) };
unsafe { t.vec.set_len(len) };
t
}
pub fn from_iter_in<I: IntoIterator<Item = char>>(iter: I, bump: &'bump Bump) -> String<'bump> {
let mut s = String::new_in(bump);
for c in iter {
s.push(c);
}
s
}
#[inline]
pub unsafe fn from_raw_parts_in(
buf: *mut u8,
length: usize,
capacity: usize,
bump: &'bump Bump,
) -> String<'bump> {
String {
vec: Vec::from_raw_parts_in(buf, length, capacity, bump),
}
}
#[inline]
pub unsafe fn from_utf8_unchecked(bytes: Vec<'bump, u8>) -> String<'bump> {
String { vec: bytes }
}
#[inline]
#[must_use]
pub fn bump(&self) -> &'bump Bump {
self.vec.bump()
}
#[inline]
pub fn into_bytes(self) -> Vec<'bump, u8> {
self.vec
}
pub fn into_bump_str(self) -> &'bump str {
let s = unsafe {
let s = self.as_str();
mem::transmute(s)
};
mem::forget(self);
s
}
#[inline]
pub fn as_str(&self) -> &str {
self
}
#[inline]
pub fn as_mut_str(&mut self) -> &mut str {
self
}
#[inline]
pub fn push_str(&mut self, string: &str) {
self.vec.extend_from_slice_copy(string.as_bytes())
}
#[inline]
pub fn capacity(&self) -> usize {
self.vec.capacity()
}
#[inline]
pub fn reserve(&mut self, additional: usize) {
self.vec.reserve(additional)
}
#[inline]
pub fn reserve_exact(&mut self, additional: usize) {
self.vec.reserve_exact(additional)
}
#[inline]
pub fn shrink_to_fit(&mut self) {
self.vec.shrink_to_fit()
}
#[inline]
pub fn push(&mut self, ch: char) {
match ch.len_utf8() {
1 => self.vec.push(ch as u8),
_ => self
.vec
.extend_from_slice(ch.encode_utf8(&mut [0; 4]).as_bytes()),
}
}
#[inline]
pub fn as_bytes(&self) -> &[u8] {
&self.vec
}
#[inline]
pub fn truncate(&mut self, new_len: usize) {
if new_len <= self.len() {
assert!(self.is_char_boundary(new_len));
self.vec.truncate(new_len)
}
}
#[inline]
pub fn pop(&mut self) -> Option<char> {
let ch = self.chars().rev().next()?;
let newlen = self.len() - ch.len_utf8();
unsafe {
self.vec.set_len(newlen);
}
Some(ch)
}
#[inline]
pub fn remove(&mut self, idx: usize) -> char {
let ch = match self[idx..].chars().next() {
Some(ch) => ch,
None => panic!("cannot remove a char from the end of a string"),
};
let next = idx + ch.len_utf8();
let len = self.len();
unsafe {
ptr::copy(
self.vec.as_ptr().add(next),
self.vec.as_mut_ptr().add(idx),
len - next,
);
self.vec.set_len(len - (next - idx));
}
ch
}
#[inline]
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(char) -> bool,
{
struct SetLenOnDrop<'a, 'bump> {
s: &'a mut String<'bump>,
idx: usize,
del_bytes: usize,
}
impl<'a, 'bump> Drop for SetLenOnDrop<'a, 'bump> {
fn drop(&mut self) {
let new_len = self.idx - self.del_bytes;
debug_assert!(new_len <= self.s.len());
unsafe { self.s.vec.set_len(new_len) };
}
}
let len = self.len();
let mut guard = SetLenOnDrop {
s: self,
idx: 0,
del_bytes: 0,
};
while guard.idx < len {
let ch =
unsafe { guard.s.get_unchecked(guard.idx..len).chars().next().unwrap_unchecked() };
let ch_len = ch.len_utf8();
if !f(ch) {
guard.del_bytes += ch_len;
} else if guard.del_bytes > 0 {
ch.encode_utf8(unsafe {
core::slice::from_raw_parts_mut(
guard.s.as_mut_ptr().add(guard.idx - guard.del_bytes),
ch.len_utf8(),
)
});
}
guard.idx += ch_len;
}
drop(guard);
}
#[inline]
pub fn insert(&mut self, idx: usize, ch: char) {
assert!(self.is_char_boundary(idx));
let mut bits = [0; 4];
let bits = ch.encode_utf8(&mut bits).as_bytes();
unsafe {
self.insert_bytes(idx, bits);
}
}
unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) {
let len = self.len();
let amt = bytes.len();
self.vec.reserve(amt);
ptr::copy(
self.vec.as_ptr().add(idx),
self.vec.as_mut_ptr().add(idx + amt),
len - idx,
);
ptr::copy(bytes.as_ptr(), self.vec.as_mut_ptr().add(idx), amt);
self.vec.set_len(len + amt);
}
#[inline]
pub fn insert_str(&mut self, idx: usize, string: &str) {
assert!(self.is_char_boundary(idx));
unsafe {
self.insert_bytes(idx, string.as_bytes());
}
}
#[inline]
pub unsafe fn as_mut_vec(&mut self) -> &mut Vec<'bump, u8> {
&mut self.vec
}
#[inline]
pub fn len(&self) -> usize {
self.vec.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn split_off(&mut self, at: usize) -> String<'bump> {
assert!(self.is_char_boundary(at));
let other = self.vec.split_off(at);
unsafe { String::from_utf8_unchecked(other) }
}
#[inline]
pub fn clear(&mut self) {
self.vec.clear()
}
pub fn drain<'a, R>(&'a mut self, range: R) -> Drain<'a, 'bump>
where
R: RangeBounds<usize>,
{
let len = self.len();
let start = match range.start_bound() {
Included(&n) => n,
Excluded(&n) => n + 1,
Unbounded => 0,
};
let end = match range.end_bound() {
Included(&n) => n + 1,
Excluded(&n) => n,
Unbounded => len,
};
let self_ptr = self as *mut _;
let chars_iter = self[start..end].chars();
Drain {
start,
end,
iter: chars_iter,
string: self_ptr,
}
}
pub fn replace_range<R>(&mut self, range: R, replace_with: &str)
where
R: RangeBounds<usize>,
{
match range.start_bound() {
Included(&n) => assert!(self.is_char_boundary(n)),
Excluded(&n) => assert!(self.is_char_boundary(n + 1)),
Unbounded => {}
};
match range.end_bound() {
Included(&n) => assert!(self.is_char_boundary(n + 1)),
Excluded(&n) => assert!(self.is_char_boundary(n)),
Unbounded => {}
};
unsafe { self.as_mut_vec() }.splice(range, replace_with.bytes());
}
}
impl<'bump> FromUtf8Error<'bump> {
pub fn as_bytes(&self) -> &[u8] {
&self.bytes[..]
}
pub fn into_bytes(self) -> Vec<'bump, u8> {
self.bytes
}
pub fn utf8_error(&self) -> Utf8Error {
self.error
}
}
impl<'bump> fmt::Display for FromUtf8Error<'bump> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.error, f)
}
}
impl fmt::Display for FromUtf16Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt("invalid utf-16: lone surrogate found", f)
}
}
impl<'bump> Clone for String<'bump> {
fn clone(&self) -> Self {
String {
vec: self.vec.clone(),
}
}
fn clone_from(&mut self, source: &Self) {
self.vec.clone_from(&source.vec);
}
}
impl<'bump> Extend<char> for String<'bump> {
fn extend<I: IntoIterator<Item = char>>(&mut self, iter: I) {
let iterator = iter.into_iter();
let (lower_bound, _) = iterator.size_hint();
self.reserve(lower_bound);
for ch in iterator {
self.push(ch)
}
}
}
impl<'a, 'bump> Extend<&'a char> for String<'bump> {
fn extend<I: IntoIterator<Item = &'a char>>(&mut self, iter: I) {
self.extend(iter.into_iter().cloned());
}
}
impl<'a, 'bump> Extend<&'a str> for String<'bump> {
fn extend<I: IntoIterator<Item = &'a str>>(&mut self, iter: I) {
for s in iter {
self.push_str(s)
}
}
}
impl<'bump> Extend<String<'bump>> for String<'bump> {
fn extend<I: IntoIterator<Item = String<'bump>>>(&mut self, iter: I) {
for s in iter {
self.push_str(&s)
}
}
}
impl<'bump> Extend<core_alloc::string::String> for String<'bump> {
fn extend<I: IntoIterator<Item = core_alloc::string::String>>(&mut self, iter: I) {
for s in iter {
self.push_str(&s)
}
}
}
impl<'a, 'bump> Extend<Cow<'a, str>> for String<'bump> {
fn extend<I: IntoIterator<Item = Cow<'a, str>>>(&mut self, iter: I) {
for s in iter {
self.push_str(&s)
}
}
}
impl<'bump> PartialEq for String<'bump> {
#[inline]
fn eq(&self, other: &String) -> bool {
PartialEq::eq(&self[..], &other[..])
}
}
macro_rules! impl_eq {
($lhs:ty, $rhs: ty) => {
impl<'a, 'bump> PartialEq<$rhs> for $lhs {
#[inline]
fn eq(&self, other: &$rhs) -> bool {
PartialEq::eq(&self[..], &other[..])
}
}
impl<'a, 'b, 'bump> PartialEq<$lhs> for $rhs {
#[inline]
fn eq(&self, other: &$lhs) -> bool {
PartialEq::eq(&self[..], &other[..])
}
}
};
}
impl_eq! { String<'bump>, str }
impl_eq! { String<'bump>, &'a str }
impl_eq! { Cow<'a, str>, String<'bump> }
impl_eq! { core_alloc::string::String, String<'bump> }
impl<'bump> fmt::Display for String<'bump> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&**self, f)
}
}
impl<'bump> fmt::Debug for String<'bump> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<'bump> hash::Hash for String<'bump> {
#[inline]
fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
(**self).hash(hasher)
}
}
impl<'a, 'bump> Add<&'a str> for String<'bump> {
type Output = String<'bump>;
#[inline]
fn add(mut self, other: &str) -> String<'bump> {
self.push_str(other);
self
}
}
impl<'a, 'bump> AddAssign<&'a str> for String<'bump> {
#[inline]
fn add_assign(&mut self, other: &str) {
self.push_str(other);
}
}
impl<'bump> ops::Index<ops::Range<usize>> for String<'bump> {
type Output = str;
#[inline]
fn index(&self, index: ops::Range<usize>) -> &str {
&self[..][index]
}
}
impl<'bump> ops::Index<ops::RangeTo<usize>> for String<'bump> {
type Output = str;
#[inline]
fn index(&self, index: ops::RangeTo<usize>) -> &str {
&self[..][index]
}
}
impl<'bump> ops::Index<ops::RangeFrom<usize>> for String<'bump> {
type Output = str;
#[inline]
fn index(&self, index: ops::RangeFrom<usize>) -> &str {
&self[..][index]
}
}
impl<'bump> ops::Index<ops::RangeFull> for String<'bump> {
type Output = str;
#[inline]
fn index(&self, _index: ops::RangeFull) -> &str {
unsafe { str::from_utf8_unchecked(&self.vec) }
}
}
impl<'bump> ops::Index<ops::RangeInclusive<usize>> for String<'bump> {
type Output = str;
#[inline]
fn index(&self, index: ops::RangeInclusive<usize>) -> &str {
Index::index(&**self, index)
}
}
impl<'bump> ops::Index<ops::RangeToInclusive<usize>> for String<'bump> {
type Output = str;
#[inline]
fn index(&self, index: ops::RangeToInclusive<usize>) -> &str {
Index::index(&**self, index)
}
}
impl<'bump> ops::IndexMut<ops::Range<usize>> for String<'bump> {
#[inline]
fn index_mut(&mut self, index: ops::Range<usize>) -> &mut str {
&mut self[..][index]
}
}
impl<'bump> ops::IndexMut<ops::RangeTo<usize>> for String<'bump> {
#[inline]
fn index_mut(&mut self, index: ops::RangeTo<usize>) -> &mut str {
&mut self[..][index]
}
}
impl<'bump> ops::IndexMut<ops::RangeFrom<usize>> for String<'bump> {
#[inline]
fn index_mut(&mut self, index: ops::RangeFrom<usize>) -> &mut str {
&mut self[..][index]
}
}
impl<'bump> ops::IndexMut<ops::RangeFull> for String<'bump> {
#[inline]
fn index_mut(&mut self, _index: ops::RangeFull) -> &mut str {
unsafe { str::from_utf8_unchecked_mut(&mut *self.vec) }
}
}
impl<'bump> ops::IndexMut<ops::RangeInclusive<usize>> for String<'bump> {
#[inline]
fn index_mut(&mut self, index: ops::RangeInclusive<usize>) -> &mut str {
IndexMut::index_mut(&mut **self, index)
}
}
impl<'bump> ops::IndexMut<ops::RangeToInclusive<usize>> for String<'bump> {
#[inline]
fn index_mut(&mut self, index: ops::RangeToInclusive<usize>) -> &mut str {
IndexMut::index_mut(&mut **self, index)
}
}
impl<'bump> ops::Deref for String<'bump> {
type Target = str;
#[inline]
fn deref(&self) -> &str {
unsafe { str::from_utf8_unchecked(&self.vec) }
}
}
impl<'bump> ops::DerefMut for String<'bump> {
#[inline]
fn deref_mut(&mut self) -> &mut str {
unsafe { str::from_utf8_unchecked_mut(&mut *self.vec) }
}
}
impl<'bump> AsRef<str> for String<'bump> {
#[inline]
fn as_ref(&self) -> &str {
self
}
}
impl<'bump> AsRef<[u8]> for String<'bump> {
#[inline]
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
impl<'bump> fmt::Write for String<'bump> {
#[inline]
fn write_str(&mut self, s: &str) -> fmt::Result {
self.push_str(s);
Ok(())
}
#[inline]
fn write_char(&mut self, c: char) -> fmt::Result {
self.push(c);
Ok(())
}
}
impl<'bump> Borrow<str> for String<'bump> {
#[inline]
fn borrow(&self) -> &str {
&self[..]
}
}
impl<'bump> BorrowMut<str> for String<'bump> {
#[inline]
fn borrow_mut(&mut self) -> &mut str {
&mut self[..]
}
}
pub struct Drain<'a, 'bump> {
string: *mut String<'bump>,
start: usize,
end: usize,
iter: Chars<'a>,
}
impl<'a, 'bump> fmt::Debug for Drain<'a, 'bump> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("Drain { .. }")
}
}
unsafe impl<'a, 'bump> Sync for Drain<'a, 'bump> {}
unsafe impl<'a, 'bump> Send for Drain<'a, 'bump> {}
impl<'a, 'bump> Drop for Drain<'a, 'bump> {
fn drop(&mut self) {
unsafe {
let self_vec = (*self.string).as_mut_vec();
if self.start <= self.end && self.end <= self_vec.len() {
self_vec.drain(self.start..self.end);
}
}
}
}
impl<'a, 'bump> Iterator for Drain<'a, 'bump> {
type Item = char;
#[inline]
fn next(&mut self) -> Option<char> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a, 'bump> DoubleEndedIterator for Drain<'a, 'bump> {
#[inline]
fn next_back(&mut self) -> Option<char> {
self.iter.next_back()
}
}
impl<'a, 'bump> FusedIterator for Drain<'a, 'bump> {}
#[cfg(feature = "serde")]
mod serialize {
use super::*;
use serde::{Serialize, Serializer};
impl<'bump> Serialize for String<'bump> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self)
}
}
}