cesu8str/ngstr/mutf8str.rs
1
2use super::prelude::*;
3
4/// A borrowed MUTF-8 string.
5#[derive(PartialEq, Eq, PartialOrd, Ord)]
6#[repr(transparent)]
7pub struct Mutf8Str {
8 inner: [u8],
9}
10
11impl Mutf8Str {
12 impl_str_encoding_meths!(base, Mutf8Str, any, "MUTF-8");
13 impl_str_encoding_meths!(str, Mutf8Str, any, "MUTF-8");
14}
15
16impl Mutf8Str {
17 /// Determines if this string encoding uses literal nul bytes. If true, then literal nul bytes are not allowed
18 /// within the string's contents.
19 pub const ENCODE_NUL: bool = true;
20 /// Determines if this string maintains a literal nul byte as a terminator. This makes it functionally equilavent
21 /// to a [`CStr`], including any encoding guarantees provided by the string type.
22 ///
23 /// If this is `true`, then [`Self::ENCODE_NUL`] must also be `true`.
24 pub const NUL_TERM: bool = false;
25
26 /// Uses pointer magic to transmute a byte slice to an instance of Mutf8Str
27 ///
28 /// # Safety
29 /// The byte string should be encoded in MUTF8. That is, UTF8 with 4-byte-sequences re-encoded as 2, 3-byte
30 /// sequences, and with nul bytes re-encoded as as [0xC0, 0x80]
31 pub(crate) const unsafe fn _from_bytes_unchecked(bytes: &[u8]) -> &Self {
32 // &[u8]
33 // *const [u8]
34 // *const Mutf8Str
35 // &Mutf8Str
36
37 // should be a no-op
38
39 &*(bytes as *const [u8] as *const Self)
40 }
41
42 pub(crate) const fn _raw_bytes(&self) -> &[u8] {
43 unsafe { &*(self as *const Self as *const [u8]) }
44 }
45}
46
47// don't impl Deref as it can make nul-terminator inclusion ambiguous for Mutf8CStr -> Mutf8Str -> [u8]
48impl ToOwned for Mutf8Str {
49 type Owned = Mutf8String;
50 fn to_owned(&self) -> Self::Owned {
51 // SAFETY: string has already been validated as mutf8
52 unsafe { Self::Owned::from_bytes_unchecked(self.inner.to_vec()) }
53 }
54}
55impl Default for &Mutf8Str {
56 fn default() -> Self {
57 const EMPTY: &[u8] = &[];
58 unsafe { Mutf8Str::from_bytes_unchecked(EMPTY) }
59 }
60}
61