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