mirror of
https://github.com/fish-shell/fish-shell
synced 2024-11-10 15:14:44 +00:00
Add ToCString trait
This can be used for functions that accept non-Unicode content (i.e. &CStr or CString) but are often used in our code base with a UTF-8 or UTF-32 string on-hand. When such a function is passed a CString, it's passed through as-is and allocation-free. But when, as is often the case, we have a static string we can now pass it in directly with all the nice ergonomics thereof instead of having to manually create and unwrap a CString at the call location. There's an upstream request to add this functionality to the standard library: https://github.com/rust-lang/rust/issues/71448
This commit is contained in:
parent
b17124d8d2
commit
77dda2cdef
1 changed files with 61 additions and 1 deletions
|
@ -23,7 +23,7 @@ use libc::{EINTR, EIO, O_WRONLY, SIGTTOU, SIG_IGN, STDERR_FILENO, STDIN_FILENO,
|
|||
use num_traits::ToPrimitive;
|
||||
use once_cell::sync::Lazy;
|
||||
use std::env;
|
||||
use std::ffi::{CString, OsString};
|
||||
use std::ffi::{CStr, CString, OsString};
|
||||
use std::mem::{self, ManuallyDrop};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::os::fd::{AsRawFd, RawFd};
|
||||
|
@ -34,6 +34,7 @@ use std::str::FromStr;
|
|||
use std::sync::atomic::{AtomicI32, AtomicU32, Ordering};
|
||||
use std::sync::Mutex;
|
||||
use std::time;
|
||||
use widestring::Utf32String;
|
||||
use widestring_suffix::widestrs;
|
||||
|
||||
// Highest legal ASCII value.
|
||||
|
@ -1998,6 +1999,65 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// A trait to make it more convenient to pass ascii/Unicode strings to functions that can take
|
||||
/// non-Unicode values. The result is nul-terminated and can be passed to OS functions.
|
||||
///
|
||||
/// This is only implemented for owned types where an owned instance will skip allocations (e.g.
|
||||
/// `CString` can return `self`) but not implemented for owned instances where a new allocation is
|
||||
/// always required (e.g. implemented for `&wstr` but not `WideString`) because you might as well be
|
||||
/// left with the original item if we're going to allocate from scratch in all cases.
|
||||
pub trait ToCString {
|
||||
/// Correctly convert to a nul-terminated [`CString`] that can be passed to OS functions.
|
||||
fn to_cstring(self) -> CString;
|
||||
}
|
||||
|
||||
impl ToCString for CString {
|
||||
fn to_cstring(self) -> CString {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCString for &CStr {
|
||||
fn to_cstring(self) -> CString {
|
||||
self.to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
/// Safely converts from `&wstr` to a `CString` to a nul-terminated `CString` that can be passed to
|
||||
/// OS functions, taking into account non-Unicode values that have been shifted into the private-use
|
||||
/// range by using [`wcs2zstring()`].
|
||||
impl ToCString for &wstr {
|
||||
/// The wide string may contain non-Unicode bytes mapped to the private-use Unicode range, so we
|
||||
/// have to use [`wcs2zstring()`](self::wcs2zstring) to convert it correctly.
|
||||
fn to_cstring(self) -> CString {
|
||||
self::wcs2zstring(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Safely converts from `&Utf32String` to a nul-terminated `CString` that can be passed to OS
|
||||
/// functions, taking into account non-Unicode values that have been shifted into the private-use
|
||||
/// range by using [`wcs2zstring()`].
|
||||
impl ToCString for &Utf32String {
|
||||
fn to_cstring(self) -> CString {
|
||||
self.as_utfstr().to_cstring()
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a (probably ascii) string to CString that can be passed to OS functions.
|
||||
impl ToCString for Vec<u8> {
|
||||
fn to_cstring(mut self) -> CString {
|
||||
self.push(b'\0');
|
||||
CString::from_vec_with_nul(self).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a (probably ascii) string to nul-terminated CString that can be passed to OS functions.
|
||||
impl ToCString for &[u8] {
|
||||
fn to_cstring(self) -> CString {
|
||||
CString::new(self).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! fwprintf {
|
||||
($fd:expr, $format:literal $(, $arg:expr)*) => {
|
||||
|
|
Loading…
Reference in a new issue