#![cfg(feature = "unsafe_alloc")]
use super::StableLayout;
use alloc::string::String;
use core::{
fmt::Debug,
ops::{Deref, DerefMut},
slice, str,
};
#[repr(C)]
pub struct StableString {
ptr: *mut u8,
len: usize,
cap: usize,
}
unsafe impl StableLayout for StableString {}
impl Deref for StableString {
type Target = str;
#[inline(always)]
fn deref(&self) -> &str {
unsafe {
str::from_utf8_unchecked(slice::from_raw_parts(self.ptr, self.len))
}
}
}
impl DerefMut for StableString {
#[inline(always)]
fn deref_mut(&mut self) -> &mut str {
unsafe {
str::from_utf8_unchecked_mut(slice::from_raw_parts_mut(
self.ptr, self.len,
))
}
}
}
impl Debug for StableString {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
Debug::fmt(self.deref(), f)
}
}
impl From<String> for StableString {
fn from(s: String) -> Self {
let mut md_s = core::mem::ManuallyDrop::new(s);
let cap = md_s.capacity();
let len = md_s.len();
let ptr = md_s.as_mut_ptr();
Self { ptr, len, cap }
}
}
impl From<StableString> for String {
fn from(sv: StableString) -> Self {
unsafe { String::from_raw_parts(sv.ptr, sv.len, sv.cap) }
}
}
impl Default for StableString {
#[inline(always)]
fn default() -> Self {
Self::from(String::default())
}
}