abi_stable/std_types/str.rs
1//! Contains an ffi-safe equivalent of `&'a str`.
2
3use std::{
4 borrow::{Borrow, Cow},
5 fmt::{self, Display},
6 ops::{Deref, Index},
7 str,
8};
9
10#[allow(unused_imports)]
11use core_extensions::SelfOps;
12
13use serde::{Deserialize, Deserializer, Serialize, Serializer};
14
15use crate::std_types::{RSlice, RString};
16
17/// Ffi-safe equivalent of `&'a str`
18///
19/// # Example
20///
21/// This defines a function that returns the first word in a string.
22///
23/// ```
24/// use abi_stable::{sabi_extern_fn, std_types::RStr};
25///
26/// #[sabi_extern_fn]
27/// fn first_word(phrase: RStr<'_>) -> RStr<'_> {
28/// match phrase.as_str().split_whitespace().next() {
29/// Some(x) => x.into(),
30/// None => "".into(),
31/// }
32/// }
33///
34///
35/// ```
36#[repr(C)]
37#[derive(Copy, Clone, StableAbi)]
38pub struct RStr<'a> {
39 inner: RSlice<'a, u8>,
40}
41
42impl<'a> RStr<'a> {
43 /// An empty `RStr`.
44 pub const EMPTY: Self = RStr {
45 inner: RSlice::EMPTY,
46 };
47}
48
49impl<'a> RStr<'a> {
50 /// Constructs an empty `RStr<'a>`.
51 ///
52 /// # Example
53 ///
54 /// ```
55 /// use abi_stable::std_types::RStr;
56 ///
57 /// const STR: RStr<'static> = RStr::empty();
58 ///
59 /// assert_eq!(STR, RStr::from(""));
60 ///
61 /// ```
62 #[inline]
63 pub const fn empty() -> Self {
64 Self::EMPTY
65 }
66
67 /// Constructs an `RStr<'a>` from a pointer to the first byte,
68 /// and a length.
69 ///
70 /// # Safety
71 ///
72 /// Callers must ensure that:
73 ///
74 /// - `ptr_` points to valid memory,
75 ///
76 /// - `ptr_ .. ptr+len` range is accessible memory, and is valid utf-8.
77 ///
78 /// - The data that `ptr_` points to must be valid for the lifetime of this `RStr<'a>`
79 ///
80 /// # Examples
81 ///
82 /// This function unsafely converts a `&str` to an `RStr<'_>`,
83 /// equivalent to doing `RStr::from`.
84 ///
85 /// ```
86 /// use abi_stable::std_types::RStr;
87 ///
88 /// fn convert(slice_: &str) -> RStr<'_> {
89 /// unsafe { RStr::from_raw_parts(slice_.as_ptr(), slice_.len()) }
90 /// }
91 ///
92 /// ```
93 #[inline]
94 pub const unsafe fn from_raw_parts(ptr_: *const u8, len: usize) -> Self {
95 Self {
96 inner: unsafe { RSlice::from_raw_parts(ptr_, len) },
97 }
98 }
99
100 /// Converts `&'a str` to a `RStr<'a>`.
101 ///
102 /// # Example
103 ///
104 /// ```
105 /// use abi_stable::std_types::RStr;
106 ///
107 /// assert_eq!(RStr::from_str("").as_str(), "");
108 /// assert_eq!(RStr::from_str("Hello").as_str(), "Hello");
109 /// assert_eq!(RStr::from_str("World").as_str(), "World");
110 ///
111 /// ```
112 pub const fn from_str(s: &'a str) -> Self {
113 unsafe { Self::from_raw_parts(s.as_ptr(), s.len()) }
114 }
115
116 /// For slicing `RStr`s.
117 ///
118 /// This is an inherent method instead of an implementation of the
119 /// `std::ops::Index` trait because it does not return a reference.
120 ///
121 /// # Example
122 ///
123 /// ```
124 /// use abi_stable::std_types::RStr;
125 ///
126 /// let str = RStr::from("What is that.");
127 ///
128 /// assert_eq!(str.slice(..), str);
129 /// assert_eq!(str.slice(..4), RStr::from("What"));
130 /// assert_eq!(str.slice(4..), RStr::from(" is that."));
131 /// assert_eq!(str.slice(4..7), RStr::from(" is"));
132 ///
133 /// ```
134 pub fn slice<I>(&self, i: I) -> RStr<'a>
135 where
136 str: Index<I, Output = str>,
137 {
138 self.as_str().index(i).into()
139 }
140
141 /// Accesses the underlying byte slice.
142 ///
143 /// # Example
144 ///
145 /// ```
146 /// use abi_stable::std_types::{RSlice, RStr};
147 ///
148 /// let str = RStr::from("What is that.");
149 /// let bytes = RSlice::from("What is that.".as_bytes());
150 ///
151 /// assert_eq!(str.as_rslice(), bytes);
152 ///
153 /// ```
154 #[inline]
155 pub const fn as_rslice(&self) -> RSlice<'a, u8> {
156 self.inner
157 }
158
159 conditionally_const! {
160 feature = "rust_1_64"
161 /// Casts this `RStr<'a>` to a `&'a str`.
162 ///
163 ;
164 ///
165 /// # Example
166 ///
167 /// ```
168 /// use abi_stable::std_types::RStr;
169 ///
170 /// let str = "What is that.";
171 /// assert_eq!(RStr::from(str).as_str(), str);
172 ///
173 /// ```
174 #[inline]
175 pub fn as_str(&self) -> &'a str {
176 unsafe { str::from_utf8_unchecked(self.inner.as_slice()) }
177 }
178 }
179
180 /// Gets a raw pointer to the start of the string slice.
181 pub const fn as_ptr(&self) -> *const u8 {
182 self.inner.as_ptr()
183 }
184
185 /// Gets the length(in bytes) of this `RStr<'a>`.
186 ///
187 /// # Example
188 ///
189 /// ```
190 /// use abi_stable::std_types::RStr;
191 ///
192 /// assert_eq!(RStr::from("").len(), 0);
193 /// assert_eq!(RStr::from("a").len(), 1);
194 /// assert_eq!(RStr::from("What").len(), 4);
195 ///
196 /// ```
197 #[inline]
198 pub const fn len(&self) -> usize {
199 self.inner.len()
200 }
201
202 /// Queries whether this RStr is empty.
203 ///
204 /// # Example
205 ///
206 /// ```
207 /// use abi_stable::std_types::RStr;
208 ///
209 /// assert_eq!(RStr::from("").is_empty(), true);
210 /// assert_eq!(RStr::from("a").is_empty(), false);
211 /// assert_eq!(RStr::from("What").is_empty(), false);
212 ///
213 /// ```
214 pub const fn is_empty(&self) -> bool {
215 self.inner.is_empty()
216 }
217}
218
219unsafe impl<'a> Send for RStr<'a> {}
220unsafe impl<'a> Sync for RStr<'a> {}
221
222impl<'a> Default for RStr<'a> {
223 fn default() -> Self {
224 Self::EMPTY
225 }
226}
227
228impl<'a> Deref for RStr<'a> {
229 type Target = str;
230
231 #[inline]
232 fn deref(&self) -> &Self::Target {
233 self.as_str()
234 }
235}
236
237deref_coerced_impl_cmp_traits! {
238 RStr<'_>;
239 coerce_to = str,
240 [
241 String,
242 str,
243 &str,
244 std::borrow::Cow<'_, str>,
245 crate::std_types::RCowStr<'_>,
246 ]
247}
248
249////////////////////////////////
250
251impl<'a> From<RStr<'a>> for Cow<'a, str> {
252 fn from(this: RStr<'a>) -> Cow<'a, str> {
253 this.as_str().into()
254 }
255}
256
257impl_into_rust_repr! {
258 impl['a] Into<&'a str> for RStr<'a> {
259 fn(this){
260 this.as_str()
261 }
262 }
263}
264
265impl From<RStr<'_>> for String {
266 fn from(this: RStr<'_>) -> String {
267 this.as_str().into()
268 }
269}
270
271impl From<RStr<'_>> for RString {
272 fn from(this: RStr<'_>) -> RString {
273 this.as_str().into()
274 }
275}
276
277impl_from_rust_repr! {
278 impl['a] From<&'a str> for RStr<'a> {
279 fn(this){
280 RStr {
281 inner: this.as_bytes().into(),
282 }
283 }
284 }
285}
286
287////////////////////////////////
288
289impl<'a> Borrow<str> for RStr<'a> {
290 fn borrow(&self) -> &str {
291 self
292 }
293}
294
295impl AsRef<str> for RStr<'_> {
296 fn as_ref(&self) -> &str {
297 self
298 }
299}
300
301impl AsRef<[u8]> for RStr<'_> {
302 fn as_ref(&self) -> &[u8] {
303 self.as_bytes()
304 }
305}
306
307////////////////////////////////
308
309impl Display for RStr<'_> {
310 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
311 Display::fmt(self.as_str(), f)
312 }
313}
314
315impl<'de> Deserialize<'de> for RStr<'de> {
316 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
317 where
318 D: Deserializer<'de>,
319 {
320 <&'de str as Deserialize<'de>>::deserialize(deserializer).map(Self::from)
321 }
322}
323
324impl<'a> Serialize for RStr<'a> {
325 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
326 where
327 S: Serializer,
328 {
329 self.as_str().serialize(serializer)
330 }
331}
332
333#[allow(dead_code)]
334type Str<'a> = &'a str;
335
336shared_impls! {
337 mod = slice_impls
338 new_type = RStr['a][],
339 original_type = Str,
340}
341
342////////////////////////////////////////////////////
343
344//#[cfg(test)]
345#[cfg(all(test, not(feature = "only_new_tests")))]
346mod test {
347 use super::*;
348
349 #[test]
350 fn from_to_str() {
351 const RS: RStr<'_> = RStr::from_str("foo bar");
352
353 let string = "what the hell";
354 let rstr = RStr::from_str(string);
355
356 assert_eq!(rstr, string);
357 assert_eq!(RS, "foo bar");
358 }
359
360 #[cfg(feature = "rust_1_64")]
361 #[test]
362 fn const_as_str() {
363 const RS: RStr<'_> = RStr::from_str("Hello, world!");
364 const S: &str = RS.as_str();
365
366 assert_eq!(S, "Hello, world!");
367 }
368}