Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

82 lines
2.0 KiB
Rust
Raw Normal View History

use std::ffi;
use std::ops::Deref;
2018-08-23 20:22:22 +02:00
use smallvec::SmallVec;
#[cfg(test)]
mod tests;
2018-08-23 20:22:22 +02:00
const SIZE: usize = 36;
/// Like SmallVec but for C strings.
#[derive(Clone)]
2018-08-23 20:22:22 +02:00
pub struct SmallCStr {
data: SmallVec<[u8; SIZE]>,
}
impl SmallCStr {
#[inline]
pub fn new(s: &str) -> SmallCStr {
2018-08-23 20:22:22 +02:00
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 {
2018-08-23 20:22:22 +02:00
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 \"{s}\" cannot be converted into a CStr: {e}");
}
2018-08-23 20:22:22 +02:00
SmallCStr { data }
}
2018-08-23 20:22:22 +02:00
#[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 \"{s}\" cannot be converted into a CStr: {e}");
2018-08-23 20:22:22 +02:00
}
SmallCStr { data: SmallVec::from_slice(s.as_bytes()) }
}
#[inline]
pub fn as_c_str(&self) -> &ffi::CStr {
2021-12-03 03:06:36 +01:00
unsafe { ffi::CStr::from_bytes_with_nul_unchecked(&self.data) }
}
#[inline]
pub fn len_with_nul(&self) -> usize {
2018-08-23 20:22:22 +02:00
self.data.len()
}
pub fn spilled(&self) -> bool {
self.data.spilled()
}
}
impl Deref for SmallCStr {
type Target = ffi::CStr;
2022-03-03 00:00:00 +00:00
#[inline]
fn deref(&self) -> &ffi::CStr {
self.as_c_str()
}
}
impl<'a> FromIterator<&'a str> for SmallCStr {
fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
let mut data =
iter.into_iter().flat_map(|s| s.as_bytes()).copied().collect::<SmallVec<_>>();
data.push(0);
if let Err(e) = ffi::CStr::from_bytes_with_nul(&data) {
panic!("The iterator {data:?} cannot be converted into a CStr: {e}");
}
Self { data }
}
}