1cdb3e2c8Sopenharmony_ci//! This crate allows interacting with the data stored by [`OsStr`] and 2cdb3e2c8Sopenharmony_ci//! [`OsString`], without resorting to panics or corruption for invalid UTF-8. 3cdb3e2c8Sopenharmony_ci//! Thus, methods can be used that are already defined on [`[u8]`][slice] and 4cdb3e2c8Sopenharmony_ci//! [`Vec<u8>`]. 5cdb3e2c8Sopenharmony_ci//! 6cdb3e2c8Sopenharmony_ci//! Typically, the only way to losslessly construct [`OsStr`] or [`OsString`] 7cdb3e2c8Sopenharmony_ci//! from a byte sequence is to use `OsStr::new(str::from_utf8(bytes)?)`, which 8cdb3e2c8Sopenharmony_ci//! requires the bytes to be valid in UTF-8. However, since this crate makes 9cdb3e2c8Sopenharmony_ci//! conversions directly between the platform encoding and raw bytes, even some 10cdb3e2c8Sopenharmony_ci//! strings invalid in UTF-8 can be converted. 11cdb3e2c8Sopenharmony_ci//! 12cdb3e2c8Sopenharmony_ci//! In most cases, [`RawOsStr`] and [`RawOsString`] should be used. 13cdb3e2c8Sopenharmony_ci//! [`OsStrBytes`] and [`OsStringBytes`] provide lower-level APIs that are 14cdb3e2c8Sopenharmony_ci//! easier to misuse. 15cdb3e2c8Sopenharmony_ci//! 16cdb3e2c8Sopenharmony_ci//! # Encoding 17cdb3e2c8Sopenharmony_ci//! 18cdb3e2c8Sopenharmony_ci//! The encoding of bytes returned or accepted by methods of this crate is 19cdb3e2c8Sopenharmony_ci//! intentionally left unspecified. It may vary for different platforms, so 20cdb3e2c8Sopenharmony_ci//! defining it would run contrary to the goal of generic string handling. 21cdb3e2c8Sopenharmony_ci//! However, the following invariants will always be upheld: 22cdb3e2c8Sopenharmony_ci//! 23cdb3e2c8Sopenharmony_ci//! - The encoding will be compatible with UTF-8. In particular, splitting an 24cdb3e2c8Sopenharmony_ci//! encoded byte sequence by a UTF-8–encoded character always produces 25cdb3e2c8Sopenharmony_ci//! other valid byte sequences. They can be re-encoded without error using 26cdb3e2c8Sopenharmony_ci//! [`RawOsString::into_os_string`] and similar methods. 27cdb3e2c8Sopenharmony_ci//! 28cdb3e2c8Sopenharmony_ci//! - All characters valid in platform strings are representable. [`OsStr`] and 29cdb3e2c8Sopenharmony_ci//! [`OsString`] can always be losslessly reconstructed from extracted bytes. 30cdb3e2c8Sopenharmony_ci//! 31cdb3e2c8Sopenharmony_ci//! Note that the chosen encoding may not match how Rust stores these strings 32cdb3e2c8Sopenharmony_ci//! internally, which is undocumented. For instance, the result of calling 33cdb3e2c8Sopenharmony_ci//! [`OsStr::len`] will not necessarily match the number of bytes this crate 34cdb3e2c8Sopenharmony_ci//! uses to represent the same string. 35cdb3e2c8Sopenharmony_ci//! 36cdb3e2c8Sopenharmony_ci//! Additionally, concatenation may yield unexpected results without a UTF-8 37cdb3e2c8Sopenharmony_ci//! separator. If two platform strings need to be concatenated, the only safe 38cdb3e2c8Sopenharmony_ci//! way to do so is using [`OsString::push`]. This limitation also makes it 39cdb3e2c8Sopenharmony_ci//! undesirable to use the bytes in interchange. 40cdb3e2c8Sopenharmony_ci//! 41cdb3e2c8Sopenharmony_ci//! Since this encoding can change between versions and platforms, it should 42cdb3e2c8Sopenharmony_ci//! not be used for storage. The standard library provides implementations of 43cdb3e2c8Sopenharmony_ci//! [`OsStrExt`] and [`OsStringExt`] for various platforms, which should be 44cdb3e2c8Sopenharmony_ci//! preferred for that use case. 45cdb3e2c8Sopenharmony_ci//! 46cdb3e2c8Sopenharmony_ci//! # User Input 47cdb3e2c8Sopenharmony_ci//! 48cdb3e2c8Sopenharmony_ci//! Traits in this crate should ideally not be used to convert byte sequences 49cdb3e2c8Sopenharmony_ci//! that did not originate from [`OsStr`] or a related struct. The encoding 50cdb3e2c8Sopenharmony_ci//! used by this crate is an implementation detail, so it does not make sense 51cdb3e2c8Sopenharmony_ci//! to expose it to users. 52cdb3e2c8Sopenharmony_ci//! 53cdb3e2c8Sopenharmony_ci//! Crate [bstr] offers some useful alternative methods, such as 54cdb3e2c8Sopenharmony_ci//! [`ByteSlice::to_os_str`] and [`ByteVec::into_os_string`], that are meant 55cdb3e2c8Sopenharmony_ci//! for user input. But, they reject some byte sequences used to represent 56cdb3e2c8Sopenharmony_ci//! valid platform strings, which would be undesirable for reliable path 57cdb3e2c8Sopenharmony_ci//! handling. They are best used only when accepting unknown input. 58cdb3e2c8Sopenharmony_ci//! 59cdb3e2c8Sopenharmony_ci//! This crate is meant to help when you already have an instance of [`OsStr`] 60cdb3e2c8Sopenharmony_ci//! and need to modify the data in a lossless way. 61cdb3e2c8Sopenharmony_ci//! 62cdb3e2c8Sopenharmony_ci//! # Features 63cdb3e2c8Sopenharmony_ci//! 64cdb3e2c8Sopenharmony_ci//! These features are optional and can be enabled or disabled in a 65cdb3e2c8Sopenharmony_ci//! "Cargo.toml" file. 66cdb3e2c8Sopenharmony_ci//! 67cdb3e2c8Sopenharmony_ci//! ### Default Features 68cdb3e2c8Sopenharmony_ci//! 69cdb3e2c8Sopenharmony_ci//! - **memchr** - 70cdb3e2c8Sopenharmony_ci//! Changes the implementation to use crate [memchr] for better performance. 71cdb3e2c8Sopenharmony_ci//! This feature is useless when "raw\_os\_str" is disabled. 72cdb3e2c8Sopenharmony_ci//! 73cdb3e2c8Sopenharmony_ci//! For more information, see [`RawOsStr`][memchr complexity]. 74cdb3e2c8Sopenharmony_ci//! 75cdb3e2c8Sopenharmony_ci//! - **raw\_os\_str** - 76cdb3e2c8Sopenharmony_ci//! Provides: 77cdb3e2c8Sopenharmony_ci//! - [`iter`] 78cdb3e2c8Sopenharmony_ci//! - [`Pattern`] 79cdb3e2c8Sopenharmony_ci//! - [`RawOsStr`] 80cdb3e2c8Sopenharmony_ci//! - [`RawOsStrCow`] 81cdb3e2c8Sopenharmony_ci//! - [`RawOsString`] 82cdb3e2c8Sopenharmony_ci//! 83cdb3e2c8Sopenharmony_ci//! ### Optional Features 84cdb3e2c8Sopenharmony_ci//! 85cdb3e2c8Sopenharmony_ci//! - **checked\_conversions** - 86cdb3e2c8Sopenharmony_ci//! Provides: 87cdb3e2c8Sopenharmony_ci//! - [`EncodingError`] 88cdb3e2c8Sopenharmony_ci//! - [`OsStrBytes::from_raw_bytes`] 89cdb3e2c8Sopenharmony_ci//! - [`OsStringBytes::from_raw_vec`] 90cdb3e2c8Sopenharmony_ci//! - [`RawOsStr::from_raw_bytes`] 91cdb3e2c8Sopenharmony_ci//! - [`RawOsString::from_raw_vec`] 92cdb3e2c8Sopenharmony_ci//! 93cdb3e2c8Sopenharmony_ci//! Because this feature should not be used in libraries, the 94cdb3e2c8Sopenharmony_ci//! "OS_STR_BYTES_CHECKED_CONVERSIONS" environment variable must be defined 95cdb3e2c8Sopenharmony_ci//! during compilation. 96cdb3e2c8Sopenharmony_ci//! 97cdb3e2c8Sopenharmony_ci//! - **print\_bytes** - 98cdb3e2c8Sopenharmony_ci//! Provides implementations of [`print_bytes::ToBytes`] for [`RawOsStr`] and 99cdb3e2c8Sopenharmony_ci//! [`RawOsString`]. 100cdb3e2c8Sopenharmony_ci//! 101cdb3e2c8Sopenharmony_ci//! - **uniquote** - 102cdb3e2c8Sopenharmony_ci//! Provides implementations of [`uniquote::Quote`] for [`RawOsStr`] and 103cdb3e2c8Sopenharmony_ci//! [`RawOsString`]. 104cdb3e2c8Sopenharmony_ci//! 105cdb3e2c8Sopenharmony_ci//! # Implementation 106cdb3e2c8Sopenharmony_ci//! 107cdb3e2c8Sopenharmony_ci//! Some methods return [`Cow`] to account for platform differences. However, 108cdb3e2c8Sopenharmony_ci//! no guarantee is made that the same variant of that enum will always be 109cdb3e2c8Sopenharmony_ci//! returned for the same platform. Whichever can be constructed most 110cdb3e2c8Sopenharmony_ci//! efficiently will be returned. 111cdb3e2c8Sopenharmony_ci//! 112cdb3e2c8Sopenharmony_ci//! All traits are [sealed], meaning that they can only be implemented by this 113cdb3e2c8Sopenharmony_ci//! crate. Otherwise, backward compatibility would be more difficult to 114cdb3e2c8Sopenharmony_ci//! maintain for new features. 115cdb3e2c8Sopenharmony_ci//! 116cdb3e2c8Sopenharmony_ci//! # Complexity 117cdb3e2c8Sopenharmony_ci//! 118cdb3e2c8Sopenharmony_ci//! Conversion method complexities will vary based on what functionality is 119cdb3e2c8Sopenharmony_ci//! available for the platform. At worst, they will all be linear, but some can 120cdb3e2c8Sopenharmony_ci//! take constant time. For example, [`RawOsString::into_os_string`] might be 121cdb3e2c8Sopenharmony_ci//! able to reuse its allocation. 122cdb3e2c8Sopenharmony_ci//! 123cdb3e2c8Sopenharmony_ci//! # Examples 124cdb3e2c8Sopenharmony_ci//! 125cdb3e2c8Sopenharmony_ci//! ``` 126cdb3e2c8Sopenharmony_ci//! # use std::io; 127cdb3e2c8Sopenharmony_ci//! # 128cdb3e2c8Sopenharmony_ci//! # #[cfg(feature = "raw_os_str")] 129cdb3e2c8Sopenharmony_ci//! # { 130cdb3e2c8Sopenharmony_ci//! # #[cfg(any())] 131cdb3e2c8Sopenharmony_ci//! use std::env; 132cdb3e2c8Sopenharmony_ci//! use std::fs; 133cdb3e2c8Sopenharmony_ci//! 134cdb3e2c8Sopenharmony_ci//! use os_str_bytes::RawOsStr; 135cdb3e2c8Sopenharmony_ci//! 136cdb3e2c8Sopenharmony_ci//! # mod env { 137cdb3e2c8Sopenharmony_ci//! # use std::env; 138cdb3e2c8Sopenharmony_ci//! # use std::ffi::OsString; 139cdb3e2c8Sopenharmony_ci//! # 140cdb3e2c8Sopenharmony_ci//! # pub fn args_os() -> impl Iterator<Item = OsString> { 141cdb3e2c8Sopenharmony_ci//! # let mut file = env::temp_dir(); 142cdb3e2c8Sopenharmony_ci//! # file.push("os_str_bytes\u{E9}.txt"); 143cdb3e2c8Sopenharmony_ci//! # return vec![OsString::new(), file.into_os_string()].into_iter(); 144cdb3e2c8Sopenharmony_ci//! # } 145cdb3e2c8Sopenharmony_ci//! # } 146cdb3e2c8Sopenharmony_ci//! # 147cdb3e2c8Sopenharmony_ci//! for file in env::args_os().skip(1) { 148cdb3e2c8Sopenharmony_ci//! if !RawOsStr::new(&file).starts_with('-') { 149cdb3e2c8Sopenharmony_ci//! let string = "Hello, world!"; 150cdb3e2c8Sopenharmony_ci//! fs::write(&file, string)?; 151cdb3e2c8Sopenharmony_ci//! assert_eq!(string, fs::read_to_string(file)?); 152cdb3e2c8Sopenharmony_ci//! } 153cdb3e2c8Sopenharmony_ci//! } 154cdb3e2c8Sopenharmony_ci//! # } 155cdb3e2c8Sopenharmony_ci//! # 156cdb3e2c8Sopenharmony_ci//! # Ok::<_, io::Error>(()) 157cdb3e2c8Sopenharmony_ci//! ``` 158cdb3e2c8Sopenharmony_ci//! 159cdb3e2c8Sopenharmony_ci//! [bstr]: https://crates.io/crates/bstr 160cdb3e2c8Sopenharmony_ci//! [`ByteSlice::to_os_str`]: https://docs.rs/bstr/0.2.12/bstr/trait.ByteSlice.html#method.to_os_str 161cdb3e2c8Sopenharmony_ci//! [`ByteVec::into_os_string`]: https://docs.rs/bstr/0.2.12/bstr/trait.ByteVec.html#method.into_os_string 162cdb3e2c8Sopenharmony_ci//! [memchr complexity]: RawOsStr#complexity 163cdb3e2c8Sopenharmony_ci//! [memchr]: https://crates.io/crates/memchr 164cdb3e2c8Sopenharmony_ci//! [`OsStrExt`]: ::std::os::unix::ffi::OsStrExt 165cdb3e2c8Sopenharmony_ci//! [`OsStringExt`]: ::std::os::unix::ffi::OsStringExt 166cdb3e2c8Sopenharmony_ci//! [sealed]: https://rust-lang.github.io/api-guidelines/future-proofing.html#c-sealed 167cdb3e2c8Sopenharmony_ci//! [print\_bytes]: https://crates.io/crates/print_bytes 168cdb3e2c8Sopenharmony_ci 169cdb3e2c8Sopenharmony_ci#![cfg_attr(not(feature = "checked_conversions"), allow(deprecated))] 170cdb3e2c8Sopenharmony_ci// Only require a nightly compiler when building documentation for docs.rs. 171cdb3e2c8Sopenharmony_ci// This is a private option that should not be used. 172cdb3e2c8Sopenharmony_ci// https://github.com/rust-lang/docs.rs/issues/147#issuecomment-389544407 173cdb3e2c8Sopenharmony_ci// https://github.com/dylni/os_str_bytes/issues/2 174cdb3e2c8Sopenharmony_ci#![cfg_attr(os_str_bytes_docs_rs, feature(doc_cfg))] 175cdb3e2c8Sopenharmony_ci// Nightly is also currently required for the SGX platform. 176cdb3e2c8Sopenharmony_ci#![cfg_attr( 177cdb3e2c8Sopenharmony_ci all(target_vendor = "fortanix", target_env = "sgx"), 178cdb3e2c8Sopenharmony_ci feature(sgx_platform) 179cdb3e2c8Sopenharmony_ci)] 180cdb3e2c8Sopenharmony_ci#![warn(unsafe_op_in_unsafe_fn)] 181cdb3e2c8Sopenharmony_ci#![warn(unused_results)] 182cdb3e2c8Sopenharmony_ci 183cdb3e2c8Sopenharmony_ciuse std::borrow::Cow; 184cdb3e2c8Sopenharmony_ciuse std::error::Error; 185cdb3e2c8Sopenharmony_ciuse std::ffi::OsStr; 186cdb3e2c8Sopenharmony_ciuse std::ffi::OsString; 187cdb3e2c8Sopenharmony_ciuse std::fmt; 188cdb3e2c8Sopenharmony_ciuse std::fmt::Display; 189cdb3e2c8Sopenharmony_ciuse std::fmt::Formatter; 190cdb3e2c8Sopenharmony_ciuse std::path::Path; 191cdb3e2c8Sopenharmony_ciuse std::path::PathBuf; 192cdb3e2c8Sopenharmony_ciuse std::result; 193cdb3e2c8Sopenharmony_ci 194cdb3e2c8Sopenharmony_cimacro_rules! if_checked_conversions { 195cdb3e2c8Sopenharmony_ci ( $($item:item)+ ) => { 196cdb3e2c8Sopenharmony_ci $( 197cdb3e2c8Sopenharmony_ci #[cfg(feature = "checked_conversions")] 198cdb3e2c8Sopenharmony_ci $item 199cdb3e2c8Sopenharmony_ci )+ 200cdb3e2c8Sopenharmony_ci }; 201cdb3e2c8Sopenharmony_ci} 202cdb3e2c8Sopenharmony_ci 203cdb3e2c8Sopenharmony_ci#[cfg(not(os_str_bytes_docs_rs))] 204cdb3e2c8Sopenharmony_ciif_checked_conversions! { 205cdb3e2c8Sopenharmony_ci const _: &str = env!( 206cdb3e2c8Sopenharmony_ci "OS_STR_BYTES_CHECKED_CONVERSIONS", 207cdb3e2c8Sopenharmony_ci "The 'OS_STR_BYTES_CHECKED_CONVERSIONS' environment variable must be \ 208cdb3e2c8Sopenharmony_ci defined to use the 'checked_conversions' feature.", 209cdb3e2c8Sopenharmony_ci ); 210cdb3e2c8Sopenharmony_ci} 211cdb3e2c8Sopenharmony_ci 212cdb3e2c8Sopenharmony_ci#[rustfmt::skip] 213cdb3e2c8Sopenharmony_cimacro_rules! deprecated_checked_conversion { 214cdb3e2c8Sopenharmony_ci ( $message:expr , $item:item ) => { 215cdb3e2c8Sopenharmony_ci #[cfg_attr( 216cdb3e2c8Sopenharmony_ci not(feature = "checked_conversions"), 217cdb3e2c8Sopenharmony_ci deprecated = $message 218cdb3e2c8Sopenharmony_ci )] 219cdb3e2c8Sopenharmony_ci $item 220cdb3e2c8Sopenharmony_ci }; 221cdb3e2c8Sopenharmony_ci} 222cdb3e2c8Sopenharmony_ci 223cdb3e2c8Sopenharmony_cimacro_rules! expect_encoded { 224cdb3e2c8Sopenharmony_ci ( $result:expr ) => { 225cdb3e2c8Sopenharmony_ci $result.expect("invalid raw bytes") 226cdb3e2c8Sopenharmony_ci }; 227cdb3e2c8Sopenharmony_ci} 228cdb3e2c8Sopenharmony_ci 229cdb3e2c8Sopenharmony_cimacro_rules! if_raw_str { 230cdb3e2c8Sopenharmony_ci ( $($item:item)+ ) => { 231cdb3e2c8Sopenharmony_ci $( 232cdb3e2c8Sopenharmony_ci #[cfg(feature = "raw_os_str")] 233cdb3e2c8Sopenharmony_ci $item 234cdb3e2c8Sopenharmony_ci )+ 235cdb3e2c8Sopenharmony_ci }; 236cdb3e2c8Sopenharmony_ci} 237cdb3e2c8Sopenharmony_ci 238cdb3e2c8Sopenharmony_ci#[cfg_attr( 239cdb3e2c8Sopenharmony_ci all(target_family = "wasm", target_os = "unknown"), 240cdb3e2c8Sopenharmony_ci path = "wasm/mod.rs" 241cdb3e2c8Sopenharmony_ci)] 242cdb3e2c8Sopenharmony_ci#[cfg_attr(windows, path = "windows/mod.rs")] 243cdb3e2c8Sopenharmony_ci#[cfg_attr( 244cdb3e2c8Sopenharmony_ci not(any(all(target_family = "wasm", target_os = "unknown"), windows)), 245cdb3e2c8Sopenharmony_ci path = "common/mod.rs" 246cdb3e2c8Sopenharmony_ci)] 247cdb3e2c8Sopenharmony_cimod imp; 248cdb3e2c8Sopenharmony_ci 249cdb3e2c8Sopenharmony_ci#[cfg(any( 250cdb3e2c8Sopenharmony_ci all( 251cdb3e2c8Sopenharmony_ci feature = "raw_os_str", 252cdb3e2c8Sopenharmony_ci target_family = "wasm", 253cdb3e2c8Sopenharmony_ci target_os = "unknown", 254cdb3e2c8Sopenharmony_ci ), 255cdb3e2c8Sopenharmony_ci windows, 256cdb3e2c8Sopenharmony_ci))] 257cdb3e2c8Sopenharmony_cimod util; 258cdb3e2c8Sopenharmony_ci 259cdb3e2c8Sopenharmony_ciif_raw_str! { 260cdb3e2c8Sopenharmony_ci pub mod iter; 261cdb3e2c8Sopenharmony_ci 262cdb3e2c8Sopenharmony_ci mod pattern; 263cdb3e2c8Sopenharmony_ci pub use pattern::Pattern; 264cdb3e2c8Sopenharmony_ci 265cdb3e2c8Sopenharmony_ci mod raw_str; 266cdb3e2c8Sopenharmony_ci pub use raw_str::RawOsStr; 267cdb3e2c8Sopenharmony_ci pub use raw_str::RawOsStrCow; 268cdb3e2c8Sopenharmony_ci pub use raw_str::RawOsString; 269cdb3e2c8Sopenharmony_ci} 270cdb3e2c8Sopenharmony_ci 271cdb3e2c8Sopenharmony_cideprecated_checked_conversion! { 272cdb3e2c8Sopenharmony_ci "use `OsStrBytes::assert_from_raw_bytes` or \ 273cdb3e2c8Sopenharmony_ci `OsStringBytes::assert_from_raw_vec` instead, or enable the \ 274cdb3e2c8Sopenharmony_ci 'checked_conversions' feature", 275cdb3e2c8Sopenharmony_ci /// The error that occurs when a byte sequence is not representable in the 276cdb3e2c8Sopenharmony_ci /// platform encoding. 277cdb3e2c8Sopenharmony_ci /// 278cdb3e2c8Sopenharmony_ci /// [`Result::unwrap`] should almost always be called on results containing 279cdb3e2c8Sopenharmony_ci /// this error. It should be known whether or not byte sequences are 280cdb3e2c8Sopenharmony_ci /// properly encoded for the platform, since [the module-level 281cdb3e2c8Sopenharmony_ci /// documentation][encoding] discourages using encoded bytes in 282cdb3e2c8Sopenharmony_ci /// interchange. Results are returned primarily to make panicking behavior 283cdb3e2c8Sopenharmony_ci /// explicit. 284cdb3e2c8Sopenharmony_ci /// 285cdb3e2c8Sopenharmony_ci /// On Unix, this error is never returned, but [`OsStrExt`] or 286cdb3e2c8Sopenharmony_ci /// [`OsStringExt`] should be used instead if that needs to be guaranteed. 287cdb3e2c8Sopenharmony_ci /// 288cdb3e2c8Sopenharmony_ci /// [encoding]: self#encoding 289cdb3e2c8Sopenharmony_ci /// [`OsStrExt`]: ::std::os::unix::ffi::OsStrExt 290cdb3e2c8Sopenharmony_ci /// [`OsStringExt`]: ::std::os::unix::ffi::OsStringExt 291cdb3e2c8Sopenharmony_ci /// [`Result::unwrap`]: ::std::result::Result::unwrap 292cdb3e2c8Sopenharmony_ci #[derive(Clone, Debug, Eq, PartialEq)] 293cdb3e2c8Sopenharmony_ci #[cfg_attr( 294cdb3e2c8Sopenharmony_ci os_str_bytes_docs_rs, 295cdb3e2c8Sopenharmony_ci doc(cfg(feature = "checked_conversions")) 296cdb3e2c8Sopenharmony_ci )] 297cdb3e2c8Sopenharmony_ci pub struct EncodingError(imp::EncodingError); 298cdb3e2c8Sopenharmony_ci} 299cdb3e2c8Sopenharmony_ci 300cdb3e2c8Sopenharmony_ciimpl Display for EncodingError { 301cdb3e2c8Sopenharmony_ci #[inline] 302cdb3e2c8Sopenharmony_ci fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 303cdb3e2c8Sopenharmony_ci self.0.fmt(f) 304cdb3e2c8Sopenharmony_ci } 305cdb3e2c8Sopenharmony_ci} 306cdb3e2c8Sopenharmony_ci 307cdb3e2c8Sopenharmony_ciimpl Error for EncodingError {} 308cdb3e2c8Sopenharmony_ci 309cdb3e2c8Sopenharmony_citype Result<T> = result::Result<T, EncodingError>; 310cdb3e2c8Sopenharmony_ci 311cdb3e2c8Sopenharmony_cifn from_raw_bytes<'a, S>( 312cdb3e2c8Sopenharmony_ci string: S, 313cdb3e2c8Sopenharmony_ci) -> result::Result<Cow<'a, OsStr>, imp::EncodingError> 314cdb3e2c8Sopenharmony_ciwhere 315cdb3e2c8Sopenharmony_ci S: Into<Cow<'a, [u8]>>, 316cdb3e2c8Sopenharmony_ci{ 317cdb3e2c8Sopenharmony_ci match string.into() { 318cdb3e2c8Sopenharmony_ci Cow::Borrowed(string) => imp::os_str_from_bytes(string), 319cdb3e2c8Sopenharmony_ci Cow::Owned(string) => imp::os_string_from_vec(string).map(Cow::Owned), 320cdb3e2c8Sopenharmony_ci } 321cdb3e2c8Sopenharmony_ci} 322cdb3e2c8Sopenharmony_ci 323cdb3e2c8Sopenharmony_cifn cow_os_str_into_path(string: Cow<'_, OsStr>) -> Cow<'_, Path> { 324cdb3e2c8Sopenharmony_ci match string { 325cdb3e2c8Sopenharmony_ci Cow::Borrowed(string) => Cow::Borrowed(Path::new(string)), 326cdb3e2c8Sopenharmony_ci Cow::Owned(string) => Cow::Owned(string.into()), 327cdb3e2c8Sopenharmony_ci } 328cdb3e2c8Sopenharmony_ci} 329cdb3e2c8Sopenharmony_ci 330cdb3e2c8Sopenharmony_ci/// A platform agnostic variant of [`OsStrExt`]. 331cdb3e2c8Sopenharmony_ci/// 332cdb3e2c8Sopenharmony_ci/// For more information, see [the module-level documentation][module]. 333cdb3e2c8Sopenharmony_ci/// 334cdb3e2c8Sopenharmony_ci/// [module]: self 335cdb3e2c8Sopenharmony_ci/// [`OsStrExt`]: ::std::os::unix::ffi::OsStrExt 336cdb3e2c8Sopenharmony_cipub trait OsStrBytes: private::Sealed + ToOwned { 337cdb3e2c8Sopenharmony_ci /// Converts a byte string into an equivalent platform-native string. 338cdb3e2c8Sopenharmony_ci /// 339cdb3e2c8Sopenharmony_ci /// # Panics 340cdb3e2c8Sopenharmony_ci /// 341cdb3e2c8Sopenharmony_ci /// Panics if the string is not valid for the [unspecified encoding] used 342cdb3e2c8Sopenharmony_ci /// by this crate. 343cdb3e2c8Sopenharmony_ci /// 344cdb3e2c8Sopenharmony_ci /// # Examples 345cdb3e2c8Sopenharmony_ci /// 346cdb3e2c8Sopenharmony_ci /// ``` 347cdb3e2c8Sopenharmony_ci /// use std::env; 348cdb3e2c8Sopenharmony_ci /// use std::ffi::OsStr; 349cdb3e2c8Sopenharmony_ci /// # use std::io; 350cdb3e2c8Sopenharmony_ci /// 351cdb3e2c8Sopenharmony_ci /// use os_str_bytes::OsStrBytes; 352cdb3e2c8Sopenharmony_ci /// 353cdb3e2c8Sopenharmony_ci /// let os_string = env::current_exe()?; 354cdb3e2c8Sopenharmony_ci /// let os_bytes = os_string.to_raw_bytes(); 355cdb3e2c8Sopenharmony_ci /// assert_eq!(os_string, OsStr::assert_from_raw_bytes(os_bytes)); 356cdb3e2c8Sopenharmony_ci /// # 357cdb3e2c8Sopenharmony_ci /// # Ok::<_, io::Error>(()) 358cdb3e2c8Sopenharmony_ci /// ``` 359cdb3e2c8Sopenharmony_ci /// 360cdb3e2c8Sopenharmony_ci /// [unspecified encoding]: self#encoding 361cdb3e2c8Sopenharmony_ci #[must_use = "method should not be used for validation"] 362cdb3e2c8Sopenharmony_ci #[track_caller] 363cdb3e2c8Sopenharmony_ci fn assert_from_raw_bytes<'a, S>(string: S) -> Cow<'a, Self> 364cdb3e2c8Sopenharmony_ci where 365cdb3e2c8Sopenharmony_ci S: Into<Cow<'a, [u8]>>; 366cdb3e2c8Sopenharmony_ci 367cdb3e2c8Sopenharmony_ci deprecated_checked_conversion! { 368cdb3e2c8Sopenharmony_ci "use `assert_from_raw_bytes` instead, or enable the \ 369cdb3e2c8Sopenharmony_ci 'checked_conversions' feature", 370cdb3e2c8Sopenharmony_ci /// Converts a byte string into an equivalent platform-native string. 371cdb3e2c8Sopenharmony_ci /// 372cdb3e2c8Sopenharmony_ci /// [`assert_from_raw_bytes`] should almost always be used instead. For 373cdb3e2c8Sopenharmony_ci /// more information, see [`EncodingError`]. 374cdb3e2c8Sopenharmony_ci /// 375cdb3e2c8Sopenharmony_ci /// # Errors 376cdb3e2c8Sopenharmony_ci /// 377cdb3e2c8Sopenharmony_ci /// See documentation for [`EncodingError`]. 378cdb3e2c8Sopenharmony_ci /// 379cdb3e2c8Sopenharmony_ci /// # Examples 380cdb3e2c8Sopenharmony_ci /// 381cdb3e2c8Sopenharmony_ci /// ``` 382cdb3e2c8Sopenharmony_ci /// use std::env; 383cdb3e2c8Sopenharmony_ci /// use std::ffi::OsStr; 384cdb3e2c8Sopenharmony_ci /// # use std::io; 385cdb3e2c8Sopenharmony_ci /// 386cdb3e2c8Sopenharmony_ci /// use os_str_bytes::OsStrBytes; 387cdb3e2c8Sopenharmony_ci /// 388cdb3e2c8Sopenharmony_ci /// let os_string = env::current_exe()?; 389cdb3e2c8Sopenharmony_ci /// let os_bytes = os_string.to_raw_bytes(); 390cdb3e2c8Sopenharmony_ci /// assert_eq!(os_string, OsStr::from_raw_bytes(os_bytes).unwrap()); 391cdb3e2c8Sopenharmony_ci /// # 392cdb3e2c8Sopenharmony_ci /// # Ok::<_, io::Error>(()) 393cdb3e2c8Sopenharmony_ci /// ``` 394cdb3e2c8Sopenharmony_ci /// 395cdb3e2c8Sopenharmony_ci /// [`assert_from_raw_bytes`]: Self::assert_from_raw_bytes 396cdb3e2c8Sopenharmony_ci #[cfg_attr( 397cdb3e2c8Sopenharmony_ci os_str_bytes_docs_rs, 398cdb3e2c8Sopenharmony_ci doc(cfg(feature = "checked_conversions")) 399cdb3e2c8Sopenharmony_ci )] 400cdb3e2c8Sopenharmony_ci fn from_raw_bytes<'a, S>(string: S) -> Result<Cow<'a, Self>> 401cdb3e2c8Sopenharmony_ci where 402cdb3e2c8Sopenharmony_ci S: Into<Cow<'a, [u8]>>; 403cdb3e2c8Sopenharmony_ci } 404cdb3e2c8Sopenharmony_ci 405cdb3e2c8Sopenharmony_ci /// Converts a platform-native string into an equivalent byte string. 406cdb3e2c8Sopenharmony_ci /// 407cdb3e2c8Sopenharmony_ci /// The returned string will use an [unspecified encoding]. 408cdb3e2c8Sopenharmony_ci /// 409cdb3e2c8Sopenharmony_ci /// # Examples 410cdb3e2c8Sopenharmony_ci /// 411cdb3e2c8Sopenharmony_ci /// ``` 412cdb3e2c8Sopenharmony_ci /// use std::ffi::OsStr; 413cdb3e2c8Sopenharmony_ci /// 414cdb3e2c8Sopenharmony_ci /// use os_str_bytes::OsStrBytes; 415cdb3e2c8Sopenharmony_ci /// 416cdb3e2c8Sopenharmony_ci /// let string = "foobar"; 417cdb3e2c8Sopenharmony_ci /// let os_string = OsStr::new(string); 418cdb3e2c8Sopenharmony_ci /// assert_eq!(string.as_bytes(), &*os_string.to_raw_bytes()); 419cdb3e2c8Sopenharmony_ci /// ``` 420cdb3e2c8Sopenharmony_ci /// 421cdb3e2c8Sopenharmony_ci /// [unspecified encoding]: self#encoding 422cdb3e2c8Sopenharmony_ci #[must_use] 423cdb3e2c8Sopenharmony_ci fn to_raw_bytes(&self) -> Cow<'_, [u8]>; 424cdb3e2c8Sopenharmony_ci} 425cdb3e2c8Sopenharmony_ci 426cdb3e2c8Sopenharmony_ciimpl OsStrBytes for OsStr { 427cdb3e2c8Sopenharmony_ci #[inline] 428cdb3e2c8Sopenharmony_ci fn assert_from_raw_bytes<'a, S>(string: S) -> Cow<'a, Self> 429cdb3e2c8Sopenharmony_ci where 430cdb3e2c8Sopenharmony_ci S: Into<Cow<'a, [u8]>>, 431cdb3e2c8Sopenharmony_ci { 432cdb3e2c8Sopenharmony_ci expect_encoded!(from_raw_bytes(string)) 433cdb3e2c8Sopenharmony_ci } 434cdb3e2c8Sopenharmony_ci 435cdb3e2c8Sopenharmony_ci #[inline] 436cdb3e2c8Sopenharmony_ci fn from_raw_bytes<'a, S>(string: S) -> Result<Cow<'a, Self>> 437cdb3e2c8Sopenharmony_ci where 438cdb3e2c8Sopenharmony_ci S: Into<Cow<'a, [u8]>>, 439cdb3e2c8Sopenharmony_ci { 440cdb3e2c8Sopenharmony_ci from_raw_bytes(string).map_err(EncodingError) 441cdb3e2c8Sopenharmony_ci } 442cdb3e2c8Sopenharmony_ci 443cdb3e2c8Sopenharmony_ci #[inline] 444cdb3e2c8Sopenharmony_ci fn to_raw_bytes(&self) -> Cow<'_, [u8]> { 445cdb3e2c8Sopenharmony_ci imp::os_str_to_bytes(self) 446cdb3e2c8Sopenharmony_ci } 447cdb3e2c8Sopenharmony_ci} 448cdb3e2c8Sopenharmony_ci 449cdb3e2c8Sopenharmony_ciimpl OsStrBytes for Path { 450cdb3e2c8Sopenharmony_ci #[inline] 451cdb3e2c8Sopenharmony_ci fn assert_from_raw_bytes<'a, S>(string: S) -> Cow<'a, Self> 452cdb3e2c8Sopenharmony_ci where 453cdb3e2c8Sopenharmony_ci S: Into<Cow<'a, [u8]>>, 454cdb3e2c8Sopenharmony_ci { 455cdb3e2c8Sopenharmony_ci cow_os_str_into_path(OsStr::assert_from_raw_bytes(string)) 456cdb3e2c8Sopenharmony_ci } 457cdb3e2c8Sopenharmony_ci 458cdb3e2c8Sopenharmony_ci #[inline] 459cdb3e2c8Sopenharmony_ci fn from_raw_bytes<'a, S>(string: S) -> Result<Cow<'a, Self>> 460cdb3e2c8Sopenharmony_ci where 461cdb3e2c8Sopenharmony_ci S: Into<Cow<'a, [u8]>>, 462cdb3e2c8Sopenharmony_ci { 463cdb3e2c8Sopenharmony_ci OsStr::from_raw_bytes(string).map(cow_os_str_into_path) 464cdb3e2c8Sopenharmony_ci } 465cdb3e2c8Sopenharmony_ci 466cdb3e2c8Sopenharmony_ci #[inline] 467cdb3e2c8Sopenharmony_ci fn to_raw_bytes(&self) -> Cow<'_, [u8]> { 468cdb3e2c8Sopenharmony_ci self.as_os_str().to_raw_bytes() 469cdb3e2c8Sopenharmony_ci } 470cdb3e2c8Sopenharmony_ci} 471cdb3e2c8Sopenharmony_ci 472cdb3e2c8Sopenharmony_ci/// A platform agnostic variant of [`OsStringExt`]. 473cdb3e2c8Sopenharmony_ci/// 474cdb3e2c8Sopenharmony_ci/// For more information, see [the module-level documentation][module]. 475cdb3e2c8Sopenharmony_ci/// 476cdb3e2c8Sopenharmony_ci/// [module]: self 477cdb3e2c8Sopenharmony_ci/// [`OsStringExt`]: ::std::os::unix::ffi::OsStringExt 478cdb3e2c8Sopenharmony_cipub trait OsStringBytes: private::Sealed + Sized { 479cdb3e2c8Sopenharmony_ci /// Converts a byte string into an equivalent platform-native string. 480cdb3e2c8Sopenharmony_ci /// 481cdb3e2c8Sopenharmony_ci /// # Panics 482cdb3e2c8Sopenharmony_ci /// 483cdb3e2c8Sopenharmony_ci /// Panics if the string is not valid for the [unspecified encoding] used 484cdb3e2c8Sopenharmony_ci /// by this crate. 485cdb3e2c8Sopenharmony_ci /// 486cdb3e2c8Sopenharmony_ci /// # Examples 487cdb3e2c8Sopenharmony_ci /// 488cdb3e2c8Sopenharmony_ci /// ``` 489cdb3e2c8Sopenharmony_ci /// use std::env; 490cdb3e2c8Sopenharmony_ci /// use std::ffi::OsString; 491cdb3e2c8Sopenharmony_ci /// # use std::io; 492cdb3e2c8Sopenharmony_ci /// 493cdb3e2c8Sopenharmony_ci /// use os_str_bytes::OsStringBytes; 494cdb3e2c8Sopenharmony_ci /// 495cdb3e2c8Sopenharmony_ci /// let os_string = env::current_exe()?; 496cdb3e2c8Sopenharmony_ci /// let os_bytes = os_string.clone().into_raw_vec(); 497cdb3e2c8Sopenharmony_ci /// assert_eq!(os_string, OsString::assert_from_raw_vec(os_bytes)); 498cdb3e2c8Sopenharmony_ci /// # 499cdb3e2c8Sopenharmony_ci /// # Ok::<_, io::Error>(()) 500cdb3e2c8Sopenharmony_ci /// ``` 501cdb3e2c8Sopenharmony_ci /// 502cdb3e2c8Sopenharmony_ci /// [unspecified encoding]: self#encoding 503cdb3e2c8Sopenharmony_ci #[must_use = "method should not be used for validation"] 504cdb3e2c8Sopenharmony_ci #[track_caller] 505cdb3e2c8Sopenharmony_ci fn assert_from_raw_vec(string: Vec<u8>) -> Self; 506cdb3e2c8Sopenharmony_ci 507cdb3e2c8Sopenharmony_ci deprecated_checked_conversion! { 508cdb3e2c8Sopenharmony_ci "use `assert_from_raw_vec` instead, or enable the \ 509cdb3e2c8Sopenharmony_ci 'checked_conversions' feature", 510cdb3e2c8Sopenharmony_ci /// Converts a byte string into an equivalent platform-native string. 511cdb3e2c8Sopenharmony_ci /// 512cdb3e2c8Sopenharmony_ci /// [`assert_from_raw_vec`] should almost always be used instead. For 513cdb3e2c8Sopenharmony_ci /// more information, see [`EncodingError`]. 514cdb3e2c8Sopenharmony_ci /// 515cdb3e2c8Sopenharmony_ci /// # Errors 516cdb3e2c8Sopenharmony_ci /// 517cdb3e2c8Sopenharmony_ci /// See documentation for [`EncodingError`]. 518cdb3e2c8Sopenharmony_ci /// 519cdb3e2c8Sopenharmony_ci /// # Examples 520cdb3e2c8Sopenharmony_ci /// 521cdb3e2c8Sopenharmony_ci /// ``` 522cdb3e2c8Sopenharmony_ci /// use std::env; 523cdb3e2c8Sopenharmony_ci /// use std::ffi::OsString; 524cdb3e2c8Sopenharmony_ci /// # use std::io; 525cdb3e2c8Sopenharmony_ci /// 526cdb3e2c8Sopenharmony_ci /// use os_str_bytes::OsStringBytes; 527cdb3e2c8Sopenharmony_ci /// 528cdb3e2c8Sopenharmony_ci /// let os_string = env::current_exe()?; 529cdb3e2c8Sopenharmony_ci /// let os_bytes = os_string.clone().into_raw_vec(); 530cdb3e2c8Sopenharmony_ci /// assert_eq!(os_string, OsString::from_raw_vec(os_bytes).unwrap()); 531cdb3e2c8Sopenharmony_ci /// # 532cdb3e2c8Sopenharmony_ci /// # Ok::<_, io::Error>(()) 533cdb3e2c8Sopenharmony_ci /// ``` 534cdb3e2c8Sopenharmony_ci /// 535cdb3e2c8Sopenharmony_ci /// [`assert_from_raw_vec`]: Self::assert_from_raw_vec 536cdb3e2c8Sopenharmony_ci #[cfg_attr( 537cdb3e2c8Sopenharmony_ci os_str_bytes_docs_rs, 538cdb3e2c8Sopenharmony_ci doc(cfg(feature = "checked_conversions")) 539cdb3e2c8Sopenharmony_ci )] 540cdb3e2c8Sopenharmony_ci fn from_raw_vec(string: Vec<u8>) -> Result<Self>; 541cdb3e2c8Sopenharmony_ci } 542cdb3e2c8Sopenharmony_ci 543cdb3e2c8Sopenharmony_ci /// Converts a platform-native string into an equivalent byte string. 544cdb3e2c8Sopenharmony_ci /// 545cdb3e2c8Sopenharmony_ci /// The returned string will use an [unspecified encoding]. 546cdb3e2c8Sopenharmony_ci /// 547cdb3e2c8Sopenharmony_ci /// # Examples 548cdb3e2c8Sopenharmony_ci /// 549cdb3e2c8Sopenharmony_ci /// ``` 550cdb3e2c8Sopenharmony_ci /// use std::ffi::OsString; 551cdb3e2c8Sopenharmony_ci /// 552cdb3e2c8Sopenharmony_ci /// use os_str_bytes::OsStringBytes; 553cdb3e2c8Sopenharmony_ci /// 554cdb3e2c8Sopenharmony_ci /// let string = "foobar".to_owned(); 555cdb3e2c8Sopenharmony_ci /// let os_string: OsString = string.clone().into(); 556cdb3e2c8Sopenharmony_ci /// assert_eq!(string.into_bytes(), os_string.into_raw_vec()); 557cdb3e2c8Sopenharmony_ci /// ``` 558cdb3e2c8Sopenharmony_ci /// 559cdb3e2c8Sopenharmony_ci /// [unspecified encoding]: self#encoding 560cdb3e2c8Sopenharmony_ci #[must_use] 561cdb3e2c8Sopenharmony_ci fn into_raw_vec(self) -> Vec<u8>; 562cdb3e2c8Sopenharmony_ci} 563cdb3e2c8Sopenharmony_ci 564cdb3e2c8Sopenharmony_ciimpl OsStringBytes for OsString { 565cdb3e2c8Sopenharmony_ci #[inline] 566cdb3e2c8Sopenharmony_ci fn assert_from_raw_vec(string: Vec<u8>) -> Self { 567cdb3e2c8Sopenharmony_ci expect_encoded!(imp::os_string_from_vec(string)) 568cdb3e2c8Sopenharmony_ci } 569cdb3e2c8Sopenharmony_ci 570cdb3e2c8Sopenharmony_ci #[inline] 571cdb3e2c8Sopenharmony_ci fn from_raw_vec(string: Vec<u8>) -> Result<Self> { 572cdb3e2c8Sopenharmony_ci imp::os_string_from_vec(string).map_err(EncodingError) 573cdb3e2c8Sopenharmony_ci } 574cdb3e2c8Sopenharmony_ci 575cdb3e2c8Sopenharmony_ci #[inline] 576cdb3e2c8Sopenharmony_ci fn into_raw_vec(self) -> Vec<u8> { 577cdb3e2c8Sopenharmony_ci imp::os_string_into_vec(self) 578cdb3e2c8Sopenharmony_ci } 579cdb3e2c8Sopenharmony_ci} 580cdb3e2c8Sopenharmony_ci 581cdb3e2c8Sopenharmony_ciimpl OsStringBytes for PathBuf { 582cdb3e2c8Sopenharmony_ci #[inline] 583cdb3e2c8Sopenharmony_ci fn assert_from_raw_vec(string: Vec<u8>) -> Self { 584cdb3e2c8Sopenharmony_ci OsString::assert_from_raw_vec(string).into() 585cdb3e2c8Sopenharmony_ci } 586cdb3e2c8Sopenharmony_ci 587cdb3e2c8Sopenharmony_ci #[inline] 588cdb3e2c8Sopenharmony_ci fn from_raw_vec(string: Vec<u8>) -> Result<Self> { 589cdb3e2c8Sopenharmony_ci OsString::from_raw_vec(string).map(Into::into) 590cdb3e2c8Sopenharmony_ci } 591cdb3e2c8Sopenharmony_ci 592cdb3e2c8Sopenharmony_ci #[inline] 593cdb3e2c8Sopenharmony_ci fn into_raw_vec(self) -> Vec<u8> { 594cdb3e2c8Sopenharmony_ci self.into_os_string().into_raw_vec() 595cdb3e2c8Sopenharmony_ci } 596cdb3e2c8Sopenharmony_ci} 597cdb3e2c8Sopenharmony_ci 598cdb3e2c8Sopenharmony_cimod private { 599cdb3e2c8Sopenharmony_ci use std::ffi::OsStr; 600cdb3e2c8Sopenharmony_ci use std::ffi::OsString; 601cdb3e2c8Sopenharmony_ci use std::path::Path; 602cdb3e2c8Sopenharmony_ci use std::path::PathBuf; 603cdb3e2c8Sopenharmony_ci 604cdb3e2c8Sopenharmony_ci if_raw_str! { 605cdb3e2c8Sopenharmony_ci use std::borrow::Cow; 606cdb3e2c8Sopenharmony_ci 607cdb3e2c8Sopenharmony_ci use super::RawOsStr; 608cdb3e2c8Sopenharmony_ci } 609cdb3e2c8Sopenharmony_ci 610cdb3e2c8Sopenharmony_ci pub trait Sealed {} 611cdb3e2c8Sopenharmony_ci 612cdb3e2c8Sopenharmony_ci impl Sealed for char {} 613cdb3e2c8Sopenharmony_ci impl Sealed for OsStr {} 614cdb3e2c8Sopenharmony_ci impl Sealed for OsString {} 615cdb3e2c8Sopenharmony_ci impl Sealed for Path {} 616cdb3e2c8Sopenharmony_ci impl Sealed for PathBuf {} 617cdb3e2c8Sopenharmony_ci impl Sealed for &str {} 618cdb3e2c8Sopenharmony_ci impl Sealed for &String {} 619cdb3e2c8Sopenharmony_ci 620cdb3e2c8Sopenharmony_ci if_raw_str! { 621cdb3e2c8Sopenharmony_ci impl Sealed for Cow<'_, RawOsStr> {} 622cdb3e2c8Sopenharmony_ci } 623cdb3e2c8Sopenharmony_ci} 624