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