1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//! Aliasable `String`.

use core::ops::{Deref, DerefMut};
use core::pin::Pin;
use core::{fmt, str};

use crate::vec::AliasableVec;

pub use alloc::string::String as UniqueString;

/// Basic aliasable (non `core::ptr::Unique`) alternative to
/// [`alloc::string::String`].
pub struct AliasableString(AliasableVec<u8>);

impl AliasableString {
    /// Consumes `self` into an [`AliasableVec`] of UTF-8 bytes.
    pub fn into_bytes(self) -> AliasableVec<u8> {
        self.0
    }

    /// Construct an `AliasableString` from a [`UniqueString`].
    pub fn from_unique(s: UniqueString) -> Self {
        Self(s.into_bytes().into())
    }

    /// Consumes `self` and converts it into a non-aliasable [`UniqueString`].
    #[inline]
    pub fn into_unique(s: AliasableString) -> UniqueString {
        let unique_bytes = s.into_bytes().into();
        unsafe { UniqueString::from_utf8_unchecked(unique_bytes) }
    }

    /// Convert a pinned [`AliasableString`] to a `core::ptr::Unique` backed pinned
    /// [`UniqueString`].
    pub fn into_unique_pin(pin: Pin<AliasableString>) -> Pin<UniqueString> {
        // SAFETY: The pointer is not changed, just the container.
        unsafe {
            let aliasable = Pin::into_inner_unchecked(pin);
            Pin::new_unchecked(AliasableString::into_unique(aliasable))
        }
    }

    /// Convert a pinned `core::ptr::Unique` backed [`UniqueString`] to a
    /// pinned [`AliasableString`].
    pub fn from_unique_pin(pin: Pin<UniqueString>) -> Pin<AliasableString> {
        // SAFETY: The pointer is not changed, just the container.
        unsafe {
            let unique = Pin::into_inner_unchecked(pin);
            Pin::new_unchecked(AliasableString::from(unique))
        }
    }
}

impl From<UniqueString> for AliasableString {
    #[inline]
    fn from(s: UniqueString) -> Self {
        Self::from_unique(s)
    }
}

impl From<AliasableString> for UniqueString {
    #[inline]
    fn from(s: AliasableString) -> Self {
        AliasableString::into_unique(s)
    }
}

impl Deref for AliasableString {
    type Target = str;

    #[inline]
    fn deref(&self) -> &str {
        // SAFETY: `AliasableString` will only ever contain UTF-8.
        unsafe { str::from_utf8_unchecked(&*self.0) }
    }
}

impl DerefMut for AliasableString {
    #[inline]
    fn deref_mut(&mut self) -> &mut str {
        // SAFETY: `AliasableString` will only ever contain UTF-8.
        unsafe { str::from_utf8_unchecked_mut(&mut *self.0) }
    }
}

impl AsRef<str> for AliasableString {
    #[inline]
    fn as_ref(&self) -> &str {
        &*self
    }
}

impl AsMut<str> for AliasableString {
    fn as_mut(&mut self) -> &mut str {
        &mut *self
    }
}

impl fmt::Debug for AliasableString {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Debug::fmt(self.as_ref(), f)
    }
}

#[cfg(feature = "traits")]
unsafe impl crate::StableDeref for AliasableString {}

#[cfg(feature = "traits")]
unsafe impl crate::AliasableDeref for AliasableString {}

#[cfg(test)]
mod tests {
    use super::{AliasableString, AliasableVec, UniqueString};
    use alloc::{format, vec};
    use core::pin::Pin;

    #[test]
    fn test_new() {
        let aliasable = AliasableString::from_unique(UniqueString::from("hello"));
        assert_eq!(&*aliasable, &"hello"[..]);
        let unique = AliasableString::into_unique(aliasable);
        assert_eq!(&*unique, &"hello"[..]);
    }

    #[test]
    fn test_new_pin() {
        let aliasable = AliasableString::from_unique_pin(Pin::new(UniqueString::from("hello")));
        assert_eq!(&*aliasable, &"hello"[..]);
        let unique = AliasableString::into_unique_pin(aliasable);
        assert_eq!(&*unique, &"hello"[..]);
    }

    #[test]
    fn test_refs() {
        let mut aliasable = AliasableString::from_unique(UniqueString::from("hello"));
        let ptr: *const str = &*aliasable;
        let as_mut_ptr: *const str = aliasable.as_mut();
        let as_ref_ptr: *const str = aliasable.as_ref();
        assert_eq!(ptr, as_mut_ptr);
        assert_eq!(ptr, as_ref_ptr);
    }

    #[test]
    fn test_debug() {
        let aliasable = AliasableString::from_unique(UniqueString::from("hello"));
        assert_eq!(format!("{:?}", aliasable), "\"hello\"");
    }

    #[test]
    fn test_into_bytes() {
        let aliasable = AliasableString::from_unique(UniqueString::from("hello"));
        assert_eq!(
            AliasableVec::into_unique(aliasable.into_bytes()),
            vec![b'h', b'e', b'l', b'l', b'o']
        );
    }
}