embedded_ffi/
inner.rs

1//! The underlying OsString/OsStr implementation on Unix and many other
2//! systems: just a `Vec<u8>`/`[u8]`.
3#[cfg(feature = "alloc")]
4use alloc::borrow::Cow;
5#[cfg(feature = "alloc")]
6use alloc::boxed::Box;
7#[cfg(feature = "alloc")]
8use alloc::rc::Rc;
9#[cfg(feature = "alloc")]
10use alloc::string::String;
11#[cfg(feature = "alloc")]
12use core::mem;
13#[cfg(feature = "alloc")]
14use alloc::sync::Arc;
15use core::fmt;
16use core::str;
17
18use crate::lossy::Utf8Lossy;
19use crate::os_str::OsStr;
20use crate::sys_common::AsInner;
21use crate::sys_common::bytestring::debug_fmt_bytestring;
22
23pub(crate) struct Slice {
24	pub inner: [u8],
25}
26
27impl fmt::Debug for Slice {
28	fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
29		debug_fmt_bytestring(&self.inner, formatter)
30	}
31}
32
33impl fmt::Display for Slice {
34	fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
35		fmt::Display::fmt(&Utf8Lossy::from_bytes(&self.inner), formatter)
36	}
37}
38
39#[cfg(feature = "alloc")]
40pub mod inner_alloc {
41	use alloc::boxed::Box;
42	use alloc::rc::Rc;
43	use alloc::string::String;
44	use alloc::sync::Arc;
45	use alloc::vec::Vec;
46	use core::fmt;
47	use core::mem;
48
49	use crate::os_str::OsString;
50	use crate::sys_common::{AsInner, FromInner, IntoInner};
51
52	use super::Slice;
53
54	#[derive(Clone, Hash)]
55	pub(crate) struct Buf {
56		pub inner: Vec<u8>,
57	}
58
59	impl fmt::Debug for Buf {
60		fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
61			fmt::Debug::fmt(self.as_slice(), formatter)
62		}
63	}
64
65	impl fmt::Display for Buf {
66		fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
67			fmt::Display::fmt(self.as_slice(), formatter)
68		}
69	}
70
71	impl IntoInner<Vec<u8>> for Buf {
72		fn into_inner(self) -> Vec<u8> {
73			self.inner
74		}
75	}
76
77	impl AsInner<[u8]> for Buf {
78		fn as_inner(&self) -> &[u8] {
79			&self.inner
80		}
81	}
82
83	impl Buf {
84		pub fn from_string(s: String) -> Buf {
85			Buf {
86				inner: s.into_bytes(),
87			}
88		}
89
90		#[inline]
91		pub fn with_capacity(capacity: usize) -> Buf {
92			Buf {
93				inner: Vec::with_capacity(capacity),
94			}
95		}
96
97		#[inline]
98		pub fn clear(&mut self) {
99			self.inner.clear()
100		}
101
102		#[inline]
103		pub fn capacity(&self) -> usize {
104			self.inner.capacity()
105		}
106
107		#[inline]
108		pub fn reserve(&mut self, additional: usize) {
109			self.inner.reserve(additional)
110		}
111
112		#[inline]
113		pub fn reserve_exact(&mut self, additional: usize) {
114			self.inner.reserve_exact(additional)
115		}
116
117		#[inline]
118		pub fn shrink_to_fit(&mut self) {
119			self.inner.shrink_to_fit()
120		}
121
122//		#[inline]
123//		pub fn shrink_to(&mut self, min_capacity: usize) {
124//			self.inner.shrink_to(min_capacity)
125//		}
126
127		pub fn as_slice(&self) -> &Slice {
128			unsafe { &*(&*self.inner as *const [u8] as *const _) }
129		}
130
131		pub fn into_string(self) -> Result<String, Buf> {
132			String::from_utf8(self.inner).map_err(|p| Buf {
133				inner: p.into_bytes(),
134			})
135		}
136
137		pub fn push_slice(&mut self, s: &Slice) {
138			self.inner.extend_from_slice(&s.inner)
139		}
140
141		#[inline]
142		pub fn into_box(self) -> Box<Slice> {
143			unsafe { mem::transmute(self.inner.into_boxed_slice()) }
144		}
145
146		#[inline]
147		pub fn from_box(boxed: Box<Slice>) -> Buf {
148			let inner: Box<[u8]> = unsafe { mem::transmute(boxed) };
149			Buf {
150				inner: inner.into_vec(),
151			}
152		}
153
154		#[inline]
155		pub fn into_arc(&self) -> Arc<Slice> {
156			self.as_slice().into_arc()
157		}
158
159		#[inline]
160		pub fn into_rc(&self) -> Rc<Slice> {
161			self.as_slice().into_rc()
162		}
163	}
164
165	/// Platform-specific extensions to [`OsString`].
166	///
167	/// [`OsString`]: ../../../../std/ffi/struct.OsString.html
168	pub trait OsStringExt {
169		/// Creates an [`OsString`] from a byte vector.
170		///
171		/// See the module docmentation for an example.
172		///
173		/// [`OsString`]: ../../../ffi/struct.OsString.html
174		fn from_vec(vec: Vec<u8>) -> Self;
175
176		/// Yields the underlying byte vector of this [`OsString`].
177		///
178		/// See the module docmentation for an example.
179		///
180		/// [`OsString`]: ../../../ffi/struct.OsString.html
181		fn into_vec(self) -> Vec<u8>;
182	}
183
184	impl OsStringExt for OsString {
185		fn from_vec(vec: Vec<u8>) -> OsString {
186			FromInner::from_inner(Buf { inner: vec })
187		}
188		fn into_vec(self) -> Vec<u8> {
189			self.into_inner().inner
190		}
191	}
192}
193
194impl Slice {
195	fn from_u8_slice(s: &[u8]) -> &Slice {
196		unsafe { &*(s as *const [u8] as *const _) }
197	}
198
199	pub fn from_str(s: &str) -> &Slice {
200		Slice::from_u8_slice(s.as_bytes())
201	}
202
203	pub fn to_str(&self) -> Option<&str> {
204		str::from_utf8(&self.inner).ok()
205	}
206
207	#[cfg(feature = "alloc")]
208	pub fn to_string_lossy(&self) -> Cow<'_, str> {
209		String::from_utf8_lossy(&self.inner)
210	}
211
212	#[cfg(feature = "alloc")]
213	pub fn to_owned(&self) -> self::inner_alloc::Buf {
214		self::inner_alloc::Buf {
215			inner: self.inner.to_vec(),
216		}
217	}
218
219	#[cfg(feature = "alloc")]
220	#[inline]
221	pub fn into_box(&self) -> Box<Slice> {
222		let boxed: Box<[u8]> = self.inner.into();
223		unsafe { mem::transmute(boxed) }
224	}
225
226	#[cfg(feature = "alloc")]
227	pub fn empty_box() -> Box<Slice> {
228		let boxed: Box<[u8]> = Default::default();
229		unsafe { mem::transmute(boxed) }
230	}
231
232	#[cfg(feature = "alloc")]
233	#[inline]
234	pub fn into_arc(&self) -> Arc<Slice> {
235		let arc: Arc<[u8]> = Arc::from(&self.inner);
236		unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Slice) }
237	}
238
239	#[cfg(feature = "alloc")]
240	#[inline]
241	pub fn into_rc(&self) -> Rc<Slice> {
242		let rc: Rc<[u8]> = Rc::from(&self.inner);
243		unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) }
244	}
245}
246
247/// Platform-specific extensions to [`OsStr`].
248///
249/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html
250pub trait OsStrExt {
251	/// Creates an [`OsStr`] from a byte slice.
252	///
253	/// See the module docmentation for an example.
254	///
255	/// [`OsStr`]: ../../../ffi/struct.OsStr.html
256	fn from_bytes(slice: &[u8]) -> &Self;
257
258	/// Gets the underlying byte view of the [`OsStr`] slice.
259	///
260	/// See the module docmentation for an example.
261	///
262	/// [`OsStr`]: ../../../ffi/struct.OsStr.html
263	fn as_bytes(&self) -> &[u8];
264}
265
266impl OsStrExt for OsStr {
267	#[inline]
268	fn from_bytes(slice: &[u8]) -> &OsStr {
269		unsafe { &*(slice as *const [u8] as *const _) }
270	}
271	#[inline]
272	fn as_bytes(&self) -> &[u8] {
273		&self.as_inner().inner
274	}
275}