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}