1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4 
5 #![allow(unsafe_code)]
6 
7 //! A replacement for `Box<str>` that has a defined layout for FFI.
8 
9 use crate::owned_slice::OwnedSlice;
10 use std::fmt;
11 use std::ops::{Deref, DerefMut};
12 
13 /// A struct that basically replaces a Box<str>, but with a defined layout,
14 /// suitable for FFI.
15 #[repr(C)]
16 #[derive(Clone, Default, Eq, MallocSizeOf, PartialEq, ToShmem)]
17 pub struct OwnedStr(OwnedSlice<u8>);
18 
19 impl fmt::Debug for OwnedStr {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result20     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
21         self.deref().fmt(formatter)
22     }
23 }
24 
25 impl Deref for OwnedStr {
26     type Target = str;
27 
28     #[inline(always)]
deref(&self) -> &Self::Target29     fn deref(&self) -> &Self::Target {
30         unsafe { std::str::from_utf8_unchecked(&*self.0) }
31     }
32 }
33 
34 impl DerefMut for OwnedStr {
35     #[inline(always)]
deref_mut(&mut self) -> &mut Self::Target36     fn deref_mut(&mut self) -> &mut Self::Target {
37         unsafe { std::str::from_utf8_unchecked_mut(&mut *self.0) }
38     }
39 }
40 
41 impl OwnedStr {
42     /// Convert the OwnedStr into a boxed str.
43     #[inline]
into_box(self) -> Box<str>44     pub fn into_box(self) -> Box<str> {
45         self.into_string().into_boxed_str()
46     }
47 
48     /// Convert the OwnedStr into a `String`.
49     #[inline]
into_string(self) -> String50     pub fn into_string(self) -> String {
51         unsafe { String::from_utf8_unchecked(self.0.into_vec()) }
52     }
53 }
54 
55 impl From<OwnedStr> for String {
56     #[inline]
from(b: OwnedStr) -> Self57     fn from(b: OwnedStr) -> Self {
58         b.into_string()
59     }
60 }
61 
62 impl From<OwnedStr> for Box<str> {
63     #[inline]
from(b: OwnedStr) -> Self64     fn from(b: OwnedStr) -> Self {
65         b.into_box()
66     }
67 }
68 
69 impl From<Box<str>> for OwnedStr {
70     #[inline]
from(b: Box<str>) -> Self71     fn from(b: Box<str>) -> Self {
72         Self::from(b.into_string())
73     }
74 }
75 
76 impl From<String> for OwnedStr {
77     #[inline]
from(s: String) -> Self78     fn from(s: String) -> Self {
79         OwnedStr(s.into_bytes().into())
80     }
81 }
82