use crate::{arraystring::ArrayString, bytearray::ByteArray, tinyvec::TinyVec};
use core::{
convert::Infallible,
fmt,
hash::{Hash, Hasher},
iter::{DoubleEndedIterator, FromIterator, FusedIterator},
ops::{
self, Add, AddAssign, Bound, Deref, DerefMut, Index, IndexMut,
RangeBounds,
},
str::{self, Chars, FromStr, Utf8Error},
};
use alloc::{borrow::Cow, string::String};
use tinyvec_macros::impl_mirrored;
#[derive(Eq, PartialOrd, Ord)]
#[cfg_attr(docs_rs, doc(cfg(target_feature = "alloc")))]
pub enum TinyString<A: ByteArray> {
Inline(ArrayString<A>),
Heap(String),
}
impl<A: ByteArray> Default for TinyString<A> {
fn default() -> Self {
TinyString::Inline(ArrayString::default())
}
}
impl<A: ByteArray> TinyString<A> {
#[inline]
pub fn new() -> TinyString<A> {
TinyString::default()
}
pub fn with_capacity(capacity: usize) -> TinyString<A> {
if capacity <= A::CAPACITY {
TinyString::Inline(ArrayString::default())
} else {
TinyString::Heap(String::with_capacity(capacity))
}
}
#[inline]
pub fn from_utf8(
vec: TinyVec<A>,
) -> Result<TinyString<A>, FromUtf8Error<A>> {
match vec {
TinyVec::Inline(vec) => match ArrayString::from_utf8(vec) {
Ok(s) => Ok(TinyString::Inline(s)),
Err(e) => Err(FromUtf8Error {
error: e.error,
vec: TinyVec::Inline(e.vec),
}),
},
TinyVec::Heap(vec) => match String::from_utf8(vec) {
Ok(s) => Ok(TinyString::Heap(s)),
Err(e) => Err(FromUtf8Error {
error: e.utf8_error(),
vec: TinyVec::Heap(e.into_bytes()),
}),
},
}
}
#[inline]
pub unsafe fn from_utf8_unchecked(vec: TinyVec<A>) -> TinyString<A> {
match vec {
TinyVec::Inline(vec) => {
TinyString::Inline(ArrayString::from_utf8_unchecked(vec))
}
TinyVec::Heap(vec) => {
TinyString::Heap(String::from_utf8_unchecked(vec))
}
}
}
#[inline]
pub fn into_bytes(self) -> TinyVec<A> {
match self {
TinyString::Inline(s) => TinyVec::Inline(s.into_bytes()),
TinyString::Heap(s) => TinyVec::Heap(s.into_bytes()),
}
}
#[inline]
pub fn as_str(&self) -> &str {
&*self
}
#[inline]
pub fn as_mut_str(&mut self) -> &mut str {
&mut *self
}
impl_mirrored! {
type Mirror = TinyString;
#[inline]
pub fn as_bytes(self: &Self) -> &[u8];
}
impl_mirrored! {
type Mirror = TinyString;
#[inline]
pub fn capacity(self: &Self) -> usize;
}
impl_mirrored! {
type Mirror = TinyString;
#[inline]
pub fn len(self: &Self) -> usize;
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn is_heap(&self) -> bool {
match self {
TinyString::Inline(_) => false,
TinyString::Heap(_) => true,
}
}
#[inline]
pub fn is_inline(&self) -> bool {
match self {
TinyString::Inline(_) => true,
TinyString::Heap(_) => false,
}
}
#[inline]
pub fn reserve(&mut self, additional: usize) {
match self {
TinyString::Inline(s) => {
if s.len() + additional > s.capacity() {
let mut heap = String::with_capacity(s.len() + additional);
heap.push_str(s.as_str());
*self = TinyString::Heap(heap);
}
}
TinyString::Heap(s) => s.reserve(additional),
}
}
#[inline]
pub fn reserve_exact(&mut self, additional: usize) {
match self {
TinyString::Inline(s) => {
if s.len() + additional > s.capacity() {
let mut heap = String::with_capacity(s.len() + additional);
heap.push_str(s.as_str());
*self = TinyString::Heap(heap);
}
}
TinyString::Heap(s) => s.reserve_exact(additional),
}
}
#[cfg_attr(docs_rs, doc(cfg(target_feature = "rustc_1_57")))]
#[cfg(feature = "rustc_1_57")]
pub fn try_reserve(
&mut self,
additional: usize,
) -> Result<(), alloc::collections::TryReserveError> {
match self {
TinyString::Inline(s) => match s.len().checked_add(additional) {
Some(new_cap) if new_cap > s.capacity() => {
let mut heap = String::new();
heap.try_reserve(new_cap)?;
heap.push_str(s.as_str());
*self = TinyString::Heap(heap);
Ok(())
}
Some(_) => Ok(()),
None => String::new().try_reserve(usize::MAX),
},
TinyString::Heap(s) => s.try_reserve(additional),
}
}
#[cfg_attr(docs_rs, doc(cfg(target_feature = "rustc_1_57")))]
#[cfg(feature = "rustc_1_57")]
pub fn try_reserve_exact(
&mut self,
additional: usize,
) -> Result<(), alloc::collections::TryReserveError> {
match self {
TinyString::Inline(s) => match s.len().checked_add(additional) {
Some(new_cap) if new_cap > s.capacity() => {
let mut heap = String::new();
heap.try_reserve_exact(new_cap)?;
heap.push_str(s.as_str());
*self = TinyString::Heap(heap);
Ok(())
}
Some(_) => Ok(()),
None => String::new().try_reserve(usize::MAX),
},
TinyString::Heap(s) => s.try_reserve_exact(additional),
}
}
pub fn shrink_to_fit(&mut self) {
if self.is_heap() {
if self.len() <= A::CAPACITY {
*self = TinyString::Inline(ArrayString::from(self.as_str()));
} else {
match self {
TinyString::Heap(s) => s.shrink_to_fit(),
TinyString::Inline(_) => unreachable!(),
}
}
}
}
pub fn shrink_to(&mut self, min_capacity: usize) {
if self.is_heap() {
if self.len().max(min_capacity) <= A::CAPACITY {
*self = TinyString::Inline(ArrayString::from(self.as_str()));
} else {
match self {
TinyString::Heap(s) => s.shrink_to(min_capacity),
TinyString::Inline(_) => unreachable!(),
}
}
}
}
#[inline]
pub fn push_str(&mut self, string: &str) {
self.reserve(string.len());
match self {
TinyString::Inline(s) => s.push_str(string),
TinyString::Heap(s) => s.push_str(string),
}
}
#[inline]
pub fn push(&mut self, ch: char) {
self.reserve(ch.len_utf8());
match self {
TinyString::Inline(s) => s.push(ch),
TinyString::Heap(s) => s.push(ch),
}
}
impl_mirrored! {
type Mirror = TinyString;
#[inline]
pub fn truncate(self: &mut Self, new_len: usize);
}
impl_mirrored! {
type Mirror = TinyString;
#[inline]
pub fn pop(self: &mut Self) -> Option<char>;
}
impl_mirrored! {
type Mirror = TinyString;
#[inline]
pub fn remove(self: &mut Self, idx: usize) -> char;
}
#[inline]
pub fn retain<F>(&mut self, f: F)
where
F: FnMut(char) -> bool,
{
match self {
TinyString::Inline(s) => s.retain(f),
TinyString::Heap(s) => s.retain(f),
}
}
#[inline]
pub fn insert(&mut self, idx: usize, ch: char) {
self.reserve(ch.len_utf8());
match self {
TinyString::Inline(s) => s.insert(idx, ch),
TinyString::Heap(s) => s.insert(idx, ch),
}
}
#[inline]
pub fn insert_str(&mut self, idx: usize, string: &str) {
self.reserve(string.len());
match self {
TinyString::Inline(s) => s.insert_str(idx, string),
TinyString::Heap(s) => s.insert_str(idx, string),
}
}
impl_mirrored! {
type Mirror = TinyString;
#[inline]
pub fn clear(self: &mut Self);
}
pub fn drain<R>(&mut self, range: R) -> Drain<'_, A>
where
R: RangeBounds<usize>,
{
use Bound::*;
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,
}
}
#[inline]
pub fn move_to_the_heap(&mut self) {
match self {
TinyString::Inline(s) => {
*self = TinyString::Heap(String::from(s.as_str()))
}
TinyString::Heap(_) => (),
}
}
#[inline]
pub fn replace_range<R>(&mut self, range: R, replace_with: &str)
where
R: RangeBounds<usize>,
{
match self {
TinyString::Inline(s) => s.replace_range(range, replace_with),
TinyString::Heap(s) => s.replace_range(range, replace_with),
}
}
#[inline]
#[must_use = "use `.truncate()` if you don't need the other half"]
pub fn split_off(&mut self, at: usize) -> TinyString<A> {
match self {
TinyString::Inline(s) => TinyString::Inline(s.split_off(at)),
TinyString::Heap(s) => TinyString::Heap(s.split_off(at)),
}
}
}
impl<A: ByteArray> Deref for TinyString<A> {
type Target = str;
impl_mirrored! {
type Mirror = TinyString;
#[inline]
fn deref(self: &Self) -> &str;
}
}
impl<A: ByteArray> DerefMut for TinyString<A> {
impl_mirrored! {
type Mirror = TinyString;
#[inline]
fn deref_mut(self: &mut Self) -> &mut str;
}
}
impl<A: ByteArray> fmt::Display for TinyString<A> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&**self, f)
}
}
impl<A: ByteArray> fmt::Debug for TinyString<A> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<A: ByteArray> Hash for TinyString<A> {
#[inline]
fn hash<H: Hasher>(&self, hasher: &mut H) {
(**self).hash(hasher)
}
}
impl<A: ByteArray + Clone> Clone for TinyString<A> {
#[inline]
fn clone(&self) -> Self {
match self {
TinyString::Inline(s) => TinyString::Inline(s.clone()),
TinyString::Heap(s) => TinyString::Heap(s.clone()),
}
}
#[inline]
fn clone_from(&mut self, source: &Self) {
match source {
TinyString::Inline(s) => *self = TinyString::Inline(s.clone()),
TinyString::Heap(s) => *self = TinyString::Heap(s.clone()),
}
}
}
impl<A: ByteArray, A2: ByteArray> FromIterator<TinyString<A2>>
for TinyString<A>
{
fn from_iter<I: IntoIterator<Item = TinyString<A2>>>(iter: I) -> Self {
let mut buf = TinyString::new();
buf.extend(iter);
buf
}
}
macro_rules! impl_from_iterator {
($(#[$meta:meta])* $ty:ty) => {
$(#[$meta])*
#[allow(unused_lifetimes)]
impl<'a, A: ByteArray> FromIterator<$ty>
for TinyString<A>
{
fn from_iter<I: IntoIterator<Item = $ty>>(iter: I) -> Self {
let mut buf = TinyString::new();
buf.extend(iter);
buf
}
}
};
}
impl_from_iterator!(
#[cfg_attr(docs_rs, doc(cfg(target_feature = "alloc")))]
#[cfg(feature = "alloc")] Cow<'a, str>);
impl_from_iterator!(
#[cfg_attr(docs_rs, doc(cfg(target_feature = "alloc")))]
#[cfg(feature = "alloc")]
String
);
impl_from_iterator!(&'a str);
impl_from_iterator!(&'a char);
impl_from_iterator!(char);
impl<A: ByteArray> Extend<char> for TinyString<A> {
fn extend<I: IntoIterator<Item = char>>(&mut self, iter: I) {
let iterator = iter.into_iter();
iterator.for_each(move |c| self.push(c));
}
}
impl<'a, A: ByteArray> Extend<&'a char> for TinyString<A> {
fn extend<I: IntoIterator<Item = &'a char>>(&mut self, iter: I) {
self.extend(iter.into_iter().copied());
}
}
impl<'a, A: ByteArray> Extend<&'a str> for TinyString<A> {
fn extend<I: IntoIterator<Item = &'a str>>(&mut self, iter: I) {
iter.into_iter().for_each(move |s| self.push_str(s));
}
}
#[cfg_attr(docs_rs, doc(cfg(target_feature = "alloc")))]
#[cfg(feature = "alloc")]
impl<A: ByteArray> Extend<String> for TinyString<A> {
fn extend<I: IntoIterator<Item = String>>(&mut self, iter: I) {
iter.into_iter().for_each(move |s| self.push_str(&s));
}
}
impl<A: ByteArray, A2: ByteArray> Extend<TinyString<A2>> for TinyString<A> {
fn extend<I: IntoIterator<Item = TinyString<A2>>>(&mut self, iter: I) {
iter.into_iter().for_each(move |s| self.push_str(&s));
}
}
#[cfg_attr(docs_rs, doc(cfg(target_feature = "alloc")))]
#[cfg(feature = "alloc")]
impl<'a, A: ByteArray> Extend<Cow<'a, str>> for TinyString<A> {
fn extend<I: IntoIterator<Item = Cow<'a, str>>>(&mut self, iter: I) {
iter.into_iter().for_each(move |s| self.push_str(&s));
}
}
macro_rules! impl_eq {
($(#[$meta:meta])* $lhs:ty, $rhs: ty) => {
$(#[$meta])*
#[allow(unused_lifetimes)]
impl<'a, 'b, A: ByteArray> PartialEq<$rhs> for $lhs {
#[inline]
fn eq(&self, other: &$rhs) -> bool {
PartialEq::eq(&self[..], &other[..])
}
#[inline]
fn ne(&self, other: &$rhs) -> bool {
PartialEq::ne(&self[..], &other[..])
}
}
$(#[$meta])*
#[allow(unused_lifetimes)]
impl<'a, 'b, A: ByteArray> PartialEq<$lhs> for $rhs {
#[inline]
fn eq(&self, other: &$lhs) -> bool {
PartialEq::eq(&self[..], &other[..])
}
#[inline]
fn ne(&self, other: &$lhs) -> bool {
PartialEq::ne(&self[..], &other[..])
}
}
};
}
impl_eq! { TinyString<A>, str }
impl_eq! { TinyString<A>, &'a str }
impl_eq! {
#[cfg_attr(docs_rs, doc(cfg(target_feature = "alloc")))]
#[cfg(feature = "alloc")]
TinyString<A>, Cow<'a, str>
}
impl_eq! {
#[cfg_attr(docs_rs, doc(cfg(target_feature = "alloc")))]
#[cfg(feature = "alloc")]
TinyString<A>, String
}
impl<A1, A2> PartialEq<TinyString<A1>> for TinyString<A2>
where
A1: ByteArray,
A2: ByteArray,
{
#[inline]
fn eq(&self, other: &TinyString<A1>) -> bool {
PartialEq::eq(&self[..], &other[..])
}
#[inline]
fn ne(&self, other: &TinyString<A1>) -> bool {
PartialEq::ne(&self[..], &other[..])
}
}
impl<A: ByteArray> Add<&str> for TinyString<A> {
type Output = TinyString<A>;
#[inline]
fn add(mut self, other: &str) -> Self {
self.push_str(other);
self
}
}
impl<A: ByteArray> AddAssign<&str> for TinyString<A> {
#[inline]
fn add_assign(&mut self, other: &str) {
self.push_str(other);
}
}
impl<A: ByteArray> ops::Index<ops::Range<usize>> for TinyString<A> {
type Output = str;
#[inline]
fn index(&self, index: ops::Range<usize>) -> &str {
&self[..][index]
}
}
impl<A: ByteArray> ops::Index<ops::RangeTo<usize>> for TinyString<A> {
type Output = str;
#[inline]
fn index(&self, index: ops::RangeTo<usize>) -> &str {
&self[..][index]
}
}
impl<A: ByteArray> ops::Index<ops::RangeFrom<usize>> for TinyString<A> {
type Output = str;
#[inline]
fn index(&self, index: ops::RangeFrom<usize>) -> &str {
&self[..][index]
}
}
impl<A: ByteArray> ops::Index<ops::RangeFull> for TinyString<A> {
type Output = str;
impl_mirrored! {
type Mirror = TinyString;
#[inline]
fn index(self: &Self, index: ops::RangeFull) -> &str;
}
}
impl<A: ByteArray> ops::Index<ops::RangeInclusive<usize>> for TinyString<A> {
type Output = str;
#[inline]
fn index(&self, index: ops::RangeInclusive<usize>) -> &str {
Index::index(&**self, index)
}
}
impl<A: ByteArray> ops::Index<ops::RangeToInclusive<usize>> for TinyString<A> {
type Output = str;
#[inline]
fn index(&self, index: ops::RangeToInclusive<usize>) -> &str {
Index::index(&**self, index)
}
}
impl<A: ByteArray> ops::IndexMut<ops::Range<usize>> for TinyString<A> {
#[inline]
fn index_mut(&mut self, index: ops::Range<usize>) -> &mut str {
&mut self[..][index]
}
}
impl<A: ByteArray> ops::IndexMut<ops::RangeTo<usize>> for TinyString<A> {
#[inline]
fn index_mut(&mut self, index: ops::RangeTo<usize>) -> &mut str {
&mut self[..][index]
}
}
impl<A: ByteArray> ops::IndexMut<ops::RangeFrom<usize>> for TinyString<A> {
#[inline]
fn index_mut(&mut self, index: ops::RangeFrom<usize>) -> &mut str {
&mut self[..][index]
}
}
impl<A: ByteArray> ops::IndexMut<ops::RangeFull> for TinyString<A> {
impl_mirrored! {
type Mirror = TinyString;
#[inline]
fn index_mut(self: &mut Self, index: ops::RangeFull) -> &mut str;
}
}
impl<A: ByteArray> ops::IndexMut<ops::RangeInclusive<usize>> for TinyString<A> {
#[inline]
fn index_mut(&mut self, index: ops::RangeInclusive<usize>) -> &mut str {
IndexMut::index_mut(&mut **self, index)
}
}
impl<A: ByteArray> ops::IndexMut<ops::RangeToInclusive<usize>>
for TinyString<A>
{
#[inline]
fn index_mut(&mut self, index: ops::RangeToInclusive<usize>) -> &mut str {
IndexMut::index_mut(&mut **self, index)
}
}
impl<A: ByteArray> AsRef<str> for TinyString<A> {
#[inline]
fn as_ref(&self) -> &str {
&*self
}
}
impl<A: ByteArray> AsMut<str> for TinyString<A> {
#[inline]
fn as_mut(&mut self) -> &mut str {
&mut *self
}
}
impl<A: ByteArray> AsRef<[u8]> for TinyString<A> {
#[inline]
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
impl<'a, A: ByteArray> From<&'a str> for TinyString<A> {
fn from(s: &'a str) -> Self {
unsafe {
let mut tv = TinyVec::from_array_len(A::DEFAULT, 0);
tv.extend(s.as_bytes().iter().copied());
TinyString::from_utf8_unchecked(tv)
}
}
}
impl<'a, A: ByteArray> From<&'a mut str> for TinyString<A> {
fn from(s: &'a mut str) -> Self {
TinyString::from(&*s)
}
}
impl<A: ByteArray> From<char> for TinyString<A> {
fn from(c: char) -> Self {
let mut buf = [0u8; 4];
let s = c.encode_utf8(&mut buf);
TinyString::from(s)
}
}
impl<'a, A: ByteArray> From<&'a char> for TinyString<A> {
fn from(c: &'a char) -> Self {
TinyString::from(*c)
}
}
impl<'a, A: ByteArray> From<&'a String> for TinyString<A> {
fn from(s: &'a String) -> Self {
TinyString::from(s.as_str())
}
}
impl<A: ByteArray> From<String> for TinyString<A> {
fn from(s: String) -> Self {
unsafe {
TinyString::from_utf8_unchecked(TinyVec::Heap(s.into_bytes()))
}
}
}
impl<'a, A: ByteArray> From<Cow<'a, str>> for TinyString<A> {
fn from(s: Cow<'a, str>) -> Self {
match s {
Cow::Borrowed(s) => TinyString::from(s),
Cow::Owned(s) => TinyString::from(s),
}
}
}
impl<A: ByteArray> FromStr for TinyString<A> {
type Err = Infallible;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(TinyString::from(s))
}
}
impl<A: ByteArray> fmt::Write for TinyString<A> {
#[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(())
}
}
#[cfg_attr(docs_rs, doc(cfg(target_feature = "serde")))]
#[cfg(feature = "serde")]
impl<A: ByteArray> serde::Serialize for TinyString<A> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(self.as_str())
}
}
#[cfg_attr(docs_rs, doc(cfg(target_feature = "serde")))]
#[cfg(feature = "serde")]
impl<'de, A: ByteArray> serde::Deserialize<'de> for TinyString<A> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
use core::marker::PhantomData;
struct TinyStringVisitor<A>(PhantomData<fn() -> A>);
impl<'de, A: ByteArray> serde::de::Visitor<'de> for TinyStringVisitor<A> {
type Value = TinyString<A>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "a string up to length {}", A::CAPACITY)
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(TinyString::from(v))
}
}
deserializer.deserialize_str(TinyStringVisitor(PhantomData))
}
}
#[derive(Clone, PartialEq, Eq)]
pub struct FromUtf8Error<A: ByteArray> {
vec: TinyVec<A>,
error: Utf8Error,
}
impl<A: ByteArray> FromUtf8Error<A> {
pub fn as_bytes(&self) -> &[u8] {
&self.vec[..]
}
pub fn into_bytes(self) -> TinyVec<A> {
self.vec
}
pub fn utf8_error(&self) -> Utf8Error {
self.error
}
}
impl<A: ByteArray> fmt::Debug for FromUtf8Error<A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FromUtf8Error")
.field("vec", &self.vec)
.field("error", &self.error)
.finish()
}
}
impl<A: ByteArray> fmt::Display for FromUtf8Error<A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.error, f)
}
}
#[cfg_attr(docs_rs, doc(cfg(target_feature = "std")))]
#[cfg(feature = "std")]
impl<A: ByteArray> std::error::Error for FromUtf8Error<A> {}
pub struct Drain<'a, A: ByteArray> {
string: *mut TinyString<A>,
start: usize,
end: usize,
iter: Chars<'a>,
}
impl<A: ByteArray> fmt::Debug for Drain<'_, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.pad("Drain { .. }")
}
}
unsafe impl<A: ByteArray> Send for Drain<'_, A> {}
unsafe impl<A: ByteArray> Sync for Drain<'_, A> {}
impl<A: ByteArray> Drop for Drain<'_, A> {
fn drop(&mut self) {
unsafe {
let this = &mut *self.string;
match this {
TinyString::Inline(s) => {
let this_vec = s.as_mut_vec();
if self.start <= self.end && self.end <= this_vec.len() {
drop(this_vec.drain(self.start..self.end))
}
}
TinyString::Heap(s) => {
let this_vec = s.as_mut_vec();
if self.start <= self.end && self.end <= this_vec.len() {
drop(this_vec.drain(self.start..self.end))
}
}
}
}
}
}
impl<A: ByteArray> Iterator for Drain<'_, A> {
type Item = char;
#[inline]
fn next(&mut self) -> Option<char> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
#[inline]
fn last(mut self) -> Option<char> {
self.next_back()
}
}
impl<A: ByteArray> DoubleEndedIterator for Drain<'_, A> {
#[inline]
fn next_back(&mut self) -> Option<char> {
self.iter.next_back()
}
}
impl<A: ByteArray> FusedIterator for Drain<'_, A> {}