mirror of
https://github.com/fish-shell/fish-shell.git
synced 2025-02-27 11:57:23 +08:00
common.rs: reorder to match C++ companion
This makes it easier to check that we ported everything.
This commit is contained in:
parent
ed3a0b2bc3
commit
746019e4ad
@ -9,6 +9,120 @@ use std::mem::ManuallyDrop;
|
|||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::os::fd::AsRawFd;
|
use std::os::fd::AsRawFd;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum EscapeStringStyle {
|
||||||
|
Script(EscapeFlags),
|
||||||
|
Url,
|
||||||
|
Var,
|
||||||
|
Regex,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for EscapeStringStyle {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Script(EscapeFlags::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
/// Flags for the [`escape_string()`] function. These are only applicable when the escape style is
|
||||||
|
/// [`EscapeStringStyle::Script`].
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct EscapeFlags: u32 {
|
||||||
|
/// Do not escape special fish syntax characters like the semicolon. Only escape non-printable
|
||||||
|
/// characters and backslashes.
|
||||||
|
const NO_PRINTABLES = 1 << 0;
|
||||||
|
/// Do not try to use 'simplified' quoted escapes, and do not use empty quotes as the empty
|
||||||
|
/// string.
|
||||||
|
const NO_QUOTED = 1 << 1;
|
||||||
|
/// Do not escape tildes.
|
||||||
|
const NO_TILDE = 1 << 2;
|
||||||
|
/// Replace non-printable control characters with Unicode symbols.
|
||||||
|
const SYMBOLIC = 1 << 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Replace special characters with backslash escape sequences. Newline is replaced with `\n`, etc.
|
||||||
|
pub fn escape_string(s: &wstr, style: EscapeStringStyle) -> WString {
|
||||||
|
let (style, flags) = match style {
|
||||||
|
EscapeStringStyle::Script(flags) => {
|
||||||
|
(ffi::escape_string_style_t::STRING_STYLE_SCRIPT, flags)
|
||||||
|
}
|
||||||
|
EscapeStringStyle::Url => (
|
||||||
|
ffi::escape_string_style_t::STRING_STYLE_URL,
|
||||||
|
Default::default(),
|
||||||
|
),
|
||||||
|
EscapeStringStyle::Var => (
|
||||||
|
ffi::escape_string_style_t::STRING_STYLE_VAR,
|
||||||
|
Default::default(),
|
||||||
|
),
|
||||||
|
EscapeStringStyle::Regex => (
|
||||||
|
ffi::escape_string_style_t::STRING_STYLE_REGEX,
|
||||||
|
Default::default(),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
ffi::escape_string(c_str!(s), flags.bits().into(), style).from_ffi()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test if the string is a valid function name.
|
||||||
|
pub fn valid_func_name(name: &wstr) -> bool {
|
||||||
|
if name.is_empty() {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
if name.char_at(0) == '-' {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
// A function name needs to be a valid path, so no / and no NULL.
|
||||||
|
if name.find_char('/').is_some() {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
if name.find_char('\0').is_some() {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A rusty port of the C++ `write_loop()` function from `common.cpp`. This should be deprecated in
|
||||||
|
/// favor of native rust read/write methods at some point.
|
||||||
|
///
|
||||||
|
/// Returns the number of bytes written or an IO error.
|
||||||
|
pub fn write_loop<Fd: AsRawFd>(fd: &Fd, buf: &[u8]) -> std::io::Result<usize> {
|
||||||
|
let fd = fd.as_raw_fd();
|
||||||
|
let mut total = 0;
|
||||||
|
while total < buf.len() {
|
||||||
|
let written =
|
||||||
|
unsafe { libc::write(fd, buf[total..].as_ptr() as *const _, buf.len() - total) };
|
||||||
|
if written < 0 {
|
||||||
|
let errno = errno::errno().0;
|
||||||
|
if matches!(errno, libc::EAGAIN | libc::EINTR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return Err(std::io::Error::from_raw_os_error(errno));
|
||||||
|
}
|
||||||
|
total += written as usize;
|
||||||
|
}
|
||||||
|
Ok(total)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A rusty port of the C++ `read_loop()` function from `common.cpp`. This should be deprecated in
|
||||||
|
/// favor of native rust read/write methods at some point.
|
||||||
|
///
|
||||||
|
/// Returns the number of bytes read or an IO error.
|
||||||
|
pub fn read_loop<Fd: AsRawFd>(fd: &Fd, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||||
|
let fd = fd.as_raw_fd();
|
||||||
|
loop {
|
||||||
|
let read = unsafe { libc::read(fd, buf.as_mut_ptr() as *mut _, buf.len()) };
|
||||||
|
if read < 0 {
|
||||||
|
let errno = errno::errno().0;
|
||||||
|
if matches!(errno, libc::EAGAIN | libc::EINTR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return Err(std::io::Error::from_raw_os_error(errno));
|
||||||
|
}
|
||||||
|
return Ok(read as usize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Like [`std::mem::replace()`] but provides a reference to the old value in a callback to obtain
|
/// Like [`std::mem::replace()`] but provides a reference to the old value in a callback to obtain
|
||||||
/// the replacement value. Useful to avoid errors about multiple references (`&mut T` for `old` then
|
/// the replacement value. Useful to avoid errors about multiple references (`&mut T` for `old` then
|
||||||
/// `&T` again in the `new` expression).
|
/// `&T` again in the `new` expression).
|
||||||
@ -142,124 +256,10 @@ impl<'a, T> Drop for ScopedPush<'a, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub enum EscapeStringStyle {
|
|
||||||
Script(EscapeFlags),
|
|
||||||
Url,
|
|
||||||
Var,
|
|
||||||
Regex,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for EscapeStringStyle {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::Script(EscapeFlags::default())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
/// Flags for the [`escape_string()`] function. These are only applicable when the escape style is
|
|
||||||
/// [`EscapeStringStyle::Script`].
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct EscapeFlags : u32 {
|
|
||||||
/// Do not escape special fish syntax characters like the semicolon. Only escape non-printable
|
|
||||||
/// characters and backslashes.
|
|
||||||
const NO_PRINTABLES = 1 << 0;
|
|
||||||
/// Do not try to use 'simplified' quoted escapes, and do not use empty quotes as the empty
|
|
||||||
/// string.
|
|
||||||
const NO_QUOTED = 1 << 1;
|
|
||||||
/// Do not escape tildes.
|
|
||||||
const NO_TILDE = 1 << 2;
|
|
||||||
/// Replace non-printable control characters with Unicode symbols.
|
|
||||||
const SYMBOLIC = 1 << 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Replace special characters with backslash escape sequences. Newline is replaced with `\n`, etc.
|
|
||||||
pub fn escape_string(s: &wstr, style: EscapeStringStyle) -> WString {
|
|
||||||
let (style, flags) = match style {
|
|
||||||
EscapeStringStyle::Script(flags) => {
|
|
||||||
(ffi::escape_string_style_t::STRING_STYLE_SCRIPT, flags)
|
|
||||||
}
|
|
||||||
EscapeStringStyle::Url => (
|
|
||||||
ffi::escape_string_style_t::STRING_STYLE_URL,
|
|
||||||
Default::default(),
|
|
||||||
),
|
|
||||||
EscapeStringStyle::Var => (
|
|
||||||
ffi::escape_string_style_t::STRING_STYLE_VAR,
|
|
||||||
Default::default(),
|
|
||||||
),
|
|
||||||
EscapeStringStyle::Regex => (
|
|
||||||
ffi::escape_string_style_t::STRING_STYLE_REGEX,
|
|
||||||
Default::default(),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
ffi::escape_string(c_str!(s), flags.bits().into(), style).from_ffi()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Test if the string is a valid function name.
|
|
||||||
pub fn valid_func_name(name: &wstr) -> bool {
|
|
||||||
if name.is_empty() {
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
if name.char_at(0) == '-' {
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
// A function name needs to be a valid path, so no / and no NULL.
|
|
||||||
if name.find_char('/').is_some() {
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
if name.find_char('\0').is_some() {
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn assert_send<T: Send>() {}
|
pub const fn assert_send<T: Send>() {}
|
||||||
|
|
||||||
pub const fn assert_sync<T: Sync>() {}
|
pub const fn assert_sync<T: Sync>() {}
|
||||||
|
|
||||||
/// A rusty port of the C++ `write_loop()` function from `common.cpp`. This should be deprecated in
|
|
||||||
/// favor of native rust read/write methods at some point.
|
|
||||||
///
|
|
||||||
/// Returns the number of bytes written or an IO error.
|
|
||||||
pub fn write_loop<Fd: AsRawFd>(fd: &Fd, buf: &[u8]) -> std::io::Result<usize> {
|
|
||||||
let fd = fd.as_raw_fd();
|
|
||||||
let mut total = 0;
|
|
||||||
while total < buf.len() {
|
|
||||||
let written =
|
|
||||||
unsafe { libc::write(fd, buf[total..].as_ptr() as *const _, buf.len() - total) };
|
|
||||||
if written < 0 {
|
|
||||||
let errno = errno::errno().0;
|
|
||||||
if matches!(errno, libc::EAGAIN | libc::EINTR) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
return Err(std::io::Error::from_raw_os_error(errno));
|
|
||||||
}
|
|
||||||
total += written as usize;
|
|
||||||
}
|
|
||||||
Ok(total)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A rusty port of the C++ `read_loop()` function from `common.cpp`. This should be deprecated in
|
|
||||||
/// favor of native rust read/write methods at some point.
|
|
||||||
///
|
|
||||||
/// Returns the number of bytes read or an IO error.
|
|
||||||
pub fn read_loop<Fd: AsRawFd>(fd: &Fd, buf: &mut [u8]) -> std::io::Result<usize> {
|
|
||||||
let fd = fd.as_raw_fd();
|
|
||||||
loop {
|
|
||||||
let read = unsafe { libc::read(fd, buf.as_mut_ptr() as *mut _, buf.len()) };
|
|
||||||
if read < 0 {
|
|
||||||
let errno = errno::errno().0;
|
|
||||||
if matches!(errno, libc::EAGAIN | libc::EINTR) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
return Err(std::io::Error::from_raw_os_error(errno));
|
|
||||||
}
|
|
||||||
return Ok(read as usize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Asserts that a slice is alphabetically sorted by a [`&wstr`] `name` field.
|
/// Asserts that a slice is alphabetically sorted by a [`&wstr`] `name` field.
|
||||||
///
|
///
|
||||||
/// Mainly useful for static asserts/const eval.
|
/// Mainly useful for static asserts/const eval.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user