1#![feature(str_from_raw_parts)]
9
10#![warn(missing_docs)]
11
12
13
14use std::{fmt::{self, Display, Formatter}, ops::Deref};
15
16
17
18#[derive(Copy, Clone)]
33#[repr(C)]
34pub struct FFIStr<'a> {
35 ptr: &'a u8,
36 len: u32,
37}
38
39impl<'a> FFIStr<'a> {
40 pub fn new(from: &'a str) -> Self {
42 unsafe {
43 Self {
44 ptr: &*from.as_ptr(),
45 len: from.len() as u32,
46 }
47 }
48 }
49 pub fn as_str(&self) -> &'a str {
53 unsafe {
54 core::str::from_raw_parts(self.ptr, self.len as usize)
55 }
56 }
57}
58
59impl Deref for FFIStr<'_> {
60 type Target = str;
61 fn deref(&self) -> &Self::Target {
62 self.as_str()
63 }
64}
65
66impl fmt::Debug for FFIStr<'_> {
67 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
68 write!(f, "\"{}\"", self.as_str())
69 }
70}
71
72impl Display for FFIStr<'_> {
73 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
74 write!(f, "{}", self.as_str())
75 }
76}
77
78impl<'a> From<&'a str> for FFIStr<'a> {
79 fn from(value: &'a str) -> Self {
80 Self::new(value)
81 }
82}
83
84impl<'a> AsRef<str> for FFIStr<'a> {
85 fn as_ref(&self) -> &str {
86 self.as_str()
87 }
88}
89
90impl Into<String> for FFIStr<'_> {
91 fn into(self) -> String {
92 self.to_string()
93 }
94}
95
96pub trait StrToFFI {
98 fn to_ffi_str<'a>(&'a self) -> FFIStr<'a>;
100 fn to_ffi_string(&self) -> FFIString;
102}
103
104impl StrToFFI for str {
105 fn to_ffi_str<'a>(&'a self) -> FFIStr<'a> {
106 FFIStr::new(self)
107 }
108 fn to_ffi_string(&self) -> FFIString {
109 FFIString::new(self)
110 }
111}
112
113
114
115#[repr(C)]
131pub struct FFIString {
132 ptr: *mut u8,
133 len: u32,
134 cap: u32,
135}
136
137impl FFIString {
138 pub fn new(from: impl Into<String>) -> Self {
140 let mut from = from.into();
141 let output = Self {
142 ptr: from.as_mut_ptr(),
143 len: from.len() as u32,
144 cap: from.capacity() as u32,
145 };
146 std::mem::forget(from);
147 output
148 }
149 pub fn into_string(self) -> String {
153 unsafe {
154 let output = String::from_raw_parts(self.ptr, self.len as usize, self.cap as usize);
155 std::mem::forget(self);
156 output
157 }
158 }
159 pub fn as_str(&self) -> &str {
161 unsafe {
162 core::str::from_raw_parts(self.ptr, self.len as usize)
163 }
164 }
165}
166
167impl Drop for FFIString {
168 fn drop(&mut self) {
169 unsafe {
170 String::from_raw_parts(self.ptr, self.len as usize, self.cap as usize);
171 }
172 }
173}
174
175impl Deref for FFIString {
176 type Target = str;
177 fn deref(&self) -> &Self::Target {
178 self.as_str()
179 }
180}
181
182impl fmt::Debug for FFIString {
183 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
184 write!(f, "\"{}\"", self.as_str())
185 }
186}
187
188impl Display for FFIString {
189 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
190 write!(f, "{}", self.as_str())
191 }
192}
193
194impl From<String> for FFIString {
195 fn from(value: String) -> Self {
196 Self::new(value)
197 }
198}
199
200impl AsRef<str> for FFIString {
201 fn as_ref(&self) -> &str {
202 self.as_str()
203 }
204}
205
206impl Into<String> for FFIString {
207 fn into(self) -> String {
208 self.to_string()
209 }
210}
211
212impl Clone for FFIString {
213 fn clone(&self) -> Self {
214 Self::new(self.to_string())
215 }
216}
217
218pub trait StringToFFI {
222 fn into_ffi_string(self) -> FFIString;
224}
225
226impl StringToFFI for String {
227 fn into_ffi_string(self) -> FFIString {
228 FFIString::new(self)
229 }
230}