]>
Commit | Line | Data |
---|---|---|
f20569fa XL |
1 | use std::ffi; |
2 | use std::ops::Deref; | |
3 | ||
4 | use smallvec::SmallVec; | |
5 | ||
6 | #[cfg(test)] | |
7 | mod tests; | |
8 | ||
9 | const SIZE: usize = 36; | |
10 | ||
11 | /// Like SmallVec but for C strings. | |
12 | #[derive(Clone)] | |
13 | pub struct SmallCStr { | |
14 | data: SmallVec<[u8; SIZE]>, | |
15 | } | |
16 | ||
17 | impl SmallCStr { | |
18 | #[inline] | |
19 | pub fn new(s: &str) -> SmallCStr { | |
20 | let len = s.len(); | |
21 | let len1 = len + 1; | |
22 | let data = if len < SIZE { | |
23 | let mut buf = [0; SIZE]; | |
24 | buf[..len].copy_from_slice(s.as_bytes()); | |
25 | SmallVec::from_buf_and_len(buf, len1) | |
26 | } else { | |
27 | let mut data = Vec::with_capacity(len1); | |
28 | data.extend_from_slice(s.as_bytes()); | |
29 | data.push(0); | |
30 | SmallVec::from_vec(data) | |
31 | }; | |
32 | if let Err(e) = ffi::CStr::from_bytes_with_nul(&data) { | |
33 | panic!("The string \"{}\" cannot be converted into a CStr: {}", s, e); | |
34 | } | |
35 | SmallCStr { data } | |
36 | } | |
37 | ||
38 | #[inline] | |
39 | pub fn new_with_nul(s: &str) -> SmallCStr { | |
40 | let b = s.as_bytes(); | |
41 | if let Err(e) = ffi::CStr::from_bytes_with_nul(b) { | |
42 | panic!("The string \"{}\" cannot be converted into a CStr: {}", s, e); | |
43 | } | |
44 | SmallCStr { data: SmallVec::from_slice(s.as_bytes()) } | |
45 | } | |
46 | ||
47 | #[inline] | |
48 | pub fn as_c_str(&self) -> &ffi::CStr { | |
49 | unsafe { ffi::CStr::from_bytes_with_nul_unchecked(&self.data[..]) } | |
50 | } | |
51 | ||
52 | #[inline] | |
53 | pub fn len_with_nul(&self) -> usize { | |
54 | self.data.len() | |
55 | } | |
56 | ||
57 | pub fn spilled(&self) -> bool { | |
58 | self.data.spilled() | |
59 | } | |
60 | } | |
61 | ||
62 | impl Deref for SmallCStr { | |
63 | type Target = ffi::CStr; | |
64 | ||
65 | fn deref(&self) -> &ffi::CStr { | |
66 | self.as_c_str() | |
67 | } | |
68 | } |