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
#![cfg_attr(rustfmt, rustfmt::skip)]
//! `Rust` string types with a defined `#[repr(C)]` layout, albeit not `char *`
//! compatible (_fat_ pointers).

use_prelude!();

pub use slice::*;
mod slice;

cfg_alloc! {
    use repr_c::Vec;

    ReprC! {
        #[repr(transparent)]
        #[cfg_attr(all(docs, feature = "nightly"), doc(cfg(feature = "alloc")))]
        /// Same as [`String`][`rust::String`], but with guaranteed `#[repr(C)]` layout
        pub
        struct String (
            Vec<u8>,
        );
    }

    /// Convert a [`std::string::String`] to a [`safer_ffi::String`].
    impl From<rust::String>
        for String
    {
        #[inline]
        fn from (s: rust::String) -> String
        {
            Self(rust::Vec::from(s).into())
        }
    }

    /// Convert a [`safer_ffi::String`] to a [`std::string::String`].
    impl From<String> for rust::String
    {
        #[inline]
        fn from(value: String) -> rust::String
        {
            unsafe {
                rust::String::from_utf8_unchecked(
                    value.0.into()
                )
            }
        }
    }

    impl Deref
        for String
    {
        type Target = str;

        fn deref (self: &'_ Self) -> &'_ Self::Target
        {
            unsafe {
                ::core::str::from_utf8_unchecked(&* self.0)
            }
        }
    }

    /// ```rust
    /// use ::safer_ffi::prelude::*;
    ///
    /// let s: repr_c::String = "".into();
    /// assert_eq!(format!("{s:?}"), "\"\"");
    /// ```
    impl fmt::Debug
        for String
    {
        fn fmt (self: &'_ Self, fmt: &'_ mut fmt::Formatter<'_>)
          -> fmt::Result
        {
            str::fmt(self, fmt)
        }
    }

    /// ```rust
    /// use ::safer_ffi::prelude::*;
    ///
    /// let s: repr_c::String = "".into();
    /// assert_eq!(format!("{s}"), "");
    /// ```
    impl fmt::Display
        for String
    {
        fn fmt (self: &'_ Self, fmt: &'_ mut fmt::Formatter<'_>)
          -> fmt::Result
        {
            str::fmt(self, fmt)
        }
    }

    impl From<&str> for repr_c::String {
        fn from(s: &str)
          -> repr_c::String
        {
            Self::from(rust::String::from(s))
        }
    }

    impl String {
        pub
        const EMPTY: Self = Self(Vec::EMPTY);

        pub
        fn with_rust_mut<R> (
            self: &'_ mut String,
            f: impl FnOnce(&'_ mut rust::String) -> R,
        ) -> R
        {
            self.0.with_rust_mut(|v: &'_ mut rust::Vec<u8>| {
                let s: &'_ mut rust::String = unsafe { mem::transmute(v) };
                f(s)
            })
        }
    }

    impl Clone for String {
        fn clone (
            self: &'_ Self,
        ) -> Self
        {
            Self(self.0.clone())
        }
    }
}