#![allow(
clippy::missing_errors_doc,
clippy::missing_panics_doc,
clippy::undocumented_unsafe_blocks,
reason = "internal docs mirror std-style APIs; unsafe code follows the documented `data`/`len`/`cap` invariants"
)]
use core::borrow::{Borrow, BorrowMut};
use core::cmp::Ordering;
use core::fmt::{self, Debug, Display, Formatter};
use core::hash::{Hash, Hasher};
use core::ops::{Bound, Deref, DerefMut, RangeBounds};
use allocator_api2::alloc::{AllocError, Allocator, Global};
use widestring::Utf16Str;
use crate::strings::string_common::impl_arena_string_common;
use crate::strings::{ArcUtf16Str, BoxUtf16Str};
use crate::vec::{FromIteratorIn, Vec};
use crate::{Arena, FromIn};
pub struct Utf16String<'a, A: Allocator + Clone = Global> {
pub(super) inner: Vec<'a, u16, A>,
}
impl<'a, A: Allocator + Clone> Utf16String<'a, A> {
#[must_use]
pub fn as_utf16_str(&self) -> &Utf16Str {
unsafe { Utf16Str::from_slice_unchecked(self.inner.as_slice()) }
}
#[must_use]
#[inline]
pub fn as_slice(&self) -> &[u16] {
self.inner.as_slice()
}
#[inline]
pub fn as_mut_utf16_str(&mut self) -> &mut Utf16Str {
unsafe { Utf16Str::from_slice_unchecked_mut(self.inner.as_mut_slice()) }
}
#[must_use]
pub fn from_utf16_str_in(s: &Utf16Str, arena: &'a Arena<A>) -> Self {
crate::arena::ExpectAlloc::expect_alloc(Self::try_from_utf16_str_in(s, arena))
}
pub fn try_from_utf16_str_in(s: &Utf16Str, arena: &'a Arena<A>) -> Result<Self, AllocError> {
let mut out = Self::try_with_capacity_in(s.len(), arena)?;
out.try_push_str(s)?;
Ok(out)
}
#[must_use]
pub(crate) fn from_str_in(s: &str, arena: &'a Arena<A>) -> Self {
let mut out = Self::with_capacity_in(s.len(), arena);
out.push_from_str(s);
out
}
pub fn pop(&mut self) -> Option<char> {
let ch = self.as_utf16_str().chars().next_back()?;
let new_len = self.len() - ch.len_utf16();
self.inner.truncate(new_len);
Some(ch)
}
pub fn truncate(&mut self, new_len: usize) {
if new_len >= self.len() {
return;
}
assert!(
self.as_utf16_str().is_char_boundary(new_len),
"Utf16String::truncate: new_len {new_len} is not on a UTF-16 char boundary"
);
self.inner.truncate(new_len);
}
#[inline]
pub fn push(&mut self, ch: char) {
let mut buf = [0u16; 2];
let units = ch.encode_utf16(&mut buf);
self.inner.extend_from_slice(&*units);
}
#[inline]
pub fn try_push(&mut self, ch: char) -> Result<(), AllocError> {
let mut buf = [0u16; 2];
let units = ch.encode_utf16(&mut buf);
self.inner.try_extend_from_slice(&*units)
}
#[inline]
pub fn push_str(&mut self, s: impl AsRef<Utf16Str>) {
self.inner.extend_from_slice(s.as_ref().as_slice());
}
#[inline(always)]
#[allow(
clippy::inline_always,
reason = "the hot path is bump-then-memcpy; the cold grow branch is `#[inline(never)]` so the inlinable body is small"
)]
pub fn try_push_str(&mut self, s: impl AsRef<Utf16Str>) -> Result<(), AllocError> {
self.inner.try_extend_from_slice(s.as_ref().as_slice())
}
#[inline]
pub fn push_from_str(&mut self, s: impl AsRef<str>) {
let s = s.as_ref();
self.inner.reserve(s.len());
for ch in s.chars() {
let mut buf = [0u16; 2];
let units = ch.encode_utf16(&mut buf);
self.inner.extend_from_slice(&*units);
}
}
pub fn try_push_from_str(&mut self, s: impl AsRef<str>) -> Result<(), AllocError> {
let s = s.as_ref();
self.inner.try_reserve(s.len())?;
for ch in s.chars() {
let mut buf = [0u16; 2];
let units = ch.encode_utf16(&mut buf);
self.inner.try_extend_from_slice(&*units)?;
}
Ok(())
}
pub fn insert(&mut self, idx: usize, ch: char) {
crate::arena::ExpectAlloc::expect_alloc(self.try_insert(idx, ch));
}
pub fn try_insert(&mut self, idx: usize, ch: char) -> Result<(), AllocError> {
let mut buf = [0u16; 2];
let units = ch.encode_utf16(&mut buf);
self.try_insert_units(idx, units)
}
pub fn insert_utf16_str(&mut self, idx: usize, s: &Utf16Str) {
crate::arena::ExpectAlloc::expect_alloc(self.try_insert_utf16_str(idx, s));
}
pub fn try_insert_utf16_str(&mut self, idx: usize, s: &Utf16Str) -> Result<(), AllocError> {
self.try_insert_units(idx, s.as_slice())
}
fn try_insert_units(&mut self, idx: usize, units: &[u16]) -> Result<(), AllocError> {
let len = self.inner.len();
assert!(
idx <= len,
"Utf16String::insert: insertion index out of bounds (was {idx}, len = {len})"
);
assert!(
self.as_utf16_str().is_char_boundary(idx),
"Utf16String::insert: idx {idx} is not on a UTF-16 char boundary"
);
let added = units.len();
if added == 0 {
return Ok(());
}
self.inner.try_reserve(added)?;
for &u in units {
self.inner.push(u);
}
let region = &mut self.inner.as_mut_slice()[idx..len + added];
region.rotate_right(added);
Ok(())
}
pub fn remove(&mut self, idx: usize) -> char {
let len = self.inner.len();
assert!(idx < len, "Utf16String::remove: idx {idx} out of bounds (len = {len})");
assert!(
self.as_utf16_str().is_char_boundary(idx),
"Utf16String::remove: idx {idx} is not on a UTF-16 char boundary"
);
let tail = &self.as_slice()[idx..];
let tail_str = unsafe { Utf16Str::from_slice_unchecked(tail) };
let ch = tail_str.chars().next().expect("remove: idx out of bounds");
let ch_len = ch.len_utf16();
let region = &mut self.inner.as_mut_slice()[idx..len];
region.rotate_left(ch_len);
self.inner.truncate(len - ch_len);
ch
}
pub fn retain<F: FnMut(char) -> bool>(&mut self, mut f: F) {
struct Guard<'g, 'a, A: Allocator + Clone> {
inner: &'g mut Vec<'a, u16, A>,
idx: usize,
del_units: usize,
}
impl<A: Allocator + Clone> Drop for Guard<'_, '_, A> {
fn drop(&mut self) {
self.inner.truncate(self.idx - self.del_units);
}
}
let len = self.inner.len();
let mut guard = Guard {
inner: &mut self.inner,
idx: 0,
del_units: 0,
};
while guard.idx < len {
let ch = unsafe { Utf16Str::from_slice_unchecked(&guard.inner.as_slice()[guard.idx..len]) }
.chars()
.next()
.expect("idx < len guarantees a remaining char");
let ch_len = ch.len_utf16();
if f(ch) {
let dst = guard.idx - guard.del_units;
guard.inner.as_mut_slice().copy_within(guard.idx..guard.idx + ch_len, dst);
} else {
guard.del_units += ch_len;
}
guard.idx += ch_len;
}
drop(guard);
}
pub fn replace_range<R: RangeBounds<usize>>(&mut self, range: R, replace_with: &Utf16Str) {
crate::arena::ExpectAlloc::expect_alloc(self.try_replace_range(range, replace_with));
}
pub fn try_replace_range<R: RangeBounds<usize>>(&mut self, range: R, replace_with: &Utf16Str) -> Result<(), AllocError> {
let len = self.len();
let start = match range.start_bound() {
Bound::Included(&i) => i,
Bound::Excluded(&i) => i.checked_add(1).expect("replace_range: start bound overflows usize"),
Bound::Unbounded => 0,
};
let end = match range.end_bound() {
Bound::Included(&i) => i.checked_add(1).expect("replace_range: end bound overflows usize"),
Bound::Excluded(&i) => i,
Bound::Unbounded => len,
};
assert!(start <= end, "Utf16String::replace_range: start > end");
assert!(end <= len, "Utf16String::replace_range: end > len");
let s_ref = self.as_utf16_str();
assert!(
s_ref.is_char_boundary(start),
"Utf16String::replace_range: start is not on a UTF-16 char boundary"
);
assert!(
s_ref.is_char_boundary(end),
"Utf16String::replace_range: end is not on a UTF-16 char boundary"
);
self.inner.try_replace_range_with_slice(start, end, replace_with.as_slice())
}
#[must_use]
pub fn into_vec(self) -> Vec<'a, u16, A> {
self.inner
}
#[must_use]
pub unsafe fn as_mut_vec(&mut self) -> &mut Vec<'a, u16, A> {
&mut self.inner
}
#[must_use]
pub fn split_off(&mut self, at: usize) -> Self {
crate::arena::ExpectAlloc::expect_alloc(self.try_split_off(at))
}
pub fn try_split_off(&mut self, at: usize) -> Result<Self, AllocError> {
assert!(
self.as_utf16_str().is_char_boundary(at),
"Utf16String::split_off: `at` is not a char boundary"
);
Ok(Self {
inner: self.inner.try_split_off(at)?,
})
}
pub fn extend_from_within<R: RangeBounds<usize>>(&mut self, src: R) {
crate::arena::ExpectAlloc::expect_alloc(self.try_extend_from_within(src));
}
pub fn try_extend_from_within<R: RangeBounds<usize>>(&mut self, src: R) -> Result<(), AllocError> {
let len = self.inner.len();
let start = match src.start_bound() {
Bound::Included(&i) => i,
Bound::Excluded(&i) => i.checked_add(1).expect("extend_from_within: start bound overflows usize"),
Bound::Unbounded => 0,
};
let end = match src.end_bound() {
Bound::Included(&i) => i.checked_add(1).expect("extend_from_within: end bound overflows usize"),
Bound::Excluded(&i) => i,
Bound::Unbounded => len,
};
assert!(start <= end, "extend_from_within: start > end");
assert!(end <= len, "extend_from_within: end > len");
let s_ref = self.as_utf16_str();
assert!(s_ref.is_char_boundary(start), "extend_from_within: start is not on a char boundary");
assert!(s_ref.is_char_boundary(end), "extend_from_within: end is not on a char boundary");
self.inner.try_extend_from_within(start..end)
}
#[must_use]
pub fn into_boxed_utf16_str(self) -> BoxUtf16Str<A> {
crate::arena::ExpectAlloc::expect_alloc(self.try_into_boxed_utf16_str())
}
pub fn try_into_boxed_utf16_str(self) -> Result<BoxUtf16Str<A>, AllocError> {
self.inner.arena().try_alloc_utf16_str_box(self.as_utf16_str())
}
#[must_use]
pub fn into_arc_utf16_str(self) -> ArcUtf16Str<A>
where
A: Send + Sync,
{
crate::arena::ExpectAlloc::expect_alloc(self.try_into_arc_utf16_str())
}
pub fn try_into_arc_utf16_str(self) -> Result<ArcUtf16Str<A>, AllocError>
where
A: Send + Sync,
{
self.inner.arena().try_alloc_utf16_str_arc(self.as_utf16_str())
}
pub fn drain<R: RangeBounds<usize>>(&mut self, range: R) -> Utf16Drain<'_, 'a, A> {
let len = self.inner.len();
let start = match range.start_bound() {
Bound::Included(&i) => i,
Bound::Excluded(&i) => i.checked_add(1).expect("drain: start bound overflows usize"),
Bound::Unbounded => 0,
};
let end = match range.end_bound() {
Bound::Included(&i) => i.checked_add(1).expect("drain: end bound overflows usize"),
Bound::Excluded(&i) => i,
Bound::Unbounded => len,
};
assert!(start <= end, "drain: start > end");
assert!(end <= len, "drain: end > len");
let s_ref = self.as_utf16_str();
assert!(s_ref.is_char_boundary(start), "drain: start is not on a char boundary");
assert!(s_ref.is_char_boundary(end), "drain: end is not on a char boundary");
Utf16Drain {
inner: self.inner.drain(start..end),
}
}
#[must_use]
pub fn leak(self) -> &'a mut Utf16Str {
let units = self.inner.leak();
unsafe { Utf16Str::from_slice_unchecked_mut(units) }
}
}
pub struct Utf16Drain<'d, 'a, A: Allocator + Clone> {
inner: crate::vec::Drain<'d, 'a, u16, A>,
}
impl<A: Allocator + Clone> fmt::Debug for Utf16Drain<'_, '_, A> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("Utf16Drain").finish_non_exhaustive()
}
}
impl<A: Allocator + Clone> Iterator for Utf16Drain<'_, '_, A> {
type Item = char;
fn next(&mut self) -> Option<char> {
let u0 = self.inner.next()?;
let decoded = if (0xD800..=0xDBFF).contains(&u0) {
let u1 = self.inner.next().expect("Utf16Drain holds valid UTF-16");
char::decode_utf16([u0, u1]).next()
} else {
char::decode_utf16([u0]).next()
};
Some(decoded.expect("non-empty").expect("Utf16Drain holds valid UTF-16"))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let units = self.inner.len();
(units.div_ceil(2), Some(units))
}
}
impl<A: Allocator + Clone> DoubleEndedIterator for Utf16Drain<'_, '_, A> {
fn next_back(&mut self) -> Option<char> {
let last = self.inner.next_back()?;
let decoded = if (0xDC00..=0xDFFF).contains(&last) {
let high = self.inner.next_back().expect("Utf16Drain holds valid UTF-16");
char::decode_utf16([high, last]).next()
} else {
char::decode_utf16([last]).next()
};
Some(decoded.expect("non-empty").expect("Utf16Drain holds valid UTF-16"))
}
}
impl<A: Allocator + Clone> core::iter::FusedIterator for Utf16Drain<'_, '_, A> {}
impl<'a, A: Allocator + Clone> From<Utf16String<'a, A>> for BoxUtf16Str<A> {
#[inline]
fn from(s: Utf16String<'a, A>) -> Self {
s.into_boxed_utf16_str()
}
}
impl<'a, A: Allocator + Clone + Send + Sync> From<Utf16String<'a, A>> for ArcUtf16Str<A> {
#[inline]
fn from(s: Utf16String<'a, A>) -> Self {
s.into_arc_utf16_str()
}
}
impl<A: Allocator + Clone> Deref for Utf16String<'_, A> {
type Target = Utf16Str;
#[inline]
fn deref(&self) -> &Utf16Str {
self.as_utf16_str()
}
}
impl<A: Allocator + Clone> DerefMut for Utf16String<'_, A> {
#[inline]
fn deref_mut(&mut self) -> &mut Utf16Str {
self.as_mut_utf16_str()
}
}
impl<A: Allocator + Clone> AsRef<Utf16Str> for Utf16String<'_, A> {
fn as_ref(&self) -> &Utf16Str {
self.as_utf16_str()
}
}
impl<A: Allocator + Clone> AsMut<Utf16Str> for Utf16String<'_, A> {
fn as_mut(&mut self) -> &mut Utf16Str {
self.as_mut_utf16_str()
}
}
impl<A: Allocator + Clone> Borrow<Utf16Str> for Utf16String<'_, A> {
fn borrow(&self) -> &Utf16Str {
self.as_utf16_str()
}
}
impl<A: Allocator + Clone> BorrowMut<Utf16Str> for Utf16String<'_, A> {
fn borrow_mut(&mut self) -> &mut Utf16Str {
self.as_mut_utf16_str()
}
}
impl<A: Allocator + Clone> Debug for Utf16String<'_, A> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Debug::fmt(self.as_utf16_str(), f)
}
}
impl<A: Allocator + Clone> Display for Utf16String<'_, A> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Display::fmt(self.as_utf16_str(), f)
}
}
impl<A: Allocator + Clone> PartialEq for Utf16String<'_, A> {
fn eq(&self, other: &Self) -> bool {
self.as_slice() == other.as_slice()
}
}
impl_arena_string_common!(Utf16String, u16);
impl<A: Allocator + Clone> Ord for Utf16String<'_, A> {
fn cmp(&self, other: &Self) -> Ordering {
self.as_slice().cmp(other.as_slice())
}
}
impl<A: Allocator + Clone> Hash for Utf16String<'_, A> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.as_utf16_str().hash(state);
}
}
impl<A: Allocator + Clone> PartialEq<Utf16Str> for Utf16String<'_, A> {
#[inline]
fn eq(&self, other: &Utf16Str) -> bool {
self.as_utf16_str() == other
}
}
impl<A: Allocator + Clone> PartialEq<Utf16String<'_, A>> for Utf16Str {
#[inline]
fn eq(&self, other: &Utf16String<'_, A>) -> bool {
self == other.as_utf16_str()
}
}
impl<A: Allocator + Clone> PartialEq<&Utf16Str> for Utf16String<'_, A> {
#[inline]
fn eq(&self, other: &&Utf16Str) -> bool {
self.as_utf16_str() == *other
}
}
impl<A: Allocator + Clone> PartialEq<Utf16String<'_, A>> for &Utf16Str {
#[inline]
fn eq(&self, other: &Utf16String<'_, A>) -> bool {
*self == other.as_utf16_str()
}
}
impl<A: Allocator + Clone> Clone for Utf16String<'_, A> {
fn clone(&self) -> Self {
Self::from_utf16_str_in(self.as_utf16_str(), self.inner.arena)
}
}
impl<A: Allocator + Clone> Extend<char> for Utf16String<'_, A> {
fn extend<I: IntoIterator<Item = char>>(&mut self, iter: I) {
let iter = iter.into_iter();
let (lo, _) = iter.size_hint();
self.reserve(lo);
for ch in iter {
self.push(ch);
}
}
}
impl<'a, A: Allocator + Clone> Extend<&'a Utf16Str> for Utf16String<'_, A> {
fn extend<I: IntoIterator<Item = &'a Utf16Str>>(&mut self, iter: I) {
for s in iter {
self.push_str(s);
}
}
}
impl<'a, A: Allocator + Clone> Extend<&'a str> for Utf16String<'_, A> {
fn extend<I: IntoIterator<Item = &'a str>>(&mut self, iter: I) {
for s in iter {
self.push_from_str(s);
}
}
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<A: Allocator + Clone> serde::ser::Serialize for Utf16String<'_, A> {
fn serialize<S: serde::ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.collect_str(self.as_utf16_str())
}
}
impl<A: Allocator + Clone> fmt::Write for Utf16String<'_, A> {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.push_from_str(s);
Ok(())
}
}
impl<'a, A: Allocator + Clone> FromIteratorIn<'a, char, A> for Utf16String<'a, A> {
fn from_iter_in<I: IntoIterator<Item = char>>(iter: I, arena: &'a Arena<A>) -> Self {
let mut s = Self::new_in(arena);
s.extend(iter);
s
}
}
impl<'a, 'b, A: Allocator + Clone> FromIteratorIn<'a, &'b Utf16Str, A> for Utf16String<'a, A> {
fn from_iter_in<I: IntoIterator<Item = &'b Utf16Str>>(iter: I, arena: &'a Arena<A>) -> Self {
let mut s = Self::new_in(arena);
s.extend(iter);
s
}
}
impl<'a, 'b, A: Allocator + Clone> FromIteratorIn<'a, &'b str, A> for Utf16String<'a, A> {
fn from_iter_in<I: IntoIterator<Item = &'b str>>(iter: I, arena: &'a Arena<A>) -> Self {
let mut s = Self::new_in(arena);
s.extend(iter);
s
}
}
impl<'a, 'b, A: Allocator + Clone> FromIteratorIn<'a, &'b char, A> for Utf16String<'a, A> {
fn from_iter_in<I: IntoIterator<Item = &'b char>>(iter: I, arena: &'a Arena<A>) -> Self {
let mut s = Self::new_in(arena);
s.extend(iter);
s
}
}
impl<'a, A: Allocator + Clone> FromIteratorIn<'a, alloc::string::String, A> for Utf16String<'a, A> {
fn from_iter_in<I: IntoIterator<Item = alloc::string::String>>(iter: I, arena: &'a Arena<A>) -> Self {
let mut s = Self::new_in(arena);
s.extend(iter);
s
}
}
impl<'a, A: Allocator + Clone> FromIteratorIn<'a, alloc::boxed::Box<str>, A> for Utf16String<'a, A> {
fn from_iter_in<I: IntoIterator<Item = alloc::boxed::Box<str>>>(iter: I, arena: &'a Arena<A>) -> Self {
let mut s = Self::new_in(arena);
s.extend(iter);
s
}
}
impl<'a, 'b, A: Allocator + Clone> FromIteratorIn<'a, alloc::borrow::Cow<'b, str>, A> for Utf16String<'a, A> {
fn from_iter_in<I: IntoIterator<Item = alloc::borrow::Cow<'b, str>>>(iter: I, arena: &'a Arena<A>) -> Self {
let mut s = Self::new_in(arena);
s.extend(iter);
s
}
}
impl<A: Allocator + Clone> AsRef<[u16]> for Utf16String<'_, A> {
#[inline]
fn as_ref(&self) -> &[u16] {
self.as_slice()
}
}
impl<A: Allocator + Clone> core::ops::Add<&Utf16Str> for Utf16String<'_, A> {
type Output = Self;
#[inline]
fn add(mut self, rhs: &Utf16Str) -> Self {
self.push_str(rhs);
self
}
}
impl<A: Allocator + Clone> core::ops::AddAssign<&Utf16Str> for Utf16String<'_, A> {
#[inline]
fn add_assign(&mut self, rhs: &Utf16Str) {
self.push_str(rhs);
}
}
impl<I, A: Allocator + Clone> core::ops::Index<I> for Utf16String<'_, A>
where
I: core::ops::RangeBounds<usize> + core::slice::SliceIndex<[u16], Output = [u16]>,
{
type Output = Utf16Str;
#[inline]
fn index(&self, index: I) -> &Utf16Str {
core::ops::Index::index(self.as_utf16_str(), index)
}
}
impl<I, A: Allocator + Clone> core::ops::IndexMut<I> for Utf16String<'_, A>
where
I: core::ops::RangeBounds<usize> + core::slice::SliceIndex<[u16], Output = [u16]>,
{
#[inline]
fn index_mut(&mut self, index: I) -> &mut Utf16Str {
core::ops::IndexMut::index_mut(self.as_mut_utf16_str(), index)
}
}
impl<'b, A: Allocator + Clone> Extend<&'b char> for Utf16String<'_, A> {
fn extend<I: IntoIterator<Item = &'b char>>(&mut self, iter: I) {
for c in iter {
self.push(*c);
}
}
}
impl<'b, A: Allocator + Clone> Extend<alloc::borrow::Cow<'b, str>> for Utf16String<'_, A> {
fn extend<I: IntoIterator<Item = alloc::borrow::Cow<'b, str>>>(&mut self, iter: I) {
for s in iter {
self.push_from_str(&s);
}
}
}
impl<A: Allocator + Clone> Extend<alloc::string::String> for Utf16String<'_, A> {
fn extend<I: IntoIterator<Item = alloc::string::String>>(&mut self, iter: I) {
for s in iter {
self.push_from_str(&s);
}
}
}
impl<A: Allocator + Clone> Extend<alloc::boxed::Box<str>> for Utf16String<'_, A> {
fn extend<I: IntoIterator<Item = alloc::boxed::Box<str>>>(&mut self, iter: I) {
for s in iter {
self.push_from_str(&s);
}
}
}
impl<'a, 'b, A: Allocator + Clone> FromIn<'a, &'b Utf16Str, A> for Utf16String<'a, A> {
#[inline]
fn from_in(value: &'b Utf16Str, arena: &'a Arena<A>) -> Self {
Self::from_utf16_str_in(value, arena)
}
}
impl<'a, 'b, A: Allocator + Clone> FromIn<'a, &'b str, A> for Utf16String<'a, A> {
#[inline]
fn from_in(value: &'b str, arena: &'a Arena<A>) -> Self {
Self::from_str_in(value, arena)
}
}
impl<'a, A: Allocator + Clone> FromIn<'a, char, A> for Utf16String<'a, A> {
#[inline]
fn from_in(value: char, arena: &'a Arena<A>) -> Self {
let mut s = Self::new_in(arena);
s.push(value);
s
}
}
impl<'a, 'b, A: Allocator + Clone> FromIn<'a, alloc::borrow::Cow<'b, Utf16Str>, A> for Utf16String<'a, A> {
#[inline]
fn from_in(value: alloc::borrow::Cow<'b, Utf16Str>, arena: &'a Arena<A>) -> Self {
Self::from_utf16_str_in(&value, arena)
}
}
impl<'a, 'b, A: Allocator + Clone> FromIn<'a, alloc::borrow::Cow<'b, str>, A> for Utf16String<'a, A> {
#[inline]
fn from_in(value: alloc::borrow::Cow<'b, str>, arena: &'a Arena<A>) -> Self {
Self::from_str_in(&value, arena)
}
}
impl<'a, A: Allocator + Clone> FromIn<'a, alloc::boxed::Box<str>, A> for Utf16String<'a, A> {
#[inline]
fn from_in(value: alloc::boxed::Box<str>, arena: &'a Arena<A>) -> Self {
Self::from_str_in(&value, arena)
}
}