Thanks to visit codestin.com
Credit goes to docs.rs

uapi/ustr/
ustring.rs

1use crate::{Bstr, Bytes, Result, Ustr};
2use std::{
3    borrow::Borrow,
4    convert::TryFrom,
5    ffi::{CString, OsStr, OsString},
6    fmt,
7    fmt::{Debug, Formatter},
8    mem,
9    mem::MaybeUninit,
10    ops::{Deref, DerefMut},
11    os::unix::ffi::OsStringExt,
12    path::{Path, PathBuf},
13    slice,
14};
15
16/// Thin wrapper for a `Vec<u8>` that has a trailing nul byte
17///
18/// NOTE: `Ustring` derefs to `Ustr` derefs to `Bstr` derefs to `[u8]`.
19/// Rustdoc might not show all available methods.
20///
21/// `Ustring` is optimized so that it can be created without allocating.
22///
23/// See also the crate documentation.
24#[derive(Eq, Ord, PartialOrd, PartialEq, Hash)]
25pub struct Ustring {
26    // invariant: vec is empty or the last element is 0
27    bytes: Vec<u8>,
28}
29
30impl Ustring {
31    /// Creates a new, empty `Ustring`
32    ///
33    /// NOTE: This function does not allocate
34    pub fn new() -> Ustring {
35        Ustring { bytes: Vec::new() }
36    }
37
38    fn init(&mut self) {
39        if self.bytes.is_empty() {
40            self.bytes.push(0);
41        }
42    }
43
44    /// Reserves space for `num` additional bytes in `Ustring`
45    ///
46    /// See `Vec::reserve`
47    pub fn reserve(&mut self, num: usize) {
48        self.init();
49        self.bytes.reserve(num);
50    }
51
52    /// Reserves space for `num` additional bytes in `Ustring`
53    ///
54    /// See `Vec::reserve_exact`
55    pub fn reserve_exact(&mut self, additional: usize) {
56        self.init();
57        self.bytes.reserve_exact(additional);
58    }
59
60    /// Returns the capacity of the underlying Vector excluding the trailing nul byte
61    pub fn capacity(&self) -> usize {
62        if self.bytes.is_empty() {
63            0
64        } else {
65            self.bytes.capacity() - 1
66        }
67    }
68
69    /// Passes the unused portion of the underlying vector to a callback
70    ///
71    /// The size of the slice is `self.capacity() - self.len()`.
72    ///
73    /// The callback should return the number of bytes written to the the slice.
74    /// If the callback returns an error, the `Ustring` is guaranteed to be unchanged.
75    ///
76    /// # Safety
77    ///
78    /// - `f` must not read from the slice
79    /// - `f` must initialize the slice up to (excluding) the returned index
80    pub unsafe fn with_unused<F>(&mut self, f: F) -> Result<usize>
81    where
82        F: FnOnce(&mut [MaybeUninit<u8>]) -> Result<usize>,
83    {
84        let mut s = mem::replace(self, Ustring::new());
85        s.init();
86
87        let res = {
88            let bytes = slice::from_raw_parts_mut(
89                s.bytes.as_mut_ptr().add(s.bytes.len() - 1) as *mut _,
90                s.bytes.capacity() - s.bytes.len() + 1,
91            );
92            let len = bytes.len();
93            let res = f(&mut bytes[..len - 1]);
94            match res {
95                Ok(num) => {
96                    bytes[num] = MaybeUninit::new(0);
97                    s.bytes.set_len(s.bytes.len() + num);
98                }
99                _ => bytes[0] = MaybeUninit::new(0),
100            }
101            res
102        };
103
104        *self = s;
105        res
106    }
107
108    /// Turns `s` into an `Ustring` by appending a nul byte.
109    pub fn from_vec(mut s: Vec<u8>) -> Self {
110        if !s.is_empty() {
111            s.push(0);
112        }
113        Ustring { bytes: s }
114    }
115
116    /// Transmutes the argument into `Ustring`
117    ///
118    /// # Safety
119    ///
120    /// `s` must be empty or contain a trailing nul byte
121    pub unsafe fn from_vec_with_nul_unchecked(s: Vec<u8>) -> Self {
122        Ustring { bytes: s }
123    }
124
125    /// Checks that `s` is empty or has a trailing nul byte and then turns it into an `Ustring`
126    pub fn from_vec_with_nul(s: Vec<u8>) -> std::result::Result<Self, Vec<u8>> {
127        if !s.is_empty() && s[s.len() - 1] != 0 {
128            return Err(s);
129        }
130        Ok(Ustring { bytes: s })
131    }
132
133    /// Returns the underlying `Vec<u8>` after removing the trailing nul byte
134    pub fn into_vec(mut self) -> Vec<u8> {
135        if !self.bytes.is_empty() {
136            self.bytes.pop();
137        }
138        self.bytes
139    }
140
141    /// Returns the underlying `Vec<u8>` without removing the trailing nul byte
142    pub fn into_vec_with_nul(mut self) -> Vec<u8> {
143        self.init();
144        self.bytes
145    }
146
147    /// Shortcut for `Ustring::from_vec(s.into_bytes())`
148    pub fn from_string(s: String) -> Self {
149        Self::from_vec(s.into_bytes())
150    }
151
152    /// Shortcut for `Ustring::from_vec_with_nul(s.into_bytes())`
153    pub fn from_string_with_nul(s: String) -> std::result::Result<Self, String> {
154        if !s.is_empty() && s.as_bytes()[s.len() - 1] != 0 {
155            return Err(s);
156        }
157        Ok(unsafe { Self::from_vec_with_nul_unchecked(s.into_bytes()) })
158    }
159
160    /// Tries to turn `self` into a `String` after removing the trailing nul byte
161    pub fn into_string(self) -> std::result::Result<String, Self> {
162        String::from_utf8(self.into_vec()).map_err(|e| Self::from_vec(e.into_bytes()))
163    }
164
165    /// Tries to turn `self` into a `String` without removing the trailing nul byte
166    pub fn into_string_with_nul(self) -> std::result::Result<String, Self> {
167        String::from_utf8(self.into_vec_with_nul())
168            .map_err(|e| Self::from_vec(e.into_bytes()))
169    }
170
171    /// Shortcut for `Ustring::from_vec(s.into_bytes())`
172    pub fn from_c_string(s: CString) -> Self {
173        Self::from_vec(s.into_bytes())
174    }
175
176    /// Tries to turn `self` into a `CString`
177    ///
178    /// On error, the `usize` is the index of the first interior nul byte.
179    pub fn into_c_string(self) -> std::result::Result<CString, (usize, Self)> {
180        CString::new(self.into_vec())
181            .map_err(|e| (e.nul_position(), Self::from_vec(e.into_vec())))
182    }
183
184    /// Shortcut for `Ustring::from_vec(s.into_vec())`
185    pub fn from_os_string(s: OsString) -> Self {
186        Self::from_vec(s.into_vec())
187    }
188
189    /// Shortcut for `Ustring::from_vec_with_nul(s.into_vec())`
190    pub fn from_os_string_with_nul(s: OsString) -> std::result::Result<Self, OsString> {
191        Self::from_vec_with_nul(s.into_vec()).map_err(OsString::from_vec)
192    }
193
194    /// Shortcut for `OsString::from_vec(self.into_vec())`
195    pub fn into_os_string(self) -> OsString {
196        OsString::from_vec(self.into_vec())
197    }
198
199    /// Shortcut for `OsString::from_vec(self.into_vec_with_nul())`
200    pub fn into_os_string_with_nul(self) -> OsString {
201        OsString::from_vec(self.into_vec_with_nul())
202    }
203
204    /// Shortcut for `Ustring::from_os_string(s.into_os_string())`
205    pub fn from_path_buf(s: PathBuf) -> Self {
206        Self::from_os_string(s.into_os_string())
207    }
208
209    /// Shortcut for `Ustring::from_os_string_with_nul(s.into_os_string())`
210    pub fn from_path_buf_with_nul(s: PathBuf) -> std::result::Result<Self, PathBuf> {
211        Self::from_os_string_with_nul(s.into_os_string()).map_err(PathBuf::from)
212    }
213
214    /// Shortcut for `PathBuf::from(self.into_os_string())`
215    pub fn into_path_buf(self) -> PathBuf {
216        PathBuf::from(self.into_os_string())
217    }
218
219    /// Shortcut for `PathBuf::from(self.into_os_string_with_nul())`
220    pub fn into_path_buf_with_nul(self) -> PathBuf {
221        PathBuf::from(self.into_os_string_with_nul())
222    }
223
224    /// Appends the bytes
225    ///
226    /// For example:
227    ///
228    /// ```
229    /// # use uapi::format_ustr;
230    /// let mut s = format_ustr!("hello ");
231    /// s.push("world");
232    /// assert_eq!("hello world", &s);
233    /// ```
234    pub fn push<T: Bytes + ?Sized>(&mut self, bytes: &T) {
235        let bytes = bytes.bytes();
236        if !bytes.is_empty() {
237            self.init();
238            self.bytes.reserve(bytes.len());
239            self.bytes.pop();
240            self.bytes.extend_from_slice(bytes);
241            self.bytes.push(0);
242        }
243    }
244
245    /// Returns `self` as a `&Ustr`
246    pub fn as_ustr(&self) -> &Ustr {
247        if self.bytes.is_empty() {
248            Ustr::empty()
249        } else {
250            unsafe { Ustr::from_bytes_unchecked(&self.bytes) }
251        }
252    }
253
254    /// Returns `self` as a `&mut Ustr`
255    pub fn as_ustr_mut(&mut self) -> &mut Ustr {
256        self.init();
257        unsafe { Ustr::from_bytes_unchecked_mut(&mut self.bytes) }
258    }
259}
260
261impl Default for Ustring {
262    fn default() -> Self {
263        Self::new()
264    }
265}
266
267impl Borrow<Ustr> for Ustring {
268    fn borrow(&self) -> &Ustr {
269        self.as_ustr()
270    }
271}
272
273impl Borrow<Bstr> for Ustring {
274    fn borrow(&self) -> &Bstr {
275        self.as_ustr().as_bstr()
276    }
277}
278
279impl From<String> for Ustring {
280    fn from(s: String) -> Self {
281        Ustring::from_string(s)
282    }
283}
284
285impl From<Vec<u8>> for Ustring {
286    fn from(s: Vec<u8>) -> Self {
287        Ustring::from_vec(s)
288    }
289}
290
291impl From<CString> for Ustring {
292    fn from(s: CString) -> Self {
293        Ustring::from_c_string(s)
294    }
295}
296
297impl From<OsString> for Ustring {
298    fn from(s: OsString) -> Self {
299        Ustring::from_os_string(s)
300    }
301}
302
303impl From<PathBuf> for Ustring {
304    fn from(s: PathBuf) -> Self {
305        Ustring::from_path_buf(s)
306    }
307}
308
309impl TryFrom<Ustring> for String {
310    type Error = Ustring;
311
312    fn try_from(value: Ustring) -> std::result::Result<Self, Self::Error> {
313        Ustring::into_string(value)
314    }
315}
316
317impl From<Ustring> for Vec<u8> {
318    fn from(s: Ustring) -> Self {
319        s.into_vec()
320    }
321}
322
323impl TryFrom<Ustring> for CString {
324    type Error = (usize, Ustring);
325
326    fn try_from(s: Ustring) -> std::result::Result<Self, Self::Error> {
327        s.into_c_string()
328    }
329}
330
331impl From<Ustring> for OsString {
332    fn from(s: Ustring) -> Self {
333        s.into_os_string()
334    }
335}
336
337impl From<Ustring> for PathBuf {
338    fn from(s: Ustring) -> Self {
339        s.into_path_buf()
340    }
341}
342
343impl AsRef<[u8]> for Ustring {
344    fn as_ref(&self) -> &[u8] {
345        self.deref().as_ref()
346    }
347}
348
349impl AsMut<[u8]> for Ustring {
350    fn as_mut(&mut self) -> &mut [u8] {
351        self.deref_mut().as_mut()
352    }
353}
354
355impl AsRef<OsStr> for Ustring {
356    fn as_ref(&self) -> &OsStr {
357        self.deref().as_ref()
358    }
359}
360
361impl AsRef<Path> for Ustring {
362    fn as_ref(&self) -> &Path {
363        self.deref().as_ref()
364    }
365}
366
367impl Deref for Ustring {
368    type Target = Ustr;
369
370    fn deref(&self) -> &Self::Target {
371        self.as_ustr()
372    }
373}
374
375impl DerefMut for Ustring {
376    fn deref_mut(&mut self) -> &mut Self::Target {
377        self.as_ustr_mut()
378    }
379}
380
381impl Debug for Ustring {
382    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
383        Debug::fmt(self.deref(), f)
384    }
385}