1 // Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
14 use smallvec::SmallVec;
16 const SIZE: usize = 36;
18 /// Like SmallVec but for C strings.
20 pub struct SmallCStr {
21 data: SmallVec<[u8; SIZE]>,
26 pub fn new(s: &str) -> SmallCStr {
29 let data = if len < SIZE {
30 let mut buf = [0; SIZE];
31 buf[..len].copy_from_slice(s.as_bytes());
32 SmallVec::from_buf_and_len(buf, len1)
34 let mut data = Vec::with_capacity(len1);
35 data.extend_from_slice(s.as_bytes());
37 SmallVec::from_vec(data)
39 if let Err(e) = ffi::CStr::from_bytes_with_nul(&data) {
40 panic!("The string \"{}\" cannot be converted into a CStr: {}", s, e);
46 pub fn new_with_nul(s: &str) -> SmallCStr {
48 if let Err(e) = ffi::CStr::from_bytes_with_nul(b) {
49 panic!("The string \"{}\" cannot be converted into a CStr: {}", s, e);
51 SmallCStr { data: SmallVec::from_slice(s.as_bytes()) }
56 pub fn as_c_str(&self) -> &ffi::CStr {
58 ffi::CStr::from_bytes_with_nul_unchecked(&self.data[..])
63 pub fn len_with_nul(&self) -> usize {
67 pub fn spilled(&self) -> bool {
72 impl Deref for SmallCStr {
73 type Target = ffi::CStr;
75 fn deref(&self) -> &ffi::CStr {
82 const TEXT: &str = "abcd";
83 let reference = ffi::CString::new(TEXT.to_string()).unwrap();
85 let scs = SmallCStr::new(TEXT);
87 assert_eq!(scs.len_with_nul(), TEXT.len() + 1);
88 assert_eq!(scs.as_c_str(), reference.as_c_str());
89 assert!(!scs.spilled());
94 const TEXT: &str = "";
95 let reference = ffi::CString::new(TEXT.to_string()).unwrap();
97 let scs = SmallCStr::new(TEXT);
99 assert_eq!(scs.len_with_nul(), TEXT.len() + 1);
100 assert_eq!(scs.as_c_str(), reference.as_c_str());
101 assert!(!scs.spilled());
106 const TEXT: &str = "01234567890123456789012345678901234567890123456789\
107 01234567890123456789012345678901234567890123456789\
108 01234567890123456789012345678901234567890123456789";
109 let reference = ffi::CString::new(TEXT.to_string()).unwrap();
111 let scs = SmallCStr::new(TEXT);
113 assert_eq!(scs.len_with_nul(), TEXT.len() + 1);
114 assert_eq!(scs.as_c_str(), reference.as_c_str());
115 assert!(scs.spilled());
121 let _ = SmallCStr::new("abcd\0def");