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&ndash;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