macro_rules! impl_str_accessors {
([$($g:tt)+], $ty:ty) => {
impl $($g)+ $ty {
#[must_use]
#[inline]
pub fn as_str(&self) -> &str {
let data = self.data_ptr();
let len = unsafe { ::core::ptr::read_unaligned(data.cast::<usize>().as_ptr().sub(1)) };
unsafe { ::core::str::from_utf8_unchecked(::core::slice::from_raw_parts(data.as_ptr(), len)) }
}
#[must_use]
#[inline]
pub fn len(&self) -> usize {
unsafe { ::core::ptr::read_unaligned(self.data_ptr().cast::<usize>().as_ptr().sub(1)) }
}
#[must_use]
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
};
}
macro_rules! impl_str_read_traits_generic {
([$($g:tt)+], $ty:ty, $view:ty, $as_view:ident) => {
impl $($g)+ ::core::ops::Deref for $ty {
type Target = $view;
#[inline]
fn deref(&self) -> &$view { self.$as_view() }
}
impl $($g)+ ::core::convert::AsRef<$view> for $ty {
#[inline]
fn as_ref(&self) -> &$view { self.$as_view() }
}
impl $($g)+ ::core::borrow::Borrow<$view> for $ty {
#[inline]
fn borrow(&self) -> &$view { self.$as_view() }
}
impl $($g)+ ::core::fmt::Debug for $ty {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
::core::fmt::Debug::fmt(self.$as_view(), f)
}
}
impl $($g)+ ::core::fmt::Display for $ty {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
::core::fmt::Display::fmt(self.$as_view(), f)
}
}
impl $($g)+ ::core::cmp::PartialEq for $ty {
#[inline]
fn eq(&self, other: &Self) -> bool { self.$as_view() == other.$as_view() }
}
impl $($g)+ ::core::cmp::Eq for $ty {}
impl $($g)+ ::core::cmp::PartialOrd for $ty {
#[inline]
fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(self.cmp(other))
}
}
impl $($g)+ ::core::cmp::Ord for $ty {
#[inline]
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
self.$as_view().cmp(other.$as_view())
}
}
impl $($g)+ ::core::hash::Hash for $ty {
fn hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
::core::hash::Hash::hash(self.$as_view(), state)
}
}
impl $($g)+ ::core::fmt::Pointer for $ty {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
::core::fmt::Pointer::fmt(&self.data_ptr().as_ptr(), f)
}
}
};
}
pub(crate) use impl_str_read_traits_generic;
macro_rules! impl_str_read_traits {
([$($g:tt)+], $ty:ty) => {
$crate::arena_str_macros::impl_str_read_traits_generic!([$($g)+], $ty, str, as_str);
};
}
pub(crate) use impl_str_accessors;
pub(crate) use impl_str_read_traits;
macro_rules! impl_str_handle_local_storage {
($ty:ident, $elem:ty) => {
impl<A: ::allocator_api2::alloc::Allocator + ::core::clone::Clone> $ty<A> {
#[inline]
#[must_use]
pub(crate) const unsafe fn from_raw_data(data: ::core::ptr::NonNull<$elem>) -> Self {
unsafe { Self::from_in_chunk($crate::internal::in_chunk::InLocalChunk::new(data)) }
}
#[inline]
#[must_use]
pub(crate) const unsafe fn from_in_chunk(data: $crate::internal::in_chunk::InLocalChunk<$elem, A>) -> Self {
Self {
data,
_phantom: ::core::marker::PhantomData,
}
}
#[inline]
#[must_use]
pub(crate) fn from_owned_in_chunk(owned: $crate::internal::owned_in_chunk::OwnedInLocalChunk<$elem, A>) -> Self {
Self {
data: owned.into_in_chunk(),
_phantom: ::core::marker::PhantomData,
}
}
}
impl<A: ::allocator_api2::alloc::Allocator + ::core::clone::Clone> ::core::clone::Clone for $ty<A> {
#[inline]
fn clone(&self) -> Self {
unsafe { self.data.chunk_ptr().as_ref() }.inc_ref();
Self {
data: self.data,
_phantom: ::core::marker::PhantomData,
}
}
}
};
}
macro_rules! impl_str_handle_shared_storage {
($ty:ident, $elem:ty) => {
impl<A: ::allocator_api2::alloc::Allocator + ::core::clone::Clone> $ty<A> {
#[inline]
#[must_use]
pub(crate) fn from_owned_in_chunk(owned: $crate::internal::owned_in_chunk::OwnedInSharedChunk<$elem, A>) -> Self {
Self {
data: owned.into_in_chunk(),
_phantom: ::core::marker::PhantomData,
}
}
}
impl<A: ::allocator_api2::alloc::Allocator + ::core::clone::Clone> ::core::clone::Clone for $ty<A> {
#[inline]
fn clone(&self) -> Self {
unsafe { self.data.chunk_ptr().as_ref() }.inc_ref();
Self {
data: self.data,
_phantom: ::core::marker::PhantomData,
}
}
}
};
}
macro_rules! impl_str_handle_body_generic {
($ty:ident, $elem:ty, $view:ty, $as_view:ident) => {
impl<A: ::allocator_api2::alloc::Allocator + ::core::clone::Clone> $ty<A> {
#[inline]
pub(crate) const fn data_ptr(&self) -> ::core::ptr::NonNull<$elem> {
self.data.as_non_null()
}
}
impl<A: ::allocator_api2::alloc::Allocator + ::core::clone::Clone> ::core::marker::Unpin for $ty<A> {}
impl<A: ::allocator_api2::alloc::Allocator + ::core::clone::Clone> ::core::cmp::PartialEq<$view> for $ty<A> {
#[inline]
fn eq(&self, other: &$view) -> bool {
self.$as_view() == other
}
}
impl<A: ::allocator_api2::alloc::Allocator + ::core::clone::Clone> ::core::cmp::PartialEq<&$view> for $ty<A> {
#[inline]
fn eq(&self, other: &&$view) -> bool {
self.$as_view() == *other
}
}
};
}
pub(crate) use impl_str_handle_body_generic;
macro_rules! impl_str_handle_core {
(@body $ty:ident) => {
$crate::arena_str_macros::impl_str_handle_body_generic!($ty, u8, str, as_str);
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<A: ::allocator_api2::alloc::Allocator + ::core::clone::Clone> ::serde::ser::Serialize for $ty<A> {
fn serialize<S: ::serde::ser::Serializer>(&self, serializer: S) -> ::core::result::Result<S::Ok, S::Error> {
serializer.serialize_str(self.as_str())
}
}
};
($ty:ident, Local) => {
$crate::arena_str_macros::impl_str_handle_local_storage!($ty, u8);
impl_str_handle_core!(@body $ty);
};
($ty:ident, Shared) => {
$crate::arena_str_macros::impl_str_handle_shared_storage!($ty, u8);
impl_str_handle_core!(@body $ty);
};
}
pub(crate) use impl_str_handle_core;
pub(crate) use impl_str_handle_local_storage;
pub(crate) use impl_str_handle_shared_storage;
#[cfg(feature = "utf16")]
macro_rules! impl_utf16_str_handle_core {
(@body $ty:ident) => {
$crate::arena_str_macros::impl_str_handle_body_generic!($ty, u16, ::widestring::Utf16Str, as_utf16_str);
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<A: ::allocator_api2::alloc::Allocator + ::core::clone::Clone> ::serde::ser::Serialize for $ty<A> {
fn serialize<S: ::serde::ser::Serializer>(&self, serializer: S) -> ::core::result::Result<S::Ok, S::Error> {
let owned: ::alloc::string::String = self.as_utf16_str().to_string();
serializer.serialize_str(&owned)
}
}
};
($ty:ident, Local) => {
$crate::arena_str_macros::impl_str_handle_local_storage!($ty, u16);
impl_utf16_str_handle_core!(@body $ty);
};
($ty:ident, Shared) => {
$crate::arena_str_macros::impl_str_handle_shared_storage!($ty, u16);
impl_utf16_str_handle_core!(@body $ty);
};
}
#[cfg(feature = "utf16")]
pub(crate) use impl_utf16_str_handle_core;
#[cfg(feature = "utf16")]
macro_rules! impl_utf16_str_accessors {
([$($g:tt)+], $ty:ty) => {
impl $($g)+ $ty {
#[must_use]
#[inline]
pub fn as_utf16_str(&self) -> &::widestring::Utf16Str {
let data = self.data_ptr();
let len = unsafe { ::core::ptr::read_unaligned(data.cast::<usize>().as_ptr().sub(1)) };
let slice = unsafe { ::core::slice::from_raw_parts(data.as_ptr(), len) };
unsafe { ::widestring::Utf16Str::from_slice_unchecked(slice) }
}
#[must_use]
#[inline]
pub fn len(&self) -> usize {
unsafe { ::core::ptr::read_unaligned(self.data_ptr().cast::<usize>().as_ptr().sub(1)) }
}
#[must_use]
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
};
}
#[cfg(feature = "utf16")]
macro_rules! impl_utf16_str_read_traits {
([$($g:tt)+], $ty:ty) => {
$crate::arena_str_macros::impl_str_read_traits_generic!(
[$($g)+], $ty, ::widestring::Utf16Str, as_utf16_str
);
};
}
#[cfg(feature = "utf16")]
pub(crate) use impl_utf16_str_accessors;
#[cfg(feature = "utf16")]
pub(crate) use impl_utf16_str_read_traits;
macro_rules! impl_arena_string_forwarding_traits {
($Ty:ident, $lt:lifetime, $StrTy:ty, $as_str:ident, $as_mut:ident) => {
impl<A: Allocator + Clone> Drop for $Ty<'_, A> {
#[inline]
fn drop(&mut self) {
if self.cap > 0 {
let in_chunk = unsafe { crate::internal::in_chunk::InLocalChunk::<_, A>::new(self.data) };
let chunk = in_chunk.chunk_ptr();
unsafe { crate::internal::local_chunk::LocalChunk::dec_ref(chunk) };
}
}
}
impl<A: Allocator + Clone> ::core::ops::Deref for $Ty<'_, A> {
type Target = $StrTy;
#[inline]
fn deref(&self) -> &$StrTy {
self.$as_str()
}
}
impl<A: Allocator + Clone> ::core::ops::DerefMut for $Ty<'_, A> {
#[inline]
fn deref_mut(&mut self) -> &mut $StrTy {
self.$as_mut()
}
}
impl<A: Allocator + Clone> ::core::convert::AsRef<$StrTy> for $Ty<'_, A> {
fn as_ref(&self) -> &$StrTy {
self.$as_str()
}
}
impl<A: Allocator + Clone> ::core::convert::AsMut<$StrTy> for $Ty<'_, A> {
fn as_mut(&mut self) -> &mut $StrTy {
self.$as_mut()
}
}
impl<A: Allocator + Clone> ::core::borrow::Borrow<$StrTy> for $Ty<'_, A> {
fn borrow(&self) -> &$StrTy {
self.$as_str()
}
}
impl<A: Allocator + Clone> ::core::borrow::BorrowMut<$StrTy> for $Ty<'_, A> {
fn borrow_mut(&mut self) -> &mut $StrTy {
self.$as_mut()
}
}
impl<A: Allocator + Clone> ::core::fmt::Debug for $Ty<'_, A> {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
::core::fmt::Debug::fmt(self.$as_str(), f)
}
}
impl<A: Allocator + Clone> ::core::fmt::Display for $Ty<'_, A> {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
::core::fmt::Display::fmt(self.$as_str(), f)
}
}
impl<A: Allocator + Clone> ::core::cmp::PartialEq for $Ty<'_, A> {
fn eq(&self, other: &Self) -> bool {
self.$as_str() == other.$as_str()
}
}
impl<A: Allocator + Clone> ::core::cmp::Eq for $Ty<'_, A> {}
impl<A: Allocator + Clone> ::core::cmp::PartialOrd for $Ty<'_, A> {
fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<A: Allocator + Clone> ::core::cmp::Ord for $Ty<'_, A> {
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
self.$as_str().cmp(other.$as_str())
}
}
impl<A: Allocator + Clone> ::core::hash::Hash for $Ty<'_, A> {
fn hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
::core::hash::Hash::hash(self.$as_str(), state);
}
}
impl<A: Allocator + Clone> ::core::cmp::PartialEq<$StrTy> for $Ty<'_, A> {
#[inline]
fn eq(&self, other: &$StrTy) -> bool {
self.$as_str() == other
}
}
impl<A: Allocator + Clone> ::core::cmp::PartialEq<&$StrTy> for $Ty<'_, A> {
#[inline]
fn eq(&self, other: &&$StrTy) -> bool {
self.$as_str() == *other
}
}
};
}
pub(crate) use impl_arena_string_forwarding_traits;
macro_rules! impl_box_str_extras_common {
($Box:ident, $Rc:ident, $view:ty, $as_view:ident, $as_mut:ident, $into_rc:ident) => {
impl<A: Allocator + Clone> Drop for $Box<A> {
#[inline]
fn drop(&mut self) {
let chunk = self.data.chunk_ptr();
unsafe { crate::internal::local_chunk::LocalChunk::dec_ref(chunk) };
}
}
impl<A: Allocator + Clone> ::core::ops::DerefMut for $Box<A> {
#[inline]
fn deref_mut(&mut self) -> &mut $view {
self.$as_mut()
}
}
impl<A: Allocator + Clone> ::core::convert::AsMut<$view> for $Box<A> {
#[inline]
fn as_mut(&mut self) -> &mut $view {
self.$as_mut()
}
}
impl<A: Allocator + Clone> ::core::borrow::BorrowMut<$view> for $Box<A> {
#[inline]
fn borrow_mut(&mut self) -> &mut $view {
self.$as_mut()
}
}
impl<A: Allocator + Clone> From<$Box<A>> for $Rc<A> {
#[inline]
fn from(b: $Box<A>) -> Self {
b.$into_rc()
}
}
impl<A: Allocator + Clone> ::core::cmp::PartialEq<$view> for $Box<A> {
#[inline]
fn eq(&self, other: &$view) -> bool {
self.$as_view() == other
}
}
impl<A: Allocator + Clone> ::core::cmp::PartialEq<&$view> for $Box<A> {
#[inline]
fn eq(&self, other: &&$view) -> bool {
self.$as_view() == *other
}
}
};
}
pub(crate) use impl_box_str_extras_common;
macro_rules! impl_box_str_extras {
($Box:ident, $Rc:ident) => {
impl<A: Allocator + Clone> $Box<A> {
#[must_use]
#[inline]
#[allow(
clippy::needless_pass_by_ref_mut,
reason = "&mut self is the API contract — the returned &mut str borrows exclusively from self"
)]
pub fn as_mut_str(&mut self) -> &mut str {
let data = self.data.as_non_null();
let len = unsafe { ::core::ptr::read_unaligned(data.cast::<usize>().as_ptr().sub(1)) };
unsafe { core::str::from_utf8_unchecked_mut(core::slice::from_raw_parts_mut(data.as_ptr(), len)) }
}
#[must_use]
#[inline]
pub fn into_rc_str(self) -> $Rc<A> {
let data = self.data.as_non_null();
core::mem::forget(self);
unsafe { $Rc::from_raw_data(data) }
}
}
$crate::arena_str_macros::impl_box_str_extras_common!($Box, $Rc, str, as_str, as_mut_str, into_rc_str);
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<A: Allocator + Clone> serde::ser::Serialize for $Box<A> {
fn serialize<S: serde::ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(self.as_str())
}
}
};
}
pub(crate) use impl_box_str_extras;
#[cfg(feature = "utf16")]
macro_rules! impl_box_utf16_str_extras {
($Box:ident, $Rc:ident) => {
impl<A: Allocator + Clone> $Box<A> {
#[must_use]
#[inline]
#[allow(
clippy::needless_pass_by_ref_mut,
reason = "&mut self is the API contract — the returned &mut Utf16Str borrows exclusively from self"
)]
pub fn as_mut_utf16_str(&mut self) -> &mut ::widestring::Utf16Str {
let data = self.data.as_non_null();
let len = self.len();
let slice = unsafe { core::slice::from_raw_parts_mut(data.as_ptr(), len) };
unsafe { ::widestring::Utf16Str::from_slice_unchecked_mut(slice) }
}
#[doc = concat!("[`", stringify!($Rc), "<A>`]. O(1).")]
#[must_use]
#[inline]
pub fn into_rc_utf16_str(self) -> $Rc<A> {
let data = self.data.as_non_null();
core::mem::forget(self);
unsafe { $Rc::from_raw_data(data) }
}
}
impl<A: Allocator + Clone> ::core::marker::Unpin for $Box<A> {}
$crate::arena_str_macros::impl_box_str_extras_common!(
$Box,
$Rc,
::widestring::Utf16Str,
as_utf16_str,
as_mut_utf16_str,
into_rc_utf16_str
);
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<A: Allocator + Clone> serde::ser::Serialize for $Box<A> {
fn serialize<S: serde::ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let s = self.as_utf16_str();
let owned = s.to_string();
serializer.serialize_str(&owned)
}
}
};
}
#[cfg(feature = "utf16")]
pub(crate) use impl_box_utf16_str_extras;
macro_rules! impl_from_str_for_slice_handle {
($Handle:ident, $Ptr:ident, $ElemTy:ty) => {
impl<A: Allocator + Clone> ::core::convert::From<$Handle<A>> for crate::$Ptr<[$ElemTy], A> {
#[doc = concat!(
"Convert a [`", stringify!($Handle), "<A>`] into an [`",
stringify!($Ptr), "<[", stringify!($ElemTy), "], A>`](crate::", stringify!($Ptr), ")."
)]
#[inline]
fn from(s: $Handle<A>) -> Self {
let data = s.data_ptr();
let len = s.len();
core::mem::forget(s);
let slice_ptr = core::ptr::slice_from_raw_parts_mut(data.as_ptr(), len);
unsafe { Self::from_value_ptr(core::ptr::NonNull::new_unchecked(slice_ptr)) }
}
}
};
}
pub(crate) use impl_from_str_for_slice_handle;