about summary refs log tree commit diff
path: root/src/librustc_data_structures/small_c_str.rs
diff options
context:
space:
mode:
authorAndre Bogus <bogusandre@gmail.com>2018-08-23 20:22:22 +0200
committerAndre Bogus <bogusandre@gmail.com>2018-08-23 23:13:14 +0200
commit25a83e3a88bf5f199c8a8d8d8f452bab83d9a061 (patch)
tree5e68b47e932b6fa925589f6abceb29967eb0e59e /src/librustc_data_structures/small_c_str.rs
parente5284b0b57275cb18618ef1532ee7f07c32a1e18 (diff)
downloadrust-25a83e3a88bf5f199c8a8d8d8f452bab83d9a061.tar.gz
rust-25a83e3a88bf5f199c8a8d8d8f452bab83d9a061.zip
Use SmallVec for SmallCStr
Diffstat (limited to 'src/librustc_data_structures/small_c_str.rs')
-rw-r--r--src/librustc_data_structures/small_c_str.rs87
1 files changed, 39 insertions, 48 deletions
diff --git a/src/librustc_data_structures/small_c_str.rs b/src/librustc_data_structures/small_c_str.rs
index b0ad83e4979..08794fbec8d 100644
--- a/src/librustc_data_structures/small_c_str.rs
+++ b/src/librustc_data_structures/small_c_str.rs
@@ -11,69 +11,61 @@
 use std::ffi;
 use std::ops::Deref;
 
-const SIZE: usize = 38;
+use smallvec::SmallVec;
+
+const SIZE: usize = 36;
 
 /// Like SmallVec but for C strings.
 #[derive(Clone)]
-pub enum SmallCStr {
-    OnStack {
-        data: [u8; SIZE],
-        len_with_nul: u8,
-    },
-    OnHeap {
-        data: ffi::CString,
-    }
+pub struct SmallCStr {
+    data: SmallVec<[u8; SIZE]>,
 }
 
 impl SmallCStr {
     #[inline]
     pub fn new(s: &str) -> SmallCStr {
-        if s.len() < SIZE {
-            let mut data = [0; SIZE];
-            data[.. s.len()].copy_from_slice(s.as_bytes());
-            let len_with_nul = s.len() + 1;
-
-            // Make sure once that this is a valid CStr
-            if let Err(e) = ffi::CStr::from_bytes_with_nul(&data[.. len_with_nul]) {
-                panic!("The string \"{}\" cannot be converted into a CStr: {}", s, e);
-            }
-
-            SmallCStr::OnStack {
-                data,
-                len_with_nul: len_with_nul as u8,
-            }
+        let len = s.len();
+        let len1 = len + 1;
+        let data = if len < SIZE {
+            let mut buf = [0; SIZE];
+            buf[..len].copy_from_slice(s.as_bytes());
+            SmallVec::from_buf_and_len(buf, len1)
         } else {
-            SmallCStr::OnHeap {
-                data: ffi::CString::new(s).unwrap()
-            }
+            let mut data = Vec::with_capacity(len1);
+            data.extend_from_slice(s.as_bytes());
+            data.push(0);
+            SmallVec::from_vec(data)
+        };
+        if let Err(e) = ffi::CStr::from_bytes_with_nul(&data) {
+            panic!("The string \"{}\" cannot be converted into a CStr: {}", s, e);
         }
+        SmallCStr { data }
     }
 
     #[inline]
+    pub fn new_with_nul(s: &str) -> SmallCStr {
+        let b = s.as_bytes();
+        if let Err(e) = ffi::CStr::from_bytes_with_nul(b) {
+            panic!("The string \"{}\" cannot be converted into a CStr: {}", s, e);
+        }
+        SmallCStr { data: SmallVec::from_slice(s.as_bytes()) }
+    }
+
+
+    #[inline]
     pub fn as_c_str(&self) -> &ffi::CStr {
-        match *self {
-            SmallCStr::OnStack { ref data, len_with_nul } => {
-                unsafe {
-                    let slice = &data[.. len_with_nul as usize];
-                    ffi::CStr::from_bytes_with_nul_unchecked(slice)
-                }
-            }
-            SmallCStr::OnHeap { ref data } => {
-                data.as_c_str()
-            }
+        unsafe {
+            ffi::CStr::from_bytes_with_nul_unchecked(&self.data[..])
         }
     }
 
     #[inline]
     pub fn len_with_nul(&self) -> usize {
-        match *self {
-            SmallCStr::OnStack { len_with_nul, .. } => {
-                len_with_nul as usize
-            }
-            SmallCStr::OnHeap { ref data } => {
-                data.as_bytes_with_nul().len()
-            }
-        }
+        self.data.len()
+    }
+
+    pub fn spilled(&self) -> bool {
+        self.data.spilled()
     }
 }
 
@@ -85,7 +77,6 @@ impl Deref for SmallCStr {
     }
 }
 
-
 #[test]
 fn short() {
     const TEXT: &str = "abcd";
@@ -95,7 +86,7 @@ fn short() {
 
     assert_eq!(scs.len_with_nul(), TEXT.len() + 1);
     assert_eq!(scs.as_c_str(), reference.as_c_str());
-    assert!(if let SmallCStr::OnStack { .. } = scs { true } else { false });
+    assert!(!scs.spilled());
 }
 
 #[test]
@@ -107,7 +98,7 @@ fn empty() {
 
     assert_eq!(scs.len_with_nul(), TEXT.len() + 1);
     assert_eq!(scs.as_c_str(), reference.as_c_str());
-    assert!(if let SmallCStr::OnStack { .. } = scs { true } else { false });
+    assert!(!scs.spilled());
 }
 
 #[test]
@@ -121,7 +112,7 @@ fn long() {
 
     assert_eq!(scs.len_with_nul(), TEXT.len() + 1);
     assert_eq!(scs.as_c_str(), reference.as_c_str());
-    assert!(if let SmallCStr::OnHeap { .. } = scs { true } else { false });
+    assert!(scs.spilled());
 }
 
 #[test]