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 const SIZE: usize = 38;
16 /// Like SmallVec but for C strings.
30 pub fn new(s: &str) -> SmallCStr {
32 let mut data = [0; SIZE];
33 data[.. s.len()].copy_from_slice(s.as_bytes());
34 let len_with_nul = s.len() + 1;
36 // Make sure once that this is a valid CStr
37 if let Err(e) = ffi::CStr::from_bytes_with_nul(&data[.. len_with_nul]) {
38 panic!("The string \"{}\" cannot be converted into a CStr: {}", s, e);
43 len_with_nul: len_with_nul as u8,
47 data: ffi::CString::new(s).unwrap()
53 pub fn as_c_str(&self) -> &ffi::CStr {
55 SmallCStr::OnStack { ref data, len_with_nul } => {
57 let slice = &data[.. len_with_nul as usize];
58 ffi::CStr::from_bytes_with_nul_unchecked(slice)
61 SmallCStr::OnHeap { ref data } => {
68 pub fn len_with_nul(&self) -> usize {
70 SmallCStr::OnStack { len_with_nul, .. } => {
73 SmallCStr::OnHeap { ref data } => {
74 data.as_bytes_with_nul().len()
80 impl Deref for SmallCStr {
81 type Target = ffi::CStr;
83 fn deref(&self) -> &ffi::CStr {
91 const TEXT: &str = "abcd";
92 let reference = ffi::CString::new(TEXT.to_string()).unwrap();
94 let scs = SmallCStr::new(TEXT);
96 assert_eq!(scs.len_with_nul(), TEXT.len() + 1);
97 assert_eq!(scs.as_c_str(), reference.as_c_str());
98 assert!(if let SmallCStr::OnStack { .. } = scs { true } else { false });
103 const TEXT: &str = "";
104 let reference = ffi::CString::new(TEXT.to_string()).unwrap();
106 let scs = SmallCStr::new(TEXT);
108 assert_eq!(scs.len_with_nul(), TEXT.len() + 1);
109 assert_eq!(scs.as_c_str(), reference.as_c_str());
110 assert!(if let SmallCStr::OnStack { .. } = scs { true } else { false });
115 const TEXT: &str = "01234567890123456789012345678901234567890123456789\
116 01234567890123456789012345678901234567890123456789\
117 01234567890123456789012345678901234567890123456789";
118 let reference = ffi::CString::new(TEXT.to_string()).unwrap();
120 let scs = SmallCStr::new(TEXT);
122 assert_eq!(scs.len_with_nul(), TEXT.len() + 1);
123 assert_eq!(scs.as_c_str(), reference.as_c_str());
124 assert!(if let SmallCStr::OnHeap { .. } = scs { true } else { false });
130 let _ = SmallCStr::new("abcd\0def");