aliasable/
string.rs

1//! Aliasable `String`.
2
3use core::ops::{Deref, DerefMut};
4use core::pin::Pin;
5use core::{fmt, str};
6
7use crate::vec::AliasableVec;
8
9pub use alloc::string::String as UniqueString;
10
11/// Basic aliasable (non `core::ptr::Unique`) alternative to
12/// [`alloc::string::String`].
13pub struct AliasableString(AliasableVec<u8>);
14
15impl AliasableString {
16    /// Consumes `self` into an [`AliasableVec`] of UTF-8 bytes.
17    pub fn into_bytes(self) -> AliasableVec<u8> {
18        self.0
19    }
20
21    /// Construct an `AliasableString` from a [`UniqueString`].
22    pub fn from_unique(s: UniqueString) -> Self {
23        Self(s.into_bytes().into())
24    }
25
26    /// Consumes `self` and converts it into a non-aliasable [`UniqueString`].
27    #[inline]
28    pub fn into_unique(s: AliasableString) -> UniqueString {
29        let unique_bytes = s.into_bytes().into();
30        unsafe { UniqueString::from_utf8_unchecked(unique_bytes) }
31    }
32
33    /// Convert a pinned [`AliasableString`] to a `core::ptr::Unique` backed pinned
34    /// [`UniqueString`].
35    pub fn into_unique_pin(pin: Pin<AliasableString>) -> Pin<UniqueString> {
36        // SAFETY: The pointer is not changed, just the container.
37        unsafe {
38            let aliasable = Pin::into_inner_unchecked(pin);
39            Pin::new_unchecked(AliasableString::into_unique(aliasable))
40        }
41    }
42
43    /// Convert a pinned `core::ptr::Unique` backed [`UniqueString`] to a
44    /// pinned [`AliasableString`].
45    pub fn from_unique_pin(pin: Pin<UniqueString>) -> Pin<AliasableString> {
46        // SAFETY: The pointer is not changed, just the container.
47        unsafe {
48            let unique = Pin::into_inner_unchecked(pin);
49            Pin::new_unchecked(AliasableString::from(unique))
50        }
51    }
52}
53
54impl From<UniqueString> for AliasableString {
55    #[inline]
56    fn from(s: UniqueString) -> Self {
57        Self::from_unique(s)
58    }
59}
60
61impl From<AliasableString> for UniqueString {
62    #[inline]
63    fn from(s: AliasableString) -> Self {
64        AliasableString::into_unique(s)
65    }
66}
67
68impl Deref for AliasableString {
69    type Target = str;
70
71    #[inline]
72    fn deref(&self) -> &str {
73        // SAFETY: `AliasableString` will only ever contain UTF-8.
74        unsafe { str::from_utf8_unchecked(&*self.0) }
75    }
76}
77
78impl DerefMut for AliasableString {
79    #[inline]
80    fn deref_mut(&mut self) -> &mut str {
81        // SAFETY: `AliasableString` will only ever contain UTF-8.
82        unsafe { str::from_utf8_unchecked_mut(&mut *self.0) }
83    }
84}
85
86impl AsRef<str> for AliasableString {
87    #[inline]
88    fn as_ref(&self) -> &str {
89        &*self
90    }
91}
92
93impl AsMut<str> for AliasableString {
94    fn as_mut(&mut self) -> &mut str {
95        &mut *self
96    }
97}
98
99impl fmt::Debug for AliasableString {
100    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101        fmt::Debug::fmt(self.as_ref(), f)
102    }
103}
104
105#[cfg(feature = "traits")]
106unsafe impl crate::StableDeref for AliasableString {}
107
108#[cfg(feature = "traits")]
109unsafe impl crate::AliasableDeref for AliasableString {}
110
111#[cfg(test)]
112mod tests {
113    use super::{AliasableString, AliasableVec, UniqueString};
114    use alloc::{format, vec};
115    use core::pin::Pin;
116
117    #[test]
118    fn test_new() {
119        let aliasable = AliasableString::from_unique(UniqueString::from("hello"));
120        assert_eq!(&*aliasable, &"hello"[..]);
121        let unique = AliasableString::into_unique(aliasable);
122        assert_eq!(&*unique, &"hello"[..]);
123    }
124
125    #[test]
126    fn test_new_pin() {
127        let aliasable = AliasableString::from_unique_pin(Pin::new(UniqueString::from("hello")));
128        assert_eq!(&*aliasable, &"hello"[..]);
129        let unique = AliasableString::into_unique_pin(aliasable);
130        assert_eq!(&*unique, &"hello"[..]);
131    }
132
133    #[test]
134    fn test_refs() {
135        let mut aliasable = AliasableString::from_unique(UniqueString::from("hello"));
136        let ptr: *const str = &*aliasable;
137        let as_mut_ptr: *const str = aliasable.as_mut();
138        let as_ref_ptr: *const str = aliasable.as_ref();
139        assert_eq!(ptr, as_mut_ptr);
140        assert_eq!(ptr, as_ref_ptr);
141    }
142
143    #[test]
144    fn test_debug() {
145        let aliasable = AliasableString::from_unique(UniqueString::from("hello"));
146        assert_eq!(format!("{:?}", aliasable), "\"hello\"");
147    }
148
149    #[test]
150    fn test_into_bytes() {
151        let aliasable = AliasableString::from_unique(UniqueString::from("hello"));
152        assert_eq!(
153            AliasableVec::into_unique(aliasable.into_bytes()),
154            vec![b'h', b'e', b'l', b'l', b'o']
155        );
156    }
157}