]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_data_structures/src/small_c_str.rs
New upstream version 1.61.0+dfsg1
[rustc.git] / compiler / rustc_data_structures / src / small_c_str.rs
CommitLineData
b7449926
XL
1use std::ffi;
2use std::ops::Deref;
3
4use smallvec::SmallVec;
5
416331ca
XL
6#[cfg(test)]
7mod tests;
8
b7449926
XL
9const SIZE: usize = 36;
10
11/// Like SmallVec but for C strings.
12#[derive(Clone)]
13pub struct SmallCStr {
14 data: SmallVec<[u8; SIZE]>,
15}
16
17impl 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
b7449926
XL
47 #[inline]
48 pub fn as_c_str(&self) -> &ffi::CStr {
a2a8927a 49 unsafe { ffi::CStr::from_bytes_with_nul_unchecked(&self.data) }
b7449926
XL
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
62impl Deref for SmallCStr {
63 type Target = ffi::CStr;
64
5e7ed085 65 #[inline]
b7449926
XL
66 fn deref(&self) -> &ffi::CStr {
67 self.as_c_str()
68 }
69}
5e7ed085
FG
70
71impl<'a> FromIterator<&'a str> for SmallCStr {
72 fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
73 let mut data =
74 iter.into_iter().flat_map(|s| s.as_bytes()).copied().collect::<SmallVec<_>>();
75 data.push(0);
76 if let Err(e) = ffi::CStr::from_bytes_with_nul(&data) {
77 panic!("The iterator {:?} cannot be converted into a CStr: {}", data, e);
78 }
79 Self { data }
80 }
81}