diff --git a/crates/wcstringutil/src/lib.rs b/crates/wcstringutil/src/lib.rs index 7f1c1d622..10cbf4d73 100644 --- a/crates/wcstringutil/src/lib.rs +++ b/crates/wcstringutil/src/lib.rs @@ -1,5 +1,10 @@ //! Helper functions for working with wcstring. +use std::{ + ffi::{CStr, CString, OsString}, + os::unix::ffi::OsStringExt as _, +}; + use fish_common::{get_ellipsis_char, get_ellipsis_str}; use fish_fallback::{fish_wcwidth, lowercase, lowercase_rev, wcscasecmp, wcscasecmp_fuzzy}; use fish_widestring::{decode_byte_from_char, prelude::*}; @@ -360,6 +365,121 @@ pub fn str2bytes_callback(input: impl IntoCharIter, mut func: impl FnMut(&[u8]) true } +/// Returns a newly allocated multibyte character string equivalent of the specified wide character +/// string. +/// +/// This function decodes illegal character sequences in a reversible way using the private use +/// area. +pub fn wcs2bytes(input: impl IntoCharIter) -> Vec { + let mut result = vec![]; + wcs2bytes_appending(&mut result, input); + result +} + +pub fn wcs2osstring(input: &wstr) -> OsString { + if input.is_empty() { + return OsString::new(); + } + + let mut result = vec![]; + wcs2bytes_appending(&mut result, input); + OsString::from_vec(result) +} + +/// Same as [`wcs2bytes`]. Meant to be used when we need a zero-terminated string to feed legacy APIs. +/// Note: if `input` contains any interior NUL bytes, the result will be truncated at the first! +pub fn wcs2zstring(input: &wstr) -> CString { + if input.is_empty() { + return CString::default(); + } + + let mut vec = Vec::with_capacity(input.len() + 1); + str2bytes_callback(input, |buff| { + vec.extend_from_slice(buff); + true + }); + vec.push(b'\0'); + + match CString::from_vec_with_nul(vec) { + Ok(cstr) => cstr, + Err(err) => { + // `input` contained a NUL in the middle; we can retrieve `vec`, though + let mut vec = err.into_bytes(); + let pos = vec.iter().position(|c| *c == b'\0').unwrap(); + vec.truncate(pos + 1); + // Safety: We truncated after the first NUL + unsafe { CString::from_vec_with_nul_unchecked(vec) } + } + } +} + +/// Like [`wcs2bytes`], but appends to `output` instead of returning a new string. +pub fn wcs2bytes_appending(output: &mut Vec, input: impl IntoCharIter) { + str2bytes_callback(input, |buff| { + output.extend_from_slice(buff); + true + }); +} + +/// 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 `&WString` 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 &WString { + 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 { + 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() + } +} + /// Split a string by runs of any of the separator characters provided in `seps`. /// Note the delimiters are the characters in `seps`, not `seps` itself. /// `seps` may contain the NUL character. diff --git a/src/autoload.rs b/src/autoload.rs index 9e7d624ea..aa4537e20 100644 --- a/src/autoload.rs +++ b/src/autoload.rs @@ -1,12 +1,12 @@ //! The classes responsible for autoloading functions and completions. -use crate::common::wcs2bytes; use crate::common::{ScopeGuard, escape}; use crate::env::Environment; use crate::flogf; use crate::io::IoChain; use crate::parser::Parser; use crate::wutil::{FileId, INVALID_FILE_ID, file_id_for_path}; +use fish_wcstringutil::wcs2bytes; use fish_widestring::{L, WExt as _, WString, wstr}; use lru::LruCache; use rust_embed::RustEmbed; @@ -463,8 +463,8 @@ mod tests { #[serial] fn test_autoload() { let _cleanup = test_init(); - use crate::common::wcs2zstring; use crate::fds::wopen_cloexec; + use fish_wcstringutil::wcs2zstring; use nix::fcntl::OFlag; macro_rules! run { diff --git a/src/bin/fish.rs b/src/bin/fish.rs index bce70de43..2f7cb0ddc 100644 --- a/src/bin/fish.rs +++ b/src/bin/fish.rs @@ -28,7 +28,7 @@ }, common::{ PACKAGE_NAME, PROFILING_ACTIVE, PROGRAM_NAME, bytes2wcstring, escape, osstr2wcstring, - save_term_foreground_process_group, wcs2bytes, + save_term_foreground_process_group, }, env::{ EnvMode, Statuses, @@ -61,6 +61,7 @@ topic_monitor, wutil::waccess, }; +use fish_wcstringutil::wcs2bytes; use libc::STDIN_FILENO; use nix::unistd::AccessFlags; use std::ffi::{OsStr, OsString}; diff --git a/src/builtins/fish_indent.rs b/src/builtins/fish_indent.rs index cccc17aa8..8dd2bef5e 100644 --- a/src/builtins/fish_indent.rs +++ b/src/builtins/fish_indent.rs @@ -14,7 +14,7 @@ }; use crate::common::{ PROGRAM_NAME, ReadExt as _, UnescapeFlags, UnescapeStringStyle, bytes2wcstring, - get_program_name, osstr2wcstring, unescape_string, wcs2bytes, + get_program_name, osstr2wcstring, unescape_string, }; use crate::env::EnvStack; use crate::env::env_init; @@ -33,7 +33,7 @@ use crate::topic_monitor::topic_monitor_init; use crate::wutil::fish_iswalnum; use assert_matches::assert_matches; -use fish_wcstringutil::count_preceding_backslashes; +use fish_wcstringutil::{count_preceding_backslashes, wcs2bytes}; use fish_wgetopt::{ArgType, WGetopter, WOption, wopt}; use std::fmt::Write as _; diff --git a/src/builtins/status.rs b/src/builtins/status.rs index 696d744df..a43df9d84 100644 --- a/src/builtins/status.rs +++ b/src/builtins/status.rs @@ -9,6 +9,8 @@ use crate::tty_handoff::{TERMINAL_OS_NAME, get_scroll_content_up_capability, xtversion}; use crate::wutil::{Error, waccess, wbasename, wdirname, wrealpath}; use cfg_if::cfg_if; +use fish_util::wcsfilecmp_glob; +use fish_wcstringutil::wcs2bytes; use nix::unistd::AccessFlags; use rust_embed::RustEmbed; @@ -467,7 +469,7 @@ pub fn status(parser: &Parser, streams: &mut IoStreams, args: &mut [&wstr]) -> B )); return Err(STATUS_INVALID_ARGS); } - let arg = crate::common::wcs2bytes(args[0]); + let arg = wcs2bytes(args[0]); let arg = std::str::from_utf8(&arg).unwrap(); let Some(emfile) = crate::autoload::Asset::get(arg) .or_else(|| Docs::get(arg)) @@ -521,10 +523,9 @@ pub fn status(parser: &Parser, streams: &mut IoStreams, args: &mut [&wstr]) -> B } } STATUS_LIST_FILES => { - use fish_util::wcsfilecmp_glob; let mut paths = vec![]; let mut add = |arg| { - let arg = crate::common::wcs2bytes(arg); + let arg = wcs2bytes(arg); let arg = std::str::from_utf8(&arg).unwrap(); for path in crate::autoload::Asset::iter() .chain(Docs::iter()) diff --git a/src/common.rs b/src/common.rs index 08a41d1aa..e6c459669 100644 --- a/src/common.rs +++ b/src/common.rs @@ -15,13 +15,13 @@ use crate::wildcard::{ANY_CHAR, ANY_STRING, ANY_STRING_RECURSIVE}; use crate::wutil::fish_iswalnum; use fish_fallback::fish_wcwidth; -use fish_wcstringutil::str2bytes_callback; +use fish_wcstringutil::wcs2bytes; use fish_widestring::{ ENCODE_DIRECT_END, decode_byte_from_char, encode_byte_to_char, subslice_position, }; use nix::sys::termios::Termios; use std::env; -use std::ffi::{CStr, CString, OsStr, OsString}; +use std::ffi::{CStr, OsStr}; use std::os::unix::prelude::*; use std::sync::atomic::Ordering; use std::sync::{Arc, MutexGuard, OnceLock}; @@ -999,62 +999,6 @@ pub(crate) fn charptr2wcstring(input: *const libc::c_char) -> WString { bytes2wcstring(input) } -/// Returns a newly allocated multibyte character string equivalent of the specified wide character -/// string. -/// -/// This function decodes illegal character sequences in a reversible way using the private use -/// area. -pub fn wcs2bytes(input: impl IntoCharIter) -> Vec { - let mut result = vec![]; - wcs2bytes_appending(&mut result, input); - result -} - -pub fn wcs2osstring(input: &wstr) -> OsString { - if input.is_empty() { - return OsString::new(); - } - - let mut result = vec![]; - wcs2bytes_appending(&mut result, input); - OsString::from_vec(result) -} - -/// Same as [`wcs2bytes`]. Meant to be used when we need a zero-terminated string to feed legacy APIs. -/// Note: if `input` contains any interior NUL bytes, the result will be truncated at the first! -pub fn wcs2zstring(input: &wstr) -> CString { - if input.is_empty() { - return CString::default(); - } - - let mut vec = Vec::with_capacity(input.len() + 1); - str2bytes_callback(input, |buff| { - vec.extend_from_slice(buff); - true - }); - vec.push(b'\0'); - - match CString::from_vec_with_nul(vec) { - Ok(cstr) => cstr, - Err(err) => { - // `input` contained a NUL in the middle; we can retrieve `vec`, though - let mut vec = err.into_bytes(); - let pos = vec.iter().position(|c| *c == b'\0').unwrap(); - vec.truncate(pos + 1); - // Safety: We truncated after the first NUL - unsafe { CString::from_vec_with_nul_unchecked(vec) } - } - } -} - -/// Like [`wcs2bytes`], but appends to `output` instead of returning a new string. -pub fn wcs2bytes_appending(output: &mut Vec, input: impl IntoCharIter) { - str2bytes_callback(input, |buff| { - output.extend_from_slice(buff); - true - }); -} - /// Stored in blocks to reference the file which created the block. pub type FilenameRef = Arc; @@ -1309,65 +1253,6 @@ pub fn valid_var_name(s: &wstr) -> bool { !s.is_empty() && s.chars().all(valid_var_name_char) } -/// 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 `&WString` 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 &WString { - 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 { - 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() - } -} - #[macro_export] macro_rules! env_stack_set_from_env { ($vars:ident, $var_name:literal) => {{ diff --git a/src/env/environment_impl.rs b/src/env/environment_impl.rs index 27bd1c269..1725295a0 100644 --- a/src/env/environment_impl.rs +++ b/src/env/environment_impl.rs @@ -1,4 +1,3 @@ -use crate::common::wcs2zstring; use crate::env::{ ELECTRIC_VARIABLES, ElectricVar, EnvMode, EnvSetMode, EnvStackSetResult, EnvVar, EnvVarFlags, PATH_ARRAY_SEP, Statuses, VarTable, is_read_only, @@ -10,11 +9,12 @@ use crate::kill::kill_entries; use crate::nix::umask; use crate::null_terminated_array::OwningNullTerminatedArray; +use crate::portable_atomic::AtomicU64; use crate::prelude::*; use crate::reader::{commandline_get_state, reader_status_count}; use crate::threads::{is_forked_child, is_main_thread}; use crate::wutil::fish_wcstol_radix; - +use fish_wcstringutil::wcs2zstring; use std::cell::{RefCell, UnsafeCell}; use std::collections::HashSet; use std::ffi::CString; @@ -22,8 +22,6 @@ use std::mem; use std::ops::{Deref, DerefMut}; use std::sync::LazyLock; - -use crate::portable_atomic::AtomicU64; use std::sync::{Arc, Mutex, MutexGuard, atomic::Ordering}; /// Getter for universal variables. diff --git a/src/env/mod.rs b/src/env/mod.rs index c8d6eefdf..a8eeb5fc1 100644 --- a/src/env/mod.rs +++ b/src/env/mod.rs @@ -3,8 +3,8 @@ mod environment_impl; pub mod var; -use crate::common::ToCString; pub use environment::*; +use fish_wcstringutil::ToCString; use std::sync::{Mutex, atomic::AtomicUsize}; pub use var::*; @@ -22,7 +22,7 @@ /// environment variables. /// /// As values could contain non-unicode characters, they must first be converted from &wstr to a -/// `CString` with [`crate::common::wcs2zstring()`]. +/// `CString` with [`fish_wcstringutil::wcs2zstring()`]. pub fn setenv_lock(name: S1, value: S2, overwrite: bool) { let name = name.to_cstring(); let value = value.to_cstring(); diff --git a/src/env_universal_common.rs b/src/env_universal_common.rs index dd1faeecf..d55a0a9c2 100644 --- a/src/env_universal_common.rs +++ b/src/env_universal_common.rs @@ -1,13 +1,11 @@ -use crate::common::{ - UnescapeFlags, UnescapeStringStyle, unescape_string, valid_var_name, wcs2zstring, -}; +use crate::common::{UnescapeFlags, UnescapeStringStyle, unescape_string, valid_var_name}; use crate::env::{EnvVar, EnvVarFlags, VarTable}; use crate::flog::{flog, flogf}; use crate::fs::{PotentialUpdate, lock_and_load, rewrite_via_temporary_file}; use crate::path::path_get_config; use crate::prelude::*; use crate::wutil::{FileId, INVALID_FILE_ID, file_id_for_file, file_id_for_path_narrow, wrealpath}; -use fish_wcstringutil::{LineIterator, join_strings}; +use fish_wcstringutil::{LineIterator, join_strings, wcs2zstring}; use fish_widestring::decode_byte_from_char; use itertools::Itertools as _; use std::collections::HashSet; @@ -808,15 +806,15 @@ fn skip_spaces(mut s: &wstr) -> &wstr { #[cfg(test)] mod tests { - use fish_tempfile::TempDir; - use fish_widestring::{ENCODE_DIRECT_BASE, char_offset}; - - use crate::common::{osstr2wcstring, wcs2osstring}; + use crate::common::osstr2wcstring; use crate::env::{EnvVar, EnvVarFlags, VarTable}; use crate::env_universal_common::{EnvUniversal, UvarFormat}; use crate::prelude::*; use crate::tests::prelude::*; use crate::wutil::{INVALID_FILE_ID, file_id_for_path}; + use fish_tempfile::TempDir; + use fish_wcstringutil::wcs2osstring; + use fish_widestring::{ENCODE_DIRECT_BASE, char_offset}; const UVARS_PER_THREAD: usize = 8; diff --git a/src/exec.rs b/src/exec.rs index bd619eb9e..0349e4a55 100644 --- a/src/exec.rs +++ b/src/exec.rs @@ -8,8 +8,7 @@ builtin_run, }; use crate::common::{ - ScopeGuard, bytes2wcstring, exit_without_destructors, truncate_at_nul, wcs2bytes, wcs2zstring, - write_loop, + ScopeGuard, bytes2wcstring, exit_without_destructors, truncate_at_nul, write_loop, }; use crate::env::{EnvMode, EnvSetMode, EnvStack, Environment as _, READ_BYTE_LIMIT, Statuses}; #[cfg(have_posix_spawn)] @@ -47,6 +46,7 @@ use crate::tty_handoff::TtyHandoff; use crate::wutil::{fish_wcstol, perror}; use errno::{errno, set_errno}; +use fish_wcstringutil::{wcs2bytes, wcs2zstring}; use fish_widestring::ToWString as _; use libc::{ EACCES, ENOENT, ENOEXEC, ENOTDIR, EPIPE, EXIT_FAILURE, EXIT_SUCCESS, STDERR_FILENO, diff --git a/src/fds.rs b/src/fds.rs index 1ba1e17b6..7044e0c7b 100644 --- a/src/fds.rs +++ b/src/fds.rs @@ -1,9 +1,9 @@ -use crate::common::wcs2zstring; use crate::flog::flog; use crate::prelude::*; use crate::signal::signal_check_cancel; use crate::wutil::perror; use cfg_if::cfg_if; +use fish_wcstringutil::wcs2zstring; use libc::{EINTR, F_GETFD, F_GETFL, F_SETFD, F_SETFL, FD_CLOEXEC, O_NONBLOCK, c_int}; use nix::fcntl::FcntlArg; use nix::fcntl::OFlag; diff --git a/src/flog.rs b/src/flog.rs index 95c980ba6..983063af9 100644 --- a/src/flog.rs +++ b/src/flog.rs @@ -1,8 +1,8 @@ -use crate::common::wcs2bytes; use crate::prelude::*; use crate::wildcard::wildcard_match; use crate::wutil::write_to_fd; use crate::{parse_util::unescape_wildcards, wutil::unescape_bytes_and_write_to_fd}; +use fish_wcstringutil::wcs2bytes; use libc::c_int; use std::sync::atomic::{AtomicI32, Ordering}; diff --git a/src/fs.rs b/src/fs.rs index 7d9396a53..c7bd2f7fd 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -1,5 +1,5 @@ use crate::{ - common::{osstr2wcstring, wcs2bytes, wcs2osstring}, + common::osstr2wcstring, fds::wopen_cloexec, flog, flogf, path::{DirRemoteness, path_remoteness}, @@ -9,6 +9,7 @@ }, }; use fish_tempfile::random_filename; +use fish_wcstringutil::{wcs2bytes, wcs2osstring}; use libc::{LOCK_EX, LOCK_SH, c_int}; use nix::{fcntl::OFlag, sys::stat::Mode}; use std::{ diff --git a/src/function.rs b/src/function.rs index 6df8b2ecb..763969286 100644 --- a/src/function.rs +++ b/src/function.rs @@ -15,6 +15,7 @@ use crate::prelude::*; use crate::proc::Pid; use crate::wutil::dir_iter::DirIter; +use fish_wcstringutil::wcs2bytes; use std::collections::{HashMap, HashSet}; use std::num::NonZeroU32; use std::sync::{Arc, LazyLock, Mutex}; @@ -240,7 +241,7 @@ pub fn exists_no_autoload(cmd: &wstr) -> bool { return true; } - let narrow = crate::common::wcs2bytes(cmd); + let narrow = wcs2bytes(cmd); if let Ok(cmdstr) = std::str::from_utf8(&narrow) { let cmd = "functions/".to_owned() + cmdstr + ".fish"; crate::autoload::has_asset(&cmd) diff --git a/src/history/file.rs b/src/history/file.rs index 6bdf7e4da..ae51cd81c 100644 --- a/src/history/file.rs +++ b/src/history/file.rs @@ -1,25 +1,23 @@ //! Implementation of the YAML-like history file format. -use std::{ - fs::File, - io::Read as _, - ops::{Deref, DerefMut}, - os::fd::AsRawFd as _, - time::{SystemTime, UNIX_EPOCH}, -}; - -use libc::{ENODEV, MAP_ANONYMOUS, MAP_FAILED, MAP_PRIVATE, PROT_READ, PROT_WRITE}; - use super::HistoryItem; use super::yaml_backend::{ decode_item_fish_2_0, escape_yaml_fish_2_0, offset_of_next_item_fish_2_0, }; use crate::{ - common::wcs2bytes, flog::flog, path::{DirRemoteness, path_get_data_remoteness}, wutil::FileId, }; +use fish_wcstringutil::wcs2bytes; +use libc::{ENODEV, MAP_ANONYMOUS, MAP_FAILED, MAP_PRIVATE, PROT_READ, PROT_WRITE}; +use std::{ + fs::File, + io::Read as _, + ops::{Deref, DerefMut}, + os::fd::AsRawFd as _, + time::{SystemTime, UNIX_EPOCH}, +}; /// History file types. #[derive(Clone, Copy, Debug, PartialEq, Eq)] diff --git a/src/history/history.rs b/src/history/history.rs index 346632463..4ae79a14c 100644 --- a/src/history/history.rs +++ b/src/history/history.rs @@ -1806,12 +1806,14 @@ mod tests { History, HistoryItem, HistorySearch, PathList, PersistenceMode, SearchDirection, SearchFlags, SearchType, VACUUM_FREQUENCY, }; - use crate::common::{ESCAPE_TEST_CHAR, osstr2wcstring, wcs2bytes}; + use crate::common::{ESCAPE_TEST_CHAR, osstr2wcstring}; use crate::env::{EnvMode, EnvSetMode, EnvStack}; use crate::fs::{LockedFile, WriteMethod}; use crate::prelude::*; use fish_build_helper::workspace_root; - use fish_wcstringutil::{string_prefixes_string, string_prefixes_string_case_insensitive}; + use fish_wcstringutil::{ + string_prefixes_string, string_prefixes_string_case_insensitive, wcs2bytes, + }; use rand::Rng as _; use rand::rngs::ThreadRng; use std::collections::VecDeque; diff --git a/src/io.rs b/src/io.rs index 130a85814..665122ce9 100644 --- a/src/io.rs +++ b/src/io.rs @@ -1,5 +1,5 @@ use crate::builtins::shared::{STATUS_CMD_ERROR, STATUS_CMD_OK, STATUS_READ_TOO_MUCH}; -use crate::common::{bytes2wcstring, wcs2bytes}; +use crate::common::bytes2wcstring; use crate::fd_monitor::{Callback, FdMonitor, FdMonitorItemId}; use crate::fds::{ BorrowedFdFile, PIPE_ERROR, make_autoclose_pipes, make_fd_nonblocking, wopen_cloexec, @@ -14,6 +14,7 @@ use crate::topic_monitor::Topic; use crate::wutil::{perror, perror_io, unescape_bytes_and_write_to_fd, wdirname, wstat}; use errno::Errno; +use fish_wcstringutil::wcs2bytes; use libc::{EAGAIN, EINTR, ENOENT, ENOTDIR, EPIPE, EWOULDBLOCK, STDOUT_FILENO}; use nix::fcntl::OFlag; use nix::sys::stat::Mode; diff --git a/src/parser.rs b/src/parser.rs index 1193f3cb9..16c480237 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -4,7 +4,7 @@ use crate::builtins::shared::STATUS_ILLEGAL_CMD; use crate::common::{ CancelChecker, EscapeFlags, EscapeStringStyle, FilenameRef, PROFILING_ACTIVE, ScopeGuarding, - ScopedCell, ScopedRefCell, escape_string, wcs2bytes, + ScopedCell, ScopedRefCell, escape_string, }; use crate::complete::CompletionList; use crate::env::{ @@ -36,6 +36,7 @@ use crate::{flog, flogf, function}; use assert_matches::assert_matches; use fish_util::get_time; +use fish_wcstringutil::wcs2bytes; use fish_widestring::WExt as _; use libc::c_int; use std::cell::{Ref, RefCell, RefMut}; diff --git a/src/path.rs b/src/path.rs index 7112646fc..fd8a23803 100644 --- a/src/path.rs +++ b/src/path.rs @@ -2,7 +2,6 @@ //! for testing if a command with a given name can be found in the PATH, and various other //! path-related issues. -use crate::common::{wcs2osstring, wcs2zstring}; use crate::env::{EnvMode, EnvSetMode, EnvStack, Environment, FALLBACK_PATH}; use crate::expand::{HOME_DIRECTORY, expand_tilde}; use crate::flog::{flog, flogf}; @@ -10,6 +9,7 @@ use crate::wutil::{normalize_path, path_normalize_for_cd, waccess, wdirname, wstat}; use cfg_if::cfg_if; use errno::{Errno, errno, set_errno}; +use fish_wcstringutil::{wcs2osstring, wcs2zstring}; use libc::{EACCES, ENOENT, ENOTDIR, X_OK}; use nix::unistd::AccessFlags; use std::ffi::OsStr; diff --git a/src/screen.rs b/src/screen.rs index f5621f2e2..848ecb114 100644 --- a/src/screen.rs +++ b/src/screen.rs @@ -7,29 +7,16 @@ //! The current implementation is less smart than ncurses allows and can not for example move blocks //! of text around to handle text insertion. -use crate::editable_line::line_at_cursor; -use crate::key::ViewportPosition; -use crate::pager::{PAGER_MIN_HEIGHT, PageRendering, Pager}; -use std::cell::RefCell; -use std::collections::LinkedList; -use std::io::Write as _; -use std::num::NonZeroU16; -use std::ops::Range; -use std::sync::Mutex; -use std::sync::atomic::AtomicU32; -use std::time::SystemTime; - -use libc::{STDERR_FILENO, STDOUT_FILENO}; -use nix::sys::termios; - use crate::common::{ - get_ellipsis_char, get_omitted_newline_str, has_working_tty_timestamps, shell_modes, wcs2bytes, - write_loop, + get_ellipsis_char, get_omitted_newline_str, has_working_tty_timestamps, shell_modes, write_loop, }; +use crate::editable_line::line_at_cursor; use crate::env::Environment; use crate::flog::{flog, flogf}; use crate::global_safety::RelaxedAtomicBool; use crate::highlight::{HighlightColorResolver, HighlightRole, HighlightSpec}; +use crate::key::ViewportPosition; +use crate::pager::{PAGER_MIN_HEIGHT, PageRendering, Pager}; use crate::prelude::*; use crate::terminal::SgrTerminalCommand::EnterDimMode; use crate::terminal::TerminalCommand::{ @@ -40,7 +27,17 @@ use crate::termsize::Termsize; use crate::wutil::fstat; use fish_fallback::fish_wcwidth; -use fish_wcstringutil::{fish_wcwidth_visible, string_prefixes_string}; +use fish_wcstringutil::{fish_wcwidth_visible, string_prefixes_string, wcs2bytes}; +use libc::{STDERR_FILENO, STDOUT_FILENO}; +use nix::sys::termios; +use std::cell::RefCell; +use std::collections::LinkedList; +use std::io::Write as _; +use std::num::NonZeroU16; +use std::ops::Range; +use std::sync::Mutex; +use std::sync::atomic::AtomicU32; +use std::time::SystemTime; #[derive(Copy, Clone, Default)] pub enum CharOffset { diff --git a/src/terminal.rs b/src/terminal.rs index 0d3005149..d141ad826 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -1,5 +1,5 @@ // Generic output functions. -use crate::common::{self, EscapeStringStyle, escape_string, wcs2bytes, wcs2bytes_appending}; +use crate::common::{self, EscapeStringStyle, escape_string}; use crate::future_feature_flags::{self, FeatureFlag}; use crate::prelude::*; use crate::screen::{is_dumb, only_grayscale}; @@ -7,6 +7,7 @@ use crate::threads::MainThread; use bitflags::bitflags; use fish_color::{Color, Color24}; +use fish_wcstringutil::{wcs2bytes, wcs2bytes_appending}; use std::cell::{RefCell, RefMut}; use std::ops::{Deref, DerefMut}; use std::os::fd::RawFd; diff --git a/src/universal_notifier/inotify.rs b/src/universal_notifier/inotify.rs index 268d050ac..9ad971f38 100644 --- a/src/universal_notifier/inotify.rs +++ b/src/universal_notifier/inotify.rs @@ -1,8 +1,8 @@ -use crate::common::wcs2osstring; use crate::env_universal_common::default_vars_path; use crate::prelude::*; use crate::universal_notifier::UniversalNotifier; use crate::wutil::{wbasename, wdirname}; +use fish_wcstringutil::wcs2osstring; use nix::sys::inotify::{AddWatchFlags, InitFlags, Inotify}; use std::ffi::OsString; use std::os::fd::{AsFd as _, AsRawFd as _, RawFd}; diff --git a/src/universal_notifier/kqueue.rs b/src/universal_notifier/kqueue.rs index 4fab5dec7..82eadcb73 100644 --- a/src/universal_notifier/kqueue.rs +++ b/src/universal_notifier/kqueue.rs @@ -1,9 +1,9 @@ -use crate::common::wcs2osstring; use crate::env_universal_common::default_vars_path; use crate::flogf; use crate::prelude::*; use crate::universal_notifier::UniversalNotifier; use crate::wutil::wdirname; +use fish_wcstringutil::wcs2osstring; use nix::sys::event::{EvFlags, EventFilter, FilterFlag, KEvent, Kqueue}; use std::fs::File; use std::os::fd::AsFd; diff --git a/src/universal_notifier/test_helpers.rs b/src/universal_notifier/test_helpers.rs index bf82a8e14..5a4daf734 100644 --- a/src/universal_notifier/test_helpers.rs +++ b/src/universal_notifier/test_helpers.rs @@ -17,7 +17,7 @@ pub fn test_notifiers(notifiers: &[&dyn UniversalNotifier], fish_variables_path: // Helper to simulate modifying a file, using the atomic rename() approach. let modify_path = |path: &wstr| -> Result<(), std::io::Error> { - use crate::common::wcs2osstring; + use fish_wcstringutil::wcs2osstring; use std::fs; use std::io::Write as _; let path = wcs2osstring(path); diff --git a/src/wutil/dir_iter.rs b/src/wutil/dir_iter.rs index 894c38ffe..363d051ef 100644 --- a/src/wutil/dir_iter.rs +++ b/src/wutil/dir_iter.rs @@ -1,7 +1,8 @@ use super::wopendir; -use crate::common::{bytes2wcstring, wcs2zstring}; +use crate::common::bytes2wcstring; use crate::wutil::DevInode; use cfg_if::cfg_if; +use fish_wcstringutil::wcs2zstring; use fish_widestring::{WString, wstr}; use libc::{ EACCES, EIO, ELOOP, ENAMETOOLONG, ENODEV, ENOENT, ENOTDIR, S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, diff --git a/src/wutil/fileid.rs b/src/wutil/fileid.rs index 9a8a1e959..49a4b3305 100644 --- a/src/wutil/fileid.rs +++ b/src/wutil/fileid.rs @@ -1,5 +1,5 @@ -use crate::common::wcs2zstring; use crate::wutil::wstr; +use fish_wcstringutil::wcs2zstring; use std::ffi::{CStr, OsStr}; use std::fs::{self, File, Metadata}; use std::os::unix::prelude::*; diff --git a/src/wutil/mod.rs b/src/wutil/mod.rs index 130538f23..336e92817 100644 --- a/src/wutil/mod.rs +++ b/src/wutil/mod.rs @@ -7,13 +7,11 @@ pub mod wcstod; pub mod wcstoi; -use crate::common::{ - bytes2wcstring, fish_reserved_codepoint, osstr2wcstring, wcs2bytes, wcs2osstring, wcs2zstring, -}; +use crate::common::{bytes2wcstring, fish_reserved_codepoint, osstr2wcstring}; use crate::fds::BorrowedFdFile; use crate::flog; use errno::errno; -use fish_wcstringutil::{join_strings, str2bytes_callback}; +use fish_wcstringutil::{join_strings, str2bytes_callback, wcs2bytes, wcs2osstring, wcs2zstring}; use fish_widestring::{IntoCharIter, L, WExt as _, WString, wstr}; use nix::unistd::AccessFlags; use std::ffi::{CStr, OsStr};