use core::{fmt, str, convert, str::Utf8Error};
use core::clone::Clone;
use core::iter::{FromIterator, IntoIterator, Extend};
use core::ops::{self, Index, Add, AddAssign};
use core::borrow::Borrow;
use alloc::{string::String, vec::Vec};
use alloc::borrow::Cow;
use crate::ibytes::IBytes;
use crate::FromUtf8Error;
#[derive(Clone)]
#[cfg_attr(feature="size", derive(datasize::DataSize))]
pub struct IString {
pub (crate) bytes: IBytes,
}
impl IString {
#[inline]
pub fn new() -> IString {
IString {
bytes: IBytes::new()
}
}
#[inline]
pub fn with_capacity(capacity: usize) -> IString {
IString {
bytes: IBytes::with_capacity(capacity)
}
}
#[inline(always)]
pub unsafe fn set_len(&mut self, new_len: usize) {
self.bytes.set_len(new_len);
}
#[inline(always)]
pub fn capacity(&self) -> usize {
self.bytes.capacity()
}
#[inline(always)]
pub fn move_to_heap(&mut self, cap: usize) {
self.bytes.move_to_heap(cap);
}
#[inline(always)]
pub fn shrink(&mut self) {
self.bytes.shrink();
}
#[inline]
pub fn push_str(&mut self, s: &str) {
self.bytes.extend_from_slice(s.as_bytes());
}
#[inline(always)]
pub unsafe fn from_raw_parts(buf: *mut u8, length: usize, capacity: usize) -> IString {
String::from_raw_parts(buf, length, capacity).into()
}
#[inline]
pub fn reserve(&mut self, additional: usize) {
self.bytes.reserve(additional);
}
#[inline]
pub fn reserve_exact(&mut self, additional: usize) {
self.bytes.reserve_exact(additional);
}
#[inline]
pub fn push(&mut self, ch: char) {
let mut buf = [0; 4];
self.push_str(ch.encode_utf8(&mut buf));
}
#[inline]
pub fn truncate(&mut self, new_len: usize) {
if new_len < self.len() {
unsafe { self.set_len(new_len) }
}
}
pub fn from_utf8(bytes: IBytes) -> Result<IString, FromUtf8Error<IBytes>> {
match str::from_utf8(bytes.as_slice()) {
Ok(_) => Ok(IString { bytes }),
Err(error) => Err(FromUtf8Error {
bytes,
error
})
}
}
}
impl<'a> convert::From<&'a str> for IString {
#[inline]
fn from(s: &'a str) -> IString {
let mut istring = IString::with_capacity(s.len());
istring.push_str(s);
istring
}
}
impl convert::From<String> for IString {
#[inline]
fn from(s: String) -> IString {
IString {
bytes: IBytes::from(s.into_bytes())
}
}
}
impl<'a> convert::From<Cow<'a, str>> for IString {
#[inline]
fn from(s: Cow<'a, str>) -> IString {
match s {
Cow::Borrowed(s) => IString::from(s),
Cow::Owned(s) => IString::from(s)
}
}
}
impl convert::Into<String> for IString {
#[inline]
fn into(self) -> String {
unsafe {
String::from_utf8_unchecked(self.bytes.into())
}
}
}
impl fmt::Write for IString {
#[inline(always)]
fn write_str(&mut self, s: &str) -> fmt::Result {
self.push_str(s);
Ok(())
}
}
impl Extend<char> for IString {
#[inline]
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> Extend<&'a char> for IString {
#[inline(always)]
fn extend<I: IntoIterator<Item = &'a char>>(&mut self, iter: I) {
self.extend(iter.into_iter().cloned());
}
}
impl<'a> Extend<&'a str> for IString {
#[inline(always)]
fn extend<I: IntoIterator<Item = &'a str>>(&mut self, iter: I) {
for s in iter {
self.push_str(s)
}
}
}
impl<'a> Extend<Cow<'a, str>> for IString {
#[inline(always)]
fn extend<I: IntoIterator<Item = Cow<'a, str>>>(&mut self, iter: I) {
for s in iter {
self.push_str(&s)
}
}
}
impl Default for IString {
#[inline(always)]
fn default() -> IString {
IString::new()
}
}
impl<'a> Add<&'a str> for IString {
type Output = IString;
#[inline(always)]
fn add(mut self, other: &str) -> IString {
self.push_str(other);
self
}
}
impl<'a> AddAssign<&'a str> for IString {
#[inline]
fn add_assign(&mut self, other: &str) {
self.push_str(other);
}
}
impl FromIterator<char> for IString {
fn from_iter<T>(iter: T) -> Self where T: IntoIterator<Item=char> {
let mut s = IString::new();
s.extend(iter);
s
}
}
impl<'a> FromIterator<&'a str> for IString {
fn from_iter<T>(iter: T) -> Self where T: IntoIterator<Item=&'a str> {
let mut s = IString::new();
s.extend(iter);
s
}
}
define_common_string!(IString, IStringUnion);