blob: 02bd442ad167b78ec58ca9454f44d833f2457bcc [file] [log] [blame]
David Tolnay3eba2012021-04-08 22:20:09 -07001use core::mem::{self, MaybeUninit};
David Tolnay3384c142020-09-14 00:26:47 -04002use core::ptr::NonNull;
David Tolnay3384c142020-09-14 00:26:47 -04003use core::str;
David Tolnay7db73692019-10-20 14:51:12 -04004
David Tolnay3eba2012021-04-08 22:20:09 -07005// ABI compatible with C++ rust::Str (not necessarily &str).
David Tolnay7db73692019-10-20 14:51:12 -04006#[repr(C)]
David Tolnay7db73692019-10-20 14:51:12 -04007pub struct RustStr {
David Tolnay3eba2012021-04-08 22:20:09 -07008 repr: [MaybeUninit<usize>; mem::size_of::<NonNull<str>>() / mem::size_of::<usize>()],
David Tolnay7db73692019-10-20 14:51:12 -04009}
10
11impl RustStr {
David Tolnay1202de52021-01-02 01:26:33 -080012 pub fn from(repr: &str) -> Self {
13 let repr = NonNull::from(repr);
David Tolnay3eba2012021-04-08 22:20:09 -070014 unsafe { mem::transmute::<NonNull<str>, RustStr>(repr) }
David Tolnay7db73692019-10-20 14:51:12 -040015 }
16
17 pub unsafe fn as_str<'a>(self) -> &'a str {
David Tolnay3eba2012021-04-08 22:20:09 -070018 let repr = mem::transmute::<RustStr, NonNull<str>>(self);
19 repr.as_ref()
David Tolnay7db73692019-10-20 14:51:12 -040020 }
21}
22
David Tolnay3eba2012021-04-08 22:20:09 -070023const_assert_eq!(mem::size_of::<NonNull<str>>(), mem::size_of::<RustStr>());
24const_assert_eq!(mem::align_of::<NonNull<str>>(), mem::align_of::<RustStr>());