unix_str/
sys.rs

1//! The underlying UnixString/UnixStr implementation: just a `Vec<u8>`/`[u8]`.
2
3use crate::sys_common::bytestring::debug_fmt_bytestring;
4#[cfg(feature = "alloc")]
5use crate::sys_common::{AsInner, IntoInner};
6use core::fmt;
7use core::mem;
8use core::str;
9
10#[cfg(feature = "alloc")]
11use alloc::borrow::Cow;
12#[cfg(feature = "alloc")]
13use alloc::boxed::Box;
14#[cfg(feature = "alloc")]
15use alloc::rc::Rc;
16#[cfg(feature = "alloc")]
17use alloc::string::String;
18#[cfg(feature = "alloc")]
19use alloc::sync::Arc;
20#[cfg(feature = "alloc")]
21use alloc::vec::Vec;
22
23#[cfg(all(feature = "alloc", feature = "toowned_clone_into"))]
24use alloc::borrow::ToOwned;
25
26#[cfg(feature = "alloc")]
27#[derive(Clone, Hash)]
28pub(crate) struct Buf {
29    pub inner: Vec<u8>,
30}
31
32// FIXME:
33// `Buf::as_slice` current implementation relies
34// on `Slice` being layout-compatible with `[u8]`.
35// When attribute privacy is implemented, `Slice` should be annotated as `#[repr(transparent)]`.
36// Anyway, `Slice` representation and layout are considered implementation detail, are
37// not documented and must not be relied upon.
38pub(crate) struct Slice {
39    pub inner: [u8],
40}
41
42impl fmt::Debug for Slice {
43    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
44        debug_fmt_bytestring(&self.inner, formatter)
45    }
46}
47
48#[cfg(feature = "alloc")]
49impl IntoInner<Vec<u8>> for Buf {
50    fn into_inner(self) -> Vec<u8> {
51        self.inner
52    }
53}
54
55#[cfg(feature = "alloc")]
56impl AsInner<[u8]> for Buf {
57    fn as_inner(&self) -> &[u8] {
58        &self.inner
59    }
60}
61
62#[cfg(feature = "alloc")]
63impl Buf {
64    pub fn from_string(s: String) -> Self {
65        Self {
66            inner: s.into_bytes(),
67        }
68    }
69
70    #[inline]
71    pub fn with_capacity(capacity: usize) -> Self {
72        Buf {
73            inner: Vec::with_capacity(capacity),
74        }
75    }
76
77    #[inline]
78    pub fn clear(&mut self) {
79        self.inner.clear()
80    }
81
82    #[inline]
83    pub fn capacity(&self) -> usize {
84        self.inner.capacity()
85    }
86
87    #[inline]
88    pub fn reserve(&mut self, additional: usize) {
89        self.inner.reserve(additional)
90    }
91
92    #[inline]
93    pub fn reserve_exact(&mut self, additional: usize) {
94        self.inner.reserve_exact(additional)
95    }
96
97    #[inline]
98    pub fn shrink_to_fit(&mut self) {
99        self.inner.shrink_to_fit()
100    }
101
102    #[inline]
103    #[cfg(feature = "shrink_to")]
104    pub fn shrink_to(&mut self, min_capacity: usize) {
105        self.inner.shrink_to(min_capacity)
106    }
107
108    #[inline]
109    pub fn as_slice(&self) -> &Slice {
110        // Safety: Slice just wraps [u8],
111        // and &*self.inner is &[u8], therefore
112        // transmuting &[u8] to &Slice is safe.
113        unsafe { mem::transmute(&*self.inner) }
114    }
115
116    #[inline]
117    pub fn as_mut_slice(&mut self) -> &mut Slice {
118        // Safety: Slice just wraps [u8],
119        // and &mut *self.inner is &mut [u8], therefore
120        // transmuting &mut [u8] to &mut Slice is safe.
121        unsafe { mem::transmute(&mut *self.inner) }
122    }
123
124    pub fn into_string(self) -> Result<String, Self> {
125        String::from_utf8(self.inner).map_err(|p| Self {
126            inner: p.into_bytes(),
127        })
128    }
129
130    pub fn push_slice(&mut self, s: &Slice) {
131        self.inner.extend_from_slice(&s.inner)
132    }
133
134    #[inline]
135    pub fn into_box(self) -> Box<Slice> {
136        unsafe { mem::transmute(self.inner.into_boxed_slice()) }
137    }
138
139    #[inline]
140    pub fn from_box(boxed: Box<Slice>) -> Self {
141        let inner: Box<[u8]> = unsafe { mem::transmute(boxed) };
142        Self {
143            inner: inner.into_vec(),
144        }
145    }
146
147    #[inline]
148    pub fn into_arc(&self) -> Arc<Slice> {
149        self.as_slice().into_arc()
150    }
151
152    #[inline]
153    pub fn into_rc(&self) -> Rc<Slice> {
154        self.as_slice().into_rc()
155    }
156}
157
158impl Slice {
159    #[inline]
160    fn from_u8_slice(s: &[u8]) -> &Self {
161        unsafe { mem::transmute(s) }
162    }
163
164    #[inline]
165    pub fn from_str(s: &str) -> &Self {
166        Self::from_u8_slice(s.as_bytes())
167    }
168
169    pub fn to_str(&self) -> Option<&str> {
170        str::from_utf8(&self.inner).ok()
171    }
172
173    #[cfg(feature = "alloc")]
174    pub fn to_string_lossy(&self) -> Cow<'_, str> {
175        String::from_utf8_lossy(&self.inner)
176    }
177
178    #[cfg(feature = "alloc")]
179    pub fn to_owned(&self) -> Buf {
180        Buf {
181            inner: self.inner.to_vec(),
182        }
183    }
184
185    #[cfg(all(feature = "alloc", feature = "toowned_clone_into"))]
186    pub fn clone_into(&self, buf: &mut Buf) {
187        self.inner.clone_into(&mut buf.inner)
188    }
189
190    #[inline]
191    #[cfg(feature = "alloc")]
192    pub fn into_box(&self) -> Box<Self> {
193        let boxed: Box<[u8]> = self.inner.into();
194        unsafe { mem::transmute(boxed) }
195    }
196
197    #[cfg(feature = "alloc")]
198    pub fn empty_box() -> Box<Self> {
199        let boxed: Box<[u8]> = Default::default();
200        unsafe { mem::transmute(boxed) }
201    }
202
203    #[inline]
204    #[cfg(feature = "alloc")]
205    pub fn into_arc(&self) -> Arc<Self> {
206        let arc: Arc<[u8]> = Arc::from(&self.inner);
207        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Self) }
208    }
209
210    #[inline]
211    #[cfg(feature = "alloc")]
212    pub fn into_rc(&self) -> Rc<Self> {
213        let rc: Rc<[u8]> = Rc::from(&self.inner);
214        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Self) }
215    }
216
217    #[inline]
218    #[cfg(feature = "unixstring_ascii")]
219    pub fn make_ascii_lowercase(&mut self) {
220        self.inner.make_ascii_lowercase()
221    }
222
223    #[inline]
224    #[cfg(feature = "unixstring_ascii")]
225    pub fn make_ascii_uppercase(&mut self) {
226        self.inner.make_ascii_uppercase()
227    }
228
229    #[inline]
230    #[cfg(all(feature = "alloc", feature = "unixstring_ascii"))]
231    pub fn to_ascii_lowercase(&self) -> Buf {
232        Buf {
233            inner: self.inner.to_ascii_lowercase(),
234        }
235    }
236
237    #[inline]
238    #[cfg(all(feature = "alloc", feature = "unixstring_ascii"))]
239    pub fn to_ascii_uppercase(&self) -> Buf {
240        Buf {
241            inner: self.inner.to_ascii_uppercase(),
242        }
243    }
244
245    #[inline]
246    #[cfg(feature = "unixstring_ascii")]
247    pub fn is_ascii(&self) -> bool {
248        self.inner.is_ascii()
249    }
250
251    #[inline]
252    #[cfg(feature = "unixstring_ascii")]
253    pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
254        self.inner.eq_ignore_ascii_case(&other.inner)
255    }
256}