raw_string/
string.rs

1use std;
2use std::borrow::{Borrow, ToOwned};
3use std::cmp::Ordering;
4use std::ffi::OsString;
5use std::fmt::{Debug, Display, Formatter};
6use std::ops::{Deref, DerefMut, RangeBounds};
7use std::path::PathBuf;
8use std::string::FromUtf8Error;
9use std::vec::Drain;
10use str::RawStr;
11
12/// A `String` with unchecked contents.
13///
14/// It is basically a `Vec<u8>`, to be interpreted as string.
15/// Unlike `String`, there are no guarantees about the contents being valid UTF-8.
16/// Unlike `Vec<u8>`, its Display and Debug implementations show a string, not
17/// an array of numbers.
18#[derive(Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
19pub struct RawString {
20	inner: Vec<u8>,
21}
22
23impl RawString {
24	#[inline]
25	pub fn new() -> Self {
26		RawString { inner: Vec::new() }
27	}
28
29	#[inline]
30	pub fn with_capacity(capacity: usize) -> Self {
31		RawString {
32			inner: Vec::with_capacity(capacity),
33		}
34	}
35
36	#[inline]
37	pub fn from_bytes(bytes: Vec<u8>) -> Self {
38		RawString { inner: bytes }
39	}
40
41	#[inline]
42	pub fn from_string(bytes: String) -> Self {
43		Self::from_bytes(bytes.into_bytes())
44	}
45
46	#[inline]
47	pub fn into_bytes(self) -> Vec<u8> {
48		self.inner
49	}
50
51	#[inline]
52	pub fn capacity(&self) -> usize {
53		self.inner.capacity()
54	}
55
56	#[inline]
57	pub fn reserve(&mut self, additional: usize) {
58		self.inner.reserve(additional)
59	}
60
61	#[inline]
62	pub fn reserve_exact(&mut self, additional: usize) {
63		self.inner.reserve_exact(additional)
64	}
65
66	#[inline]
67	pub fn shrink_to_fit(&mut self) {
68		self.inner.shrink_to_fit()
69	}
70
71	/* Unstable feature:
72	#[inline]
73	pub fn shrink_to(&mut self, min_capacity: usize) {
74		self.inner.shrink_to(min_capacity)
75	}
76	*/
77
78	#[inline]
79	pub fn clear(&mut self) {
80		self.inner.clear()
81	}
82
83	#[inline]
84	pub fn truncate(&mut self, new_len: usize) {
85		self.inner.truncate(new_len)
86	}
87
88	#[inline]
89	pub fn pop(&mut self) -> Option<u8> {
90		self.inner.pop()
91	}
92
93	#[inline]
94	pub fn remove(&mut self, idx: usize) -> u8 {
95		self.inner.remove(idx)
96	}
97
98	#[inline]
99	pub fn retain<F: FnMut(u8) -> bool>(&mut self, mut f: F) {
100		self.inner.retain(|x| f(*x))
101	}
102
103	#[inline]
104	pub fn insert(&mut self, idx: usize, b: u8) {
105		self.inner.insert(idx, b)
106	}
107
108	#[inline]
109	pub fn insert_str<T: AsRef<RawStr>>(&mut self, idx: usize, s: T) {
110		self.inner.splice(idx..idx, s.as_ref().bytes());
111	}
112
113	#[inline]
114	pub fn split_off(&mut self, at: usize) -> RawString {
115		RawString::from_bytes(self.inner.split_off(at))
116	}
117
118	#[inline]
119	pub fn drain<R: RangeBounds<usize>>(&mut self, range: R) -> Drain<u8> {
120		self.inner.drain(range)
121	}
122
123	#[inline]
124	pub fn replace_range<R: RangeBounds<usize>, T: AsRef<RawStr>>(
125		&mut self,
126		range: R,
127		replace_with: T,
128	) {
129		self.inner.splice(range, replace_with.as_ref().bytes());
130	}
131
132	#[inline]
133	pub fn into_boxed_raw_str(self) -> Box<RawStr> {
134		let raw = Box::into_raw(self.inner.into_boxed_slice()) as *mut RawStr;
135		unsafe { Box::from_raw(raw) }
136	}
137
138	#[inline]
139	pub fn push(&mut self, b: u8) {
140		self.inner.push(b)
141	}
142
143	#[inline]
144	pub fn push_str<T: AsRef<RawStr>>(&mut self, s: T) {
145		self.inner.extend_from_slice(s.as_ref().as_bytes())
146	}
147
148	#[inline]
149	pub fn as_mut_bytes(&mut self) -> &mut Vec<u8> {
150		&mut self.inner
151	}
152
153	#[inline]
154	pub fn to_string(self) -> Result<String, FromUtf8Error> {
155		String::from_utf8(self.into_bytes())
156	}
157
158	/// Convert to an OsString.
159	///
160	/// On Unix, it never fails.
161	/// On other platforms, it must be encoded as UTF-8.
162	///
163	/// A never-failing version for Unix only is available as
164	/// [`unix::RawStringExt::into_osstring`](struct.RawString.html#method.into_osstring).
165	#[inline]
166	pub fn to_osstring(self) -> Result<OsString, FromUtf8Error> {
167		self.to_osstring_()
168	}
169
170	/// Convert to a PathBuf.
171	///
172	/// On Unix, it never fails.
173	/// On other platforms, it must be encoded as UTF-8.
174	///
175	/// A never-failing version for Unix only is available as
176	/// [`unix::RawStringExt::into_pathbuf`](struct.RawString.html#method.into_pathbuf).
177	#[inline]
178	pub fn to_pathbuf(self) -> Result<PathBuf, FromUtf8Error> {
179		Ok(PathBuf::from(self.to_osstring()?))
180	}
181
182	#[cfg(unix)]
183	#[inline]
184	fn to_osstring_(self) -> Result<OsString, FromUtf8Error> {
185		use std::os::unix::ffi::OsStringExt;
186		Ok(OsString::from_vec(self.into_bytes()))
187	}
188
189	#[cfg(not(unix))]
190	#[inline]
191	fn to_osstring_(self) -> Result<OsString, FromUtf8Error> {
192		Ok(OsString::from(self.to_string()?))
193	}
194}
195
196// Deref / DerefMut {{{
197
198impl Deref for RawString {
199	type Target = RawStr;
200	#[inline]
201	fn deref(&self) -> &RawStr {
202		RawStr::from_bytes(&self.inner)
203	}
204}
205
206impl DerefMut for RawString {
207	#[inline]
208	fn deref_mut(&mut self) -> &mut RawStr {
209		RawStr::from_bytes_mut(&mut self.inner)
210	}
211}
212
213// }}}
214
215// Borrow / ToOwned {{{
216
217impl Borrow<RawStr> for RawString {
218	#[inline]
219	fn borrow(&self) -> &RawStr {
220		RawStr::from_bytes(&self.inner)
221	}
222}
223
224impl ToOwned for RawStr {
225	type Owned = RawString;
226	#[inline]
227	fn to_owned(&self) -> RawString {
228		RawString::from_bytes(self.as_bytes().to_owned())
229	}
230}
231
232// }}}
233
234// AsRef {{{
235
236impl AsRef<RawStr> for RawString {
237	#[inline]
238	fn as_ref(&self) -> &RawStr {
239		RawStr::from_bytes(&self.inner)
240	}
241}
242
243impl AsRef<[u8]> for RawString {
244	#[inline]
245	fn as_ref(&self) -> &[u8] {
246		&self.inner
247	}
248}
249
250// }}}
251
252// {{{ IntoIterator
253
254impl IntoIterator for RawString {
255	type Item = u8;
256	type IntoIter = std::vec::IntoIter<u8>;
257	#[inline]
258	fn into_iter(self) -> Self::IntoIter {
259		self.inner.into_iter()
260	}
261}
262
263impl<'a> IntoIterator for &'a RawString {
264	type Item = u8;
265	type IntoIter = std::iter::Cloned<std::slice::Iter<'a, u8>>;
266	#[inline]
267	fn into_iter(self) -> Self::IntoIter {
268		self.bytes()
269	}
270}
271
272impl<'a> IntoIterator for &'a mut RawString {
273	type Item = &'a mut u8;
274	type IntoIter = std::slice::IterMut<'a, u8>;
275	#[inline]
276	fn into_iter(self) -> Self::IntoIter {
277		self.bytes_mut()
278	}
279}
280
281// }}}
282
283// From {{{
284
285impl<'a> From<&'a RawStr> for RawString {
286	#[inline]
287	fn from(src: &'a RawStr) -> RawString {
288		RawString::from_bytes(src.as_bytes().to_owned())
289	}
290}
291
292impl<'a> From<&'a str> for RawString {
293	#[inline]
294	fn from(src: &'a str) -> RawString {
295		RawString::from_bytes(src.as_bytes().to_owned())
296	}
297}
298
299impl<'a> From<&'a [u8]> for RawString {
300	#[inline]
301	fn from(src: &'a [u8]) -> RawString {
302		RawString::from_bytes(src.to_owned())
303	}
304}
305
306impl From<String> for RawString {
307	#[inline]
308	fn from(src: String) -> RawString {
309		RawString::from_bytes(src.into_bytes())
310	}
311}
312
313impl From<Vec<u8>> for RawString {
314	#[inline]
315	fn from(src: Vec<u8>) -> RawString {
316		RawString::from_bytes(src)
317	}
318}
319
320// }}}
321
322// Display / Debug {{{
323
324impl Display for RawString {
325	#[inline]
326	fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
327		Display::fmt(self.deref(), f)
328	}
329}
330
331impl Debug for RawString {
332	#[inline]
333	fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
334		Debug::fmt(self.deref(), f)
335	}
336}
337
338// }}}
339
340// {{{ PartialEq / PartialOrd
341
342macro_rules! impl_ord {
343	($t:ty) => {
344		impl PartialEq<$t> for RawString {
345			#[inline]
346			fn eq(&self, other: &$t) -> bool {
347				<RawStr as PartialEq>::eq(self, other.as_ref())
348			}
349		}
350		impl PartialEq<RawString> for $t {
351			#[inline]
352			fn eq(&self, other: &RawString) -> bool {
353				<RawStr as PartialEq>::eq(self.as_ref(), other)
354			}
355		}
356		impl PartialOrd<$t> for RawString {
357			#[inline]
358			fn partial_cmp(&self, other: &$t) -> Option<Ordering> {
359				<RawStr as PartialOrd>::partial_cmp(self, other.as_ref())
360			}
361		}
362		impl PartialOrd<RawString> for $t {
363			#[inline]
364			fn partial_cmp(&self, other: &RawString) -> Option<Ordering> {
365				<RawStr as PartialOrd>::partial_cmp(self.as_ref(), other)
366			}
367		}
368	};
369}
370
371impl_ord!(RawStr);
372impl_ord!(str);
373impl_ord!([u8]);
374impl_ord!(&RawStr);
375impl_ord!(&str);
376impl_ord!(&[u8]);
377
378// }}}