1cdb3e2c8Sopenharmony_ciuse std::borrow::Borrow;
2cdb3e2c8Sopenharmony_ciuse std::borrow::Cow;
3cdb3e2c8Sopenharmony_ciuse std::borrow::ToOwned;
4cdb3e2c8Sopenharmony_ciuse std::ffi::OsStr;
5cdb3e2c8Sopenharmony_ciuse std::ffi::OsString;
6cdb3e2c8Sopenharmony_ciuse std::fmt;
7cdb3e2c8Sopenharmony_ciuse std::fmt::Debug;
8cdb3e2c8Sopenharmony_ciuse std::fmt::Display;
9cdb3e2c8Sopenharmony_ciuse std::fmt::Formatter;
10cdb3e2c8Sopenharmony_ciuse std::mem;
11cdb3e2c8Sopenharmony_ciuse std::ops::Deref;
12cdb3e2c8Sopenharmony_ciuse std::ops::Index;
13cdb3e2c8Sopenharmony_ciuse std::ops::Range;
14cdb3e2c8Sopenharmony_ciuse std::ops::RangeFrom;
15cdb3e2c8Sopenharmony_ciuse std::ops::RangeFull;
16cdb3e2c8Sopenharmony_ciuse std::ops::RangeInclusive;
17cdb3e2c8Sopenharmony_ciuse std::ops::RangeTo;
18cdb3e2c8Sopenharmony_ciuse std::ops::RangeToInclusive;
19cdb3e2c8Sopenharmony_ciuse std::result;
20cdb3e2c8Sopenharmony_ciuse std::str;
21cdb3e2c8Sopenharmony_ci
22cdb3e2c8Sopenharmony_ci#[cfg(feature = "memchr")]
23cdb3e2c8Sopenharmony_ciuse memchr::memmem::find;
24cdb3e2c8Sopenharmony_ci#[cfg(feature = "memchr")]
25cdb3e2c8Sopenharmony_ciuse memchr::memmem::rfind;
26cdb3e2c8Sopenharmony_ci
27cdb3e2c8Sopenharmony_ciuse super::imp;
28cdb3e2c8Sopenharmony_ciuse super::imp::raw;
29cdb3e2c8Sopenharmony_ciuse super::iter::Split;
30cdb3e2c8Sopenharmony_ciuse super::pattern::Encoded as EncodedPattern;
31cdb3e2c8Sopenharmony_ciuse super::private;
32cdb3e2c8Sopenharmony_ciuse super::Pattern;
33cdb3e2c8Sopenharmony_ci
34cdb3e2c8Sopenharmony_ciif_checked_conversions! {
35cdb3e2c8Sopenharmony_ci    use super::EncodingError;
36cdb3e2c8Sopenharmony_ci    use super::Result;
37cdb3e2c8Sopenharmony_ci}
38cdb3e2c8Sopenharmony_ci
39cdb3e2c8Sopenharmony_ci#[cfg(not(feature = "memchr"))]
40cdb3e2c8Sopenharmony_cifn find(string: &[u8], pat: &[u8]) -> Option<usize> {
41cdb3e2c8Sopenharmony_ci    (0..=string.len().checked_sub(pat.len())?)
42cdb3e2c8Sopenharmony_ci        .find(|&x| string[x..].starts_with(pat))
43cdb3e2c8Sopenharmony_ci}
44cdb3e2c8Sopenharmony_ci
45cdb3e2c8Sopenharmony_ci#[cfg(not(feature = "memchr"))]
46cdb3e2c8Sopenharmony_cifn rfind(string: &[u8], pat: &[u8]) -> Option<usize> {
47cdb3e2c8Sopenharmony_ci    (pat.len()..=string.len())
48cdb3e2c8Sopenharmony_ci        .rfind(|&x| string[..x].ends_with(pat))
49cdb3e2c8Sopenharmony_ci        .map(|x| x - pat.len())
50cdb3e2c8Sopenharmony_ci}
51cdb3e2c8Sopenharmony_ci
52cdb3e2c8Sopenharmony_ci#[allow(clippy::missing_safety_doc)]
53cdb3e2c8Sopenharmony_ciunsafe trait TransmuteBox {
54cdb3e2c8Sopenharmony_ci    fn transmute_box<R>(self: Box<Self>) -> Box<R>
55cdb3e2c8Sopenharmony_ci    where
56cdb3e2c8Sopenharmony_ci        R: ?Sized + TransmuteBox,
57cdb3e2c8Sopenharmony_ci    {
58cdb3e2c8Sopenharmony_ci        let value = Box::into_raw(self);
59cdb3e2c8Sopenharmony_ci        // SAFETY: This trait is only implemented for types that can be
60cdb3e2c8Sopenharmony_ci        // transmuted.
61cdb3e2c8Sopenharmony_ci        unsafe { Box::from_raw(mem::transmute_copy(&value)) }
62cdb3e2c8Sopenharmony_ci    }
63cdb3e2c8Sopenharmony_ci}
64cdb3e2c8Sopenharmony_ci
65cdb3e2c8Sopenharmony_ci// SAFETY: This struct has a layout that makes this operation safe.
66cdb3e2c8Sopenharmony_ciunsafe impl TransmuteBox for RawOsStr {}
67cdb3e2c8Sopenharmony_ciunsafe impl TransmuteBox for [u8] {}
68cdb3e2c8Sopenharmony_ci
69cdb3e2c8Sopenharmony_ci/// A container for borrowed byte strings converted by this crate.
70cdb3e2c8Sopenharmony_ci///
71cdb3e2c8Sopenharmony_ci/// This wrapper is intended to prevent violating the invariants of the
72cdb3e2c8Sopenharmony_ci/// [unspecified encoding] used by this crate and minimize encoding
73cdb3e2c8Sopenharmony_ci/// conversions.
74cdb3e2c8Sopenharmony_ci///
75cdb3e2c8Sopenharmony_ci/// # Indices
76cdb3e2c8Sopenharmony_ci///
77cdb3e2c8Sopenharmony_ci/// Methods of this struct that accept indices require that the index lie on a
78cdb3e2c8Sopenharmony_ci/// UTF-8 boundary. Although it is possible to manipulate platform strings
79cdb3e2c8Sopenharmony_ci/// based on other indices, this crate currently does not support them for
80cdb3e2c8Sopenharmony_ci/// slicing methods. They would add significant complication to the
81cdb3e2c8Sopenharmony_ci/// implementation and are generally not necessary. However, all indices
82cdb3e2c8Sopenharmony_ci/// returned by this struct can be used for slicing.
83cdb3e2c8Sopenharmony_ci///
84cdb3e2c8Sopenharmony_ci/// On Unix, all indices are permitted, to avoid false positives. However,
85cdb3e2c8Sopenharmony_ci/// relying on this implementation detail is discouraged. Platform-specific
86cdb3e2c8Sopenharmony_ci/// indices are error-prone.
87cdb3e2c8Sopenharmony_ci///
88cdb3e2c8Sopenharmony_ci/// # Complexity
89cdb3e2c8Sopenharmony_ci///
90cdb3e2c8Sopenharmony_ci/// All searching methods have worst-case multiplicative time complexity (i.e.,
91cdb3e2c8Sopenharmony_ci/// `O(self.raw_len() * pat.len())`). Enabling the "memchr" feature allows
92cdb3e2c8Sopenharmony_ci/// these methods to instead run in linear time in the worst case (documented
93cdb3e2c8Sopenharmony_ci/// for [`memchr::memmem::find`][memchr complexity]).
94cdb3e2c8Sopenharmony_ci///
95cdb3e2c8Sopenharmony_ci/// # Safety
96cdb3e2c8Sopenharmony_ci///
97cdb3e2c8Sopenharmony_ci/// Although this type is annotated with `#[repr(transparent)]`, the inner
98cdb3e2c8Sopenharmony_ci/// representation is not stable. Transmuting between this type and any other
99cdb3e2c8Sopenharmony_ci/// causes immediate undefined behavior.
100cdb3e2c8Sopenharmony_ci///
101cdb3e2c8Sopenharmony_ci/// [memchr complexity]: memchr::memmem::find#complexity
102cdb3e2c8Sopenharmony_ci/// [unspecified encoding]: super#encoding
103cdb3e2c8Sopenharmony_ci#[derive(Eq, Hash, Ord, PartialEq, PartialOrd)]
104cdb3e2c8Sopenharmony_ci#[cfg_attr(os_str_bytes_docs_rs, doc(cfg(feature = "raw_os_str")))]
105cdb3e2c8Sopenharmony_ci#[repr(transparent)]
106cdb3e2c8Sopenharmony_cipub struct RawOsStr([u8]);
107cdb3e2c8Sopenharmony_ci
108cdb3e2c8Sopenharmony_ciimpl RawOsStr {
109cdb3e2c8Sopenharmony_ci    const fn from_inner(string: &[u8]) -> &Self {
110cdb3e2c8Sopenharmony_ci        // SAFETY: This struct has a layout that makes this operation safe.
111cdb3e2c8Sopenharmony_ci        unsafe { mem::transmute(string) }
112cdb3e2c8Sopenharmony_ci    }
113cdb3e2c8Sopenharmony_ci
114cdb3e2c8Sopenharmony_ci    /// Converts a platform-native string into a representation that can be
115cdb3e2c8Sopenharmony_ci    /// more easily manipulated.
116cdb3e2c8Sopenharmony_ci    ///
117cdb3e2c8Sopenharmony_ci    /// This method performs the necessary conversion immediately, so it can be
118cdb3e2c8Sopenharmony_ci    /// expensive to call. It is recommended to continue using the returned
119cdb3e2c8Sopenharmony_ci    /// instance as long as possible (instead of the original [`OsStr`]), to
120cdb3e2c8Sopenharmony_ci    /// avoid repeated conversions.
121cdb3e2c8Sopenharmony_ci    ///
122cdb3e2c8Sopenharmony_ci    /// # Examples
123cdb3e2c8Sopenharmony_ci    ///
124cdb3e2c8Sopenharmony_ci    /// ```
125cdb3e2c8Sopenharmony_ci    /// use std::env;
126cdb3e2c8Sopenharmony_ci    /// # use std::io;
127cdb3e2c8Sopenharmony_ci    ///
128cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
129cdb3e2c8Sopenharmony_ci    ///
130cdb3e2c8Sopenharmony_ci    /// let os_string = env::current_exe()?.into_os_string();
131cdb3e2c8Sopenharmony_ci    /// println!("{:?}", RawOsStr::new(&os_string));
132cdb3e2c8Sopenharmony_ci    /// #
133cdb3e2c8Sopenharmony_ci    /// # Ok::<_, io::Error>(())
134cdb3e2c8Sopenharmony_ci    /// ```
135cdb3e2c8Sopenharmony_ci    #[inline]
136cdb3e2c8Sopenharmony_ci    #[must_use]
137cdb3e2c8Sopenharmony_ci    pub fn new(string: &OsStr) -> Cow<'_, Self> {
138cdb3e2c8Sopenharmony_ci        match imp::os_str_to_bytes(string) {
139cdb3e2c8Sopenharmony_ci            Cow::Borrowed(string) => Cow::Borrowed(Self::from_inner(string)),
140cdb3e2c8Sopenharmony_ci            Cow::Owned(string) => Cow::Owned(RawOsString(string)),
141cdb3e2c8Sopenharmony_ci        }
142cdb3e2c8Sopenharmony_ci    }
143cdb3e2c8Sopenharmony_ci
144cdb3e2c8Sopenharmony_ci    /// Wraps a string, without copying or encoding conversion.
145cdb3e2c8Sopenharmony_ci    ///
146cdb3e2c8Sopenharmony_ci    /// This method is much more efficient than [`RawOsStr::new`], since the
147cdb3e2c8Sopenharmony_ci    /// [encoding] used by this crate is compatible with UTF-8.
148cdb3e2c8Sopenharmony_ci    ///
149cdb3e2c8Sopenharmony_ci    /// # Examples
150cdb3e2c8Sopenharmony_ci    ///
151cdb3e2c8Sopenharmony_ci    /// ```
152cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
153cdb3e2c8Sopenharmony_ci    ///
154cdb3e2c8Sopenharmony_ci    /// let string = "foobar";
155cdb3e2c8Sopenharmony_ci    /// let raw = RawOsStr::from_str(string);
156cdb3e2c8Sopenharmony_ci    /// assert_eq!(string, raw);
157cdb3e2c8Sopenharmony_ci    /// ```
158cdb3e2c8Sopenharmony_ci    ///
159cdb3e2c8Sopenharmony_ci    /// [encoding]: super#encoding
160cdb3e2c8Sopenharmony_ci    #[allow(clippy::should_implement_trait)]
161cdb3e2c8Sopenharmony_ci    #[inline]
162cdb3e2c8Sopenharmony_ci    #[must_use]
163cdb3e2c8Sopenharmony_ci    pub fn from_str(string: &str) -> &Self {
164cdb3e2c8Sopenharmony_ci        Self::from_inner(string.as_bytes())
165cdb3e2c8Sopenharmony_ci    }
166cdb3e2c8Sopenharmony_ci
167cdb3e2c8Sopenharmony_ci    /// Wraps a byte string, without copying or encoding conversion.
168cdb3e2c8Sopenharmony_ci    ///
169cdb3e2c8Sopenharmony_ci    /// # Panics
170cdb3e2c8Sopenharmony_ci    ///
171cdb3e2c8Sopenharmony_ci    /// Panics if the string is not valid for the [unspecified encoding] used
172cdb3e2c8Sopenharmony_ci    /// by this crate.
173cdb3e2c8Sopenharmony_ci    ///
174cdb3e2c8Sopenharmony_ci    /// # Examples
175cdb3e2c8Sopenharmony_ci    ///
176cdb3e2c8Sopenharmony_ci    /// ```
177cdb3e2c8Sopenharmony_ci    /// use std::env;
178cdb3e2c8Sopenharmony_ci    /// # use std::io;
179cdb3e2c8Sopenharmony_ci    ///
180cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
181cdb3e2c8Sopenharmony_ci    ///
182cdb3e2c8Sopenharmony_ci    /// let os_string = env::current_exe()?.into_os_string();
183cdb3e2c8Sopenharmony_ci    /// let raw = RawOsStr::new(&os_string);
184cdb3e2c8Sopenharmony_ci    /// let raw_bytes = raw.as_raw_bytes();
185cdb3e2c8Sopenharmony_ci    /// assert_eq!(&*raw, RawOsStr::assert_from_raw_bytes(raw_bytes));
186cdb3e2c8Sopenharmony_ci    /// #
187cdb3e2c8Sopenharmony_ci    /// # Ok::<_, io::Error>(())
188cdb3e2c8Sopenharmony_ci    /// ```
189cdb3e2c8Sopenharmony_ci    ///
190cdb3e2c8Sopenharmony_ci    /// [unspecified encoding]: super#encoding
191cdb3e2c8Sopenharmony_ci    #[inline]
192cdb3e2c8Sopenharmony_ci    #[must_use = "method should not be used for validation"]
193cdb3e2c8Sopenharmony_ci    #[track_caller]
194cdb3e2c8Sopenharmony_ci    pub fn assert_from_raw_bytes(string: &[u8]) -> &Self {
195cdb3e2c8Sopenharmony_ci        expect_encoded!(raw::validate_bytes(string));
196cdb3e2c8Sopenharmony_ci
197cdb3e2c8Sopenharmony_ci        Self::from_inner(string)
198cdb3e2c8Sopenharmony_ci    }
199cdb3e2c8Sopenharmony_ci
200cdb3e2c8Sopenharmony_ci    if_checked_conversions! {
201cdb3e2c8Sopenharmony_ci        /// Wraps a byte string, without copying or encoding conversion.
202cdb3e2c8Sopenharmony_ci        ///
203cdb3e2c8Sopenharmony_ci        /// [`assert_from_raw_bytes`] should almost always be used instead. For
204cdb3e2c8Sopenharmony_ci        /// more information, see [`EncodingError`].
205cdb3e2c8Sopenharmony_ci        ///
206cdb3e2c8Sopenharmony_ci        /// # Errors
207cdb3e2c8Sopenharmony_ci        ///
208cdb3e2c8Sopenharmony_ci        /// See documentation for [`EncodingError`].
209cdb3e2c8Sopenharmony_ci        ///
210cdb3e2c8Sopenharmony_ci        /// # Examples
211cdb3e2c8Sopenharmony_ci        ///
212cdb3e2c8Sopenharmony_ci        /// ```
213cdb3e2c8Sopenharmony_ci        /// use std::env;
214cdb3e2c8Sopenharmony_ci        /// # use std::io;
215cdb3e2c8Sopenharmony_ci        ///
216cdb3e2c8Sopenharmony_ci        /// use os_str_bytes::RawOsStr;
217cdb3e2c8Sopenharmony_ci        ///
218cdb3e2c8Sopenharmony_ci        /// let os_string = env::current_exe()?.into_os_string();
219cdb3e2c8Sopenharmony_ci        /// let raw = RawOsStr::new(&os_string);
220cdb3e2c8Sopenharmony_ci        /// assert_eq!(Ok(&*raw), RawOsStr::from_raw_bytes(raw.as_raw_bytes()));
221cdb3e2c8Sopenharmony_ci        /// #
222cdb3e2c8Sopenharmony_ci        /// # Ok::<_, io::Error>(())
223cdb3e2c8Sopenharmony_ci        /// ```
224cdb3e2c8Sopenharmony_ci        ///
225cdb3e2c8Sopenharmony_ci        /// [`assert_from_raw_bytes`]: Self::assert_from_raw_bytes
226cdb3e2c8Sopenharmony_ci        #[cfg_attr(
227cdb3e2c8Sopenharmony_ci            os_str_bytes_docs_rs,
228cdb3e2c8Sopenharmony_ci            doc(cfg(feature = "checked_conversions"))
229cdb3e2c8Sopenharmony_ci        )]
230cdb3e2c8Sopenharmony_ci        #[inline]
231cdb3e2c8Sopenharmony_ci        pub fn from_raw_bytes(string: &[u8]) -> Result<&Self> {
232cdb3e2c8Sopenharmony_ci            raw::validate_bytes(string)
233cdb3e2c8Sopenharmony_ci                .map(|()| Self::from_inner(string))
234cdb3e2c8Sopenharmony_ci                .map_err(EncodingError)
235cdb3e2c8Sopenharmony_ci        }
236cdb3e2c8Sopenharmony_ci    }
237cdb3e2c8Sopenharmony_ci
238cdb3e2c8Sopenharmony_ci    /// Wraps a byte string, without copying or encoding conversion.
239cdb3e2c8Sopenharmony_ci    ///
240cdb3e2c8Sopenharmony_ci    /// # Safety
241cdb3e2c8Sopenharmony_ci    ///
242cdb3e2c8Sopenharmony_ci    /// The string must be valid for the [unspecified encoding] used by this
243cdb3e2c8Sopenharmony_ci    /// crate.
244cdb3e2c8Sopenharmony_ci    ///
245cdb3e2c8Sopenharmony_ci    /// # Examples
246cdb3e2c8Sopenharmony_ci    ///
247cdb3e2c8Sopenharmony_ci    /// ```
248cdb3e2c8Sopenharmony_ci    /// use std::env;
249cdb3e2c8Sopenharmony_ci    /// # use std::io;
250cdb3e2c8Sopenharmony_ci    ///
251cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
252cdb3e2c8Sopenharmony_ci    ///
253cdb3e2c8Sopenharmony_ci    /// let os_string = env::current_exe()?.into_os_string();
254cdb3e2c8Sopenharmony_ci    /// let raw = RawOsStr::new(&os_string);
255cdb3e2c8Sopenharmony_ci    /// let raw_bytes = raw.as_raw_bytes();
256cdb3e2c8Sopenharmony_ci    /// assert_eq!(&*raw, unsafe {
257cdb3e2c8Sopenharmony_ci    ///     RawOsStr::from_raw_bytes_unchecked(raw_bytes)
258cdb3e2c8Sopenharmony_ci    /// });
259cdb3e2c8Sopenharmony_ci    /// #
260cdb3e2c8Sopenharmony_ci    /// # Ok::<_, io::Error>(())
261cdb3e2c8Sopenharmony_ci    /// ```
262cdb3e2c8Sopenharmony_ci    ///
263cdb3e2c8Sopenharmony_ci    /// [unspecified encoding]: super#encoding
264cdb3e2c8Sopenharmony_ci    #[inline]
265cdb3e2c8Sopenharmony_ci    #[must_use]
266cdb3e2c8Sopenharmony_ci    #[track_caller]
267cdb3e2c8Sopenharmony_ci    pub unsafe fn from_raw_bytes_unchecked(string: &[u8]) -> &Self {
268cdb3e2c8Sopenharmony_ci        if cfg!(debug_assertions) {
269cdb3e2c8Sopenharmony_ci            expect_encoded!(raw::validate_bytes(string));
270cdb3e2c8Sopenharmony_ci        }
271cdb3e2c8Sopenharmony_ci
272cdb3e2c8Sopenharmony_ci        Self::from_inner(string)
273cdb3e2c8Sopenharmony_ci    }
274cdb3e2c8Sopenharmony_ci
275cdb3e2c8Sopenharmony_ci    /// Returns the byte string stored by this container.
276cdb3e2c8Sopenharmony_ci    ///
277cdb3e2c8Sopenharmony_ci    /// The returned string will use an [unspecified encoding].
278cdb3e2c8Sopenharmony_ci    ///
279cdb3e2c8Sopenharmony_ci    /// # Examples
280cdb3e2c8Sopenharmony_ci    ///
281cdb3e2c8Sopenharmony_ci    /// ```
282cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
283cdb3e2c8Sopenharmony_ci    ///
284cdb3e2c8Sopenharmony_ci    /// let string = "foobar";
285cdb3e2c8Sopenharmony_ci    /// let raw = RawOsStr::from_str(string);
286cdb3e2c8Sopenharmony_ci    /// assert_eq!(string.as_bytes(), raw.as_raw_bytes());
287cdb3e2c8Sopenharmony_ci    /// ```
288cdb3e2c8Sopenharmony_ci    ///
289cdb3e2c8Sopenharmony_ci    /// [unspecified encoding]: super#encoding
290cdb3e2c8Sopenharmony_ci    #[inline]
291cdb3e2c8Sopenharmony_ci    #[must_use]
292cdb3e2c8Sopenharmony_ci    pub fn as_raw_bytes(&self) -> &[u8] {
293cdb3e2c8Sopenharmony_ci        &self.0
294cdb3e2c8Sopenharmony_ci    }
295cdb3e2c8Sopenharmony_ci
296cdb3e2c8Sopenharmony_ci    /// Equivalent to [`str::contains`].
297cdb3e2c8Sopenharmony_ci    ///
298cdb3e2c8Sopenharmony_ci    /// # Examples
299cdb3e2c8Sopenharmony_ci    ///
300cdb3e2c8Sopenharmony_ci    /// ```
301cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
302cdb3e2c8Sopenharmony_ci    ///
303cdb3e2c8Sopenharmony_ci    /// let raw = RawOsStr::from_str("foobar");
304cdb3e2c8Sopenharmony_ci    /// assert!(raw.contains("oo"));
305cdb3e2c8Sopenharmony_ci    /// assert!(!raw.contains("of"));
306cdb3e2c8Sopenharmony_ci    /// ```
307cdb3e2c8Sopenharmony_ci    #[inline]
308cdb3e2c8Sopenharmony_ci    #[must_use]
309cdb3e2c8Sopenharmony_ci    pub fn contains<P>(&self, pat: P) -> bool
310cdb3e2c8Sopenharmony_ci    where
311cdb3e2c8Sopenharmony_ci        P: Pattern,
312cdb3e2c8Sopenharmony_ci    {
313cdb3e2c8Sopenharmony_ci        self.find(pat).is_some()
314cdb3e2c8Sopenharmony_ci    }
315cdb3e2c8Sopenharmony_ci
316cdb3e2c8Sopenharmony_ci    /// Equivalent to [`str::ends_with`].
317cdb3e2c8Sopenharmony_ci    ///
318cdb3e2c8Sopenharmony_ci    /// # Examples
319cdb3e2c8Sopenharmony_ci    ///
320cdb3e2c8Sopenharmony_ci    /// ```
321cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
322cdb3e2c8Sopenharmony_ci    ///
323cdb3e2c8Sopenharmony_ci    /// let raw = RawOsStr::from_str("foobar");
324cdb3e2c8Sopenharmony_ci    /// assert!(raw.ends_with("bar"));
325cdb3e2c8Sopenharmony_ci    /// assert!(!raw.ends_with("foo"));
326cdb3e2c8Sopenharmony_ci    /// ```
327cdb3e2c8Sopenharmony_ci    #[inline]
328cdb3e2c8Sopenharmony_ci    #[must_use]
329cdb3e2c8Sopenharmony_ci    pub fn ends_with<P>(&self, pat: P) -> bool
330cdb3e2c8Sopenharmony_ci    where
331cdb3e2c8Sopenharmony_ci        P: Pattern,
332cdb3e2c8Sopenharmony_ci    {
333cdb3e2c8Sopenharmony_ci        let pat = pat.__encode();
334cdb3e2c8Sopenharmony_ci        let pat = pat.__get();
335cdb3e2c8Sopenharmony_ci
336cdb3e2c8Sopenharmony_ci        self.0.ends_with(pat)
337cdb3e2c8Sopenharmony_ci    }
338cdb3e2c8Sopenharmony_ci
339cdb3e2c8Sopenharmony_ci    /// Equivalent to [`str::ends_with`] but accepts this type for the pattern.
340cdb3e2c8Sopenharmony_ci    ///
341cdb3e2c8Sopenharmony_ci    /// # Examples
342cdb3e2c8Sopenharmony_ci    ///
343cdb3e2c8Sopenharmony_ci    /// ```
344cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
345cdb3e2c8Sopenharmony_ci    ///
346cdb3e2c8Sopenharmony_ci    /// let raw = RawOsStr::from_str("foobar");
347cdb3e2c8Sopenharmony_ci    /// assert!(raw.ends_with_os(RawOsStr::from_str("bar")));
348cdb3e2c8Sopenharmony_ci    /// assert!(!raw.ends_with_os(RawOsStr::from_str("foo")));
349cdb3e2c8Sopenharmony_ci    /// ```
350cdb3e2c8Sopenharmony_ci    #[inline]
351cdb3e2c8Sopenharmony_ci    #[must_use]
352cdb3e2c8Sopenharmony_ci    pub fn ends_with_os(&self, pat: &Self) -> bool {
353cdb3e2c8Sopenharmony_ci        raw::ends_with(&self.0, &pat.0)
354cdb3e2c8Sopenharmony_ci    }
355cdb3e2c8Sopenharmony_ci
356cdb3e2c8Sopenharmony_ci    /// Equivalent to [`str::find`].
357cdb3e2c8Sopenharmony_ci    ///
358cdb3e2c8Sopenharmony_ci    /// # Examples
359cdb3e2c8Sopenharmony_ci    ///
360cdb3e2c8Sopenharmony_ci    /// ```
361cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
362cdb3e2c8Sopenharmony_ci    ///
363cdb3e2c8Sopenharmony_ci    /// let raw = RawOsStr::from_str("foobar");
364cdb3e2c8Sopenharmony_ci    /// assert_eq!(Some(1), raw.find("o"));
365cdb3e2c8Sopenharmony_ci    /// assert_eq!(None, raw.find("of"));
366cdb3e2c8Sopenharmony_ci    /// ```
367cdb3e2c8Sopenharmony_ci    #[inline]
368cdb3e2c8Sopenharmony_ci    #[must_use]
369cdb3e2c8Sopenharmony_ci    pub fn find<P>(&self, pat: P) -> Option<usize>
370cdb3e2c8Sopenharmony_ci    where
371cdb3e2c8Sopenharmony_ci        P: Pattern,
372cdb3e2c8Sopenharmony_ci    {
373cdb3e2c8Sopenharmony_ci        let pat = pat.__encode();
374cdb3e2c8Sopenharmony_ci        let pat = pat.__get();
375cdb3e2c8Sopenharmony_ci
376cdb3e2c8Sopenharmony_ci        find(&self.0, pat)
377cdb3e2c8Sopenharmony_ci    }
378cdb3e2c8Sopenharmony_ci
379cdb3e2c8Sopenharmony_ci    /// Equivalent to [`str::is_empty`].
380cdb3e2c8Sopenharmony_ci    ///
381cdb3e2c8Sopenharmony_ci    /// # Examples
382cdb3e2c8Sopenharmony_ci    ///
383cdb3e2c8Sopenharmony_ci    /// ```
384cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
385cdb3e2c8Sopenharmony_ci    ///
386cdb3e2c8Sopenharmony_ci    /// assert!(RawOsStr::from_str("").is_empty());
387cdb3e2c8Sopenharmony_ci    /// assert!(!RawOsStr::from_str("foobar").is_empty());
388cdb3e2c8Sopenharmony_ci    /// ```
389cdb3e2c8Sopenharmony_ci    #[inline]
390cdb3e2c8Sopenharmony_ci    #[must_use]
391cdb3e2c8Sopenharmony_ci    pub fn is_empty(&self) -> bool {
392cdb3e2c8Sopenharmony_ci        self.0.is_empty()
393cdb3e2c8Sopenharmony_ci    }
394cdb3e2c8Sopenharmony_ci
395cdb3e2c8Sopenharmony_ci    /// Returns the length of the byte string stored by this container.
396cdb3e2c8Sopenharmony_ci    ///
397cdb3e2c8Sopenharmony_ci    /// Only the following assumptions can be made about the result:
398cdb3e2c8Sopenharmony_ci    /// - The length of any Unicode character is the length of its UTF-8
399cdb3e2c8Sopenharmony_ci    ///   representation (i.e., [`char::len_utf8`]).
400cdb3e2c8Sopenharmony_ci    /// - Splitting a string at a UTF-8 boundary will return two strings with
401cdb3e2c8Sopenharmony_ci    ///   lengths that sum to the length of the original string.
402cdb3e2c8Sopenharmony_ci    ///
403cdb3e2c8Sopenharmony_ci    /// This method may return a different result than would [`OsStr::len`]
404cdb3e2c8Sopenharmony_ci    /// when called on same string, since [`OsStr`] uses an unspecified
405cdb3e2c8Sopenharmony_ci    /// encoding.
406cdb3e2c8Sopenharmony_ci    ///
407cdb3e2c8Sopenharmony_ci    /// # Examples
408cdb3e2c8Sopenharmony_ci    ///
409cdb3e2c8Sopenharmony_ci    /// ```
410cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
411cdb3e2c8Sopenharmony_ci    ///
412cdb3e2c8Sopenharmony_ci    /// assert_eq!(6, RawOsStr::from_str("foobar").raw_len());
413cdb3e2c8Sopenharmony_ci    /// assert_eq!(0, RawOsStr::from_str("").raw_len());
414cdb3e2c8Sopenharmony_ci    /// ```
415cdb3e2c8Sopenharmony_ci    #[inline]
416cdb3e2c8Sopenharmony_ci    #[must_use]
417cdb3e2c8Sopenharmony_ci    pub fn raw_len(&self) -> usize {
418cdb3e2c8Sopenharmony_ci        self.0.len()
419cdb3e2c8Sopenharmony_ci    }
420cdb3e2c8Sopenharmony_ci
421cdb3e2c8Sopenharmony_ci    /// Equivalent to [`str::rfind`].
422cdb3e2c8Sopenharmony_ci    ///
423cdb3e2c8Sopenharmony_ci    /// # Examples
424cdb3e2c8Sopenharmony_ci    ///
425cdb3e2c8Sopenharmony_ci    /// ```
426cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
427cdb3e2c8Sopenharmony_ci    ///
428cdb3e2c8Sopenharmony_ci    /// let raw = RawOsStr::from_str("foobar");
429cdb3e2c8Sopenharmony_ci    /// assert_eq!(Some(2), raw.rfind("o"));
430cdb3e2c8Sopenharmony_ci    /// assert_eq!(None, raw.rfind("of"));
431cdb3e2c8Sopenharmony_ci    /// ```
432cdb3e2c8Sopenharmony_ci    #[inline]
433cdb3e2c8Sopenharmony_ci    #[must_use]
434cdb3e2c8Sopenharmony_ci    pub fn rfind<P>(&self, pat: P) -> Option<usize>
435cdb3e2c8Sopenharmony_ci    where
436cdb3e2c8Sopenharmony_ci        P: Pattern,
437cdb3e2c8Sopenharmony_ci    {
438cdb3e2c8Sopenharmony_ci        let pat = pat.__encode();
439cdb3e2c8Sopenharmony_ci        let pat = pat.__get();
440cdb3e2c8Sopenharmony_ci
441cdb3e2c8Sopenharmony_ci        rfind(&self.0, pat)
442cdb3e2c8Sopenharmony_ci    }
443cdb3e2c8Sopenharmony_ci
444cdb3e2c8Sopenharmony_ci    fn split_once_raw_with<P, F>(
445cdb3e2c8Sopenharmony_ci        &self,
446cdb3e2c8Sopenharmony_ci        pat: &P,
447cdb3e2c8Sopenharmony_ci        find_fn: F,
448cdb3e2c8Sopenharmony_ci    ) -> Option<(&Self, &Self)>
449cdb3e2c8Sopenharmony_ci    where
450cdb3e2c8Sopenharmony_ci        F: FnOnce(&[u8], &[u8]) -> Option<usize>,
451cdb3e2c8Sopenharmony_ci        P: EncodedPattern,
452cdb3e2c8Sopenharmony_ci    {
453cdb3e2c8Sopenharmony_ci        let pat = pat.__get();
454cdb3e2c8Sopenharmony_ci
455cdb3e2c8Sopenharmony_ci        let index = find_fn(&self.0, pat)?;
456cdb3e2c8Sopenharmony_ci        let prefix = &self.0[..index];
457cdb3e2c8Sopenharmony_ci        let suffix = &self.0[index + pat.len()..];
458cdb3e2c8Sopenharmony_ci        Some((Self::from_inner(prefix), Self::from_inner(suffix)))
459cdb3e2c8Sopenharmony_ci    }
460cdb3e2c8Sopenharmony_ci
461cdb3e2c8Sopenharmony_ci    pub(super) fn rsplit_once_raw<P>(&self, pat: &P) -> Option<(&Self, &Self)>
462cdb3e2c8Sopenharmony_ci    where
463cdb3e2c8Sopenharmony_ci        P: EncodedPattern,
464cdb3e2c8Sopenharmony_ci    {
465cdb3e2c8Sopenharmony_ci        self.split_once_raw_with(pat, rfind)
466cdb3e2c8Sopenharmony_ci    }
467cdb3e2c8Sopenharmony_ci
468cdb3e2c8Sopenharmony_ci    /// Equivalent to [`str::rsplit_once`].
469cdb3e2c8Sopenharmony_ci    ///
470cdb3e2c8Sopenharmony_ci    /// # Examples
471cdb3e2c8Sopenharmony_ci    ///
472cdb3e2c8Sopenharmony_ci    /// ```
473cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
474cdb3e2c8Sopenharmony_ci    ///
475cdb3e2c8Sopenharmony_ci    /// let raw = RawOsStr::from_str("foobar");
476cdb3e2c8Sopenharmony_ci    /// assert_eq!(
477cdb3e2c8Sopenharmony_ci    ///     Some((RawOsStr::from_str("fo"), RawOsStr::from_str("bar"))),
478cdb3e2c8Sopenharmony_ci    ///     raw.rsplit_once("o"),
479cdb3e2c8Sopenharmony_ci    /// );
480cdb3e2c8Sopenharmony_ci    /// assert_eq!(None, raw.rsplit_once("of"));
481cdb3e2c8Sopenharmony_ci    /// ```
482cdb3e2c8Sopenharmony_ci    #[inline]
483cdb3e2c8Sopenharmony_ci    #[must_use]
484cdb3e2c8Sopenharmony_ci    pub fn rsplit_once<P>(&self, pat: P) -> Option<(&Self, &Self)>
485cdb3e2c8Sopenharmony_ci    where
486cdb3e2c8Sopenharmony_ci        P: Pattern,
487cdb3e2c8Sopenharmony_ci    {
488cdb3e2c8Sopenharmony_ci        self.rsplit_once_raw(&pat.__encode())
489cdb3e2c8Sopenharmony_ci    }
490cdb3e2c8Sopenharmony_ci
491cdb3e2c8Sopenharmony_ci    // https://github.com/rust-lang/rust/blob/49c68bd53f90e375bfb3cbba8c1c67a9e0adb9c0/src/libcore/str/mod.rs#L2184-L2221
492cdb3e2c8Sopenharmony_ci    #[cold]
493cdb3e2c8Sopenharmony_ci    #[inline(never)]
494cdb3e2c8Sopenharmony_ci    #[track_caller]
495cdb3e2c8Sopenharmony_ci    fn index_boundary_error(&self, index: usize) -> ! {
496cdb3e2c8Sopenharmony_ci        debug_assert!(raw::is_continuation(self.0[index]));
497cdb3e2c8Sopenharmony_ci
498cdb3e2c8Sopenharmony_ci        let start = expect_encoded!(self.0[..index]
499cdb3e2c8Sopenharmony_ci            .iter()
500cdb3e2c8Sopenharmony_ci            .rposition(|&x| !raw::is_continuation(x)));
501cdb3e2c8Sopenharmony_ci        let mut end = index + 1;
502cdb3e2c8Sopenharmony_ci        end += self.0[end..]
503cdb3e2c8Sopenharmony_ci            .iter()
504cdb3e2c8Sopenharmony_ci            .take_while(|&&x| raw::is_continuation(x))
505cdb3e2c8Sopenharmony_ci            .count();
506cdb3e2c8Sopenharmony_ci        let code_point = raw::decode_code_point(&self.0[start..end]);
507cdb3e2c8Sopenharmony_ci        panic!(
508cdb3e2c8Sopenharmony_ci            "byte index {} is not a valid boundary; it is inside U+{:04X} \
509cdb3e2c8Sopenharmony_ci             (bytes {}..{})",
510cdb3e2c8Sopenharmony_ci            index, code_point, start, end,
511cdb3e2c8Sopenharmony_ci        );
512cdb3e2c8Sopenharmony_ci    }
513cdb3e2c8Sopenharmony_ci
514cdb3e2c8Sopenharmony_ci    #[track_caller]
515cdb3e2c8Sopenharmony_ci    fn check_bound(&self, index: usize) {
516cdb3e2c8Sopenharmony_ci        if let Some(&byte) = self.0.get(index) {
517cdb3e2c8Sopenharmony_ci            if raw::is_continuation(byte) {
518cdb3e2c8Sopenharmony_ci                self.index_boundary_error(index);
519cdb3e2c8Sopenharmony_ci            }
520cdb3e2c8Sopenharmony_ci        }
521cdb3e2c8Sopenharmony_ci    }
522cdb3e2c8Sopenharmony_ci
523cdb3e2c8Sopenharmony_ci    /// Equivalent to [`str::split`], but empty patterns are not accepted.
524cdb3e2c8Sopenharmony_ci    ///
525cdb3e2c8Sopenharmony_ci    /// # Panics
526cdb3e2c8Sopenharmony_ci    ///
527cdb3e2c8Sopenharmony_ci    /// Panics if the pattern is empty.
528cdb3e2c8Sopenharmony_ci    ///
529cdb3e2c8Sopenharmony_ci    /// # Examples
530cdb3e2c8Sopenharmony_ci    ///
531cdb3e2c8Sopenharmony_ci    /// ```
532cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
533cdb3e2c8Sopenharmony_ci    ///
534cdb3e2c8Sopenharmony_ci    /// let raw = RawOsStr::from_str("foobar");
535cdb3e2c8Sopenharmony_ci    /// assert_eq!(["f", "", "bar"], *raw.split("o").collect::<Vec<_>>());
536cdb3e2c8Sopenharmony_ci    /// ```
537cdb3e2c8Sopenharmony_ci    #[inline]
538cdb3e2c8Sopenharmony_ci    #[must_use]
539cdb3e2c8Sopenharmony_ci    #[track_caller]
540cdb3e2c8Sopenharmony_ci    pub fn split<P>(&self, pat: P) -> Split<'_, P>
541cdb3e2c8Sopenharmony_ci    where
542cdb3e2c8Sopenharmony_ci        P: Pattern,
543cdb3e2c8Sopenharmony_ci    {
544cdb3e2c8Sopenharmony_ci        Split::new(self, pat)
545cdb3e2c8Sopenharmony_ci    }
546cdb3e2c8Sopenharmony_ci
547cdb3e2c8Sopenharmony_ci    /// Equivalent to [`str::split_at`].
548cdb3e2c8Sopenharmony_ci    ///
549cdb3e2c8Sopenharmony_ci    /// # Panics
550cdb3e2c8Sopenharmony_ci    ///
551cdb3e2c8Sopenharmony_ci    /// Panics if the index is not a [valid boundary].
552cdb3e2c8Sopenharmony_ci    ///
553cdb3e2c8Sopenharmony_ci    /// # Examples
554cdb3e2c8Sopenharmony_ci    ///
555cdb3e2c8Sopenharmony_ci    /// ```
556cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
557cdb3e2c8Sopenharmony_ci    ///
558cdb3e2c8Sopenharmony_ci    /// let raw = RawOsStr::from_str("foobar");
559cdb3e2c8Sopenharmony_ci    /// assert_eq!(
560cdb3e2c8Sopenharmony_ci    ///     ((RawOsStr::from_str("fo"), RawOsStr::from_str("obar"))),
561cdb3e2c8Sopenharmony_ci    ///     raw.split_at(2),
562cdb3e2c8Sopenharmony_ci    /// );
563cdb3e2c8Sopenharmony_ci    /// ```
564cdb3e2c8Sopenharmony_ci    ///
565cdb3e2c8Sopenharmony_ci    /// [valid boundary]: #indices
566cdb3e2c8Sopenharmony_ci    #[inline]
567cdb3e2c8Sopenharmony_ci    #[must_use]
568cdb3e2c8Sopenharmony_ci    #[track_caller]
569cdb3e2c8Sopenharmony_ci    pub fn split_at(&self, mid: usize) -> (&Self, &Self) {
570cdb3e2c8Sopenharmony_ci        self.check_bound(mid);
571cdb3e2c8Sopenharmony_ci
572cdb3e2c8Sopenharmony_ci        let (prefix, suffix) = self.0.split_at(mid);
573cdb3e2c8Sopenharmony_ci        (Self::from_inner(prefix), Self::from_inner(suffix))
574cdb3e2c8Sopenharmony_ci    }
575cdb3e2c8Sopenharmony_ci
576cdb3e2c8Sopenharmony_ci    pub(super) fn split_once_raw<P>(&self, pat: &P) -> Option<(&Self, &Self)>
577cdb3e2c8Sopenharmony_ci    where
578cdb3e2c8Sopenharmony_ci        P: EncodedPattern,
579cdb3e2c8Sopenharmony_ci    {
580cdb3e2c8Sopenharmony_ci        self.split_once_raw_with(pat, find)
581cdb3e2c8Sopenharmony_ci    }
582cdb3e2c8Sopenharmony_ci
583cdb3e2c8Sopenharmony_ci    /// Equivalent to [`str::split_once`].
584cdb3e2c8Sopenharmony_ci    ///
585cdb3e2c8Sopenharmony_ci    /// # Examples
586cdb3e2c8Sopenharmony_ci    ///
587cdb3e2c8Sopenharmony_ci    /// ```
588cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
589cdb3e2c8Sopenharmony_ci    ///
590cdb3e2c8Sopenharmony_ci    /// let raw = RawOsStr::from_str("foobar");
591cdb3e2c8Sopenharmony_ci    /// assert_eq!(
592cdb3e2c8Sopenharmony_ci    ///     Some((RawOsStr::from_str("f"), RawOsStr::from_str("obar"))),
593cdb3e2c8Sopenharmony_ci    ///     raw.split_once("o"),
594cdb3e2c8Sopenharmony_ci    /// );
595cdb3e2c8Sopenharmony_ci    /// assert_eq!(None, raw.split_once("of"));
596cdb3e2c8Sopenharmony_ci    /// ```
597cdb3e2c8Sopenharmony_ci    #[inline]
598cdb3e2c8Sopenharmony_ci    #[must_use]
599cdb3e2c8Sopenharmony_ci    pub fn split_once<P>(&self, pat: P) -> Option<(&Self, &Self)>
600cdb3e2c8Sopenharmony_ci    where
601cdb3e2c8Sopenharmony_ci        P: Pattern,
602cdb3e2c8Sopenharmony_ci    {
603cdb3e2c8Sopenharmony_ci        self.split_once_raw(&pat.__encode())
604cdb3e2c8Sopenharmony_ci    }
605cdb3e2c8Sopenharmony_ci
606cdb3e2c8Sopenharmony_ci    /// Equivalent to [`str::starts_with`].
607cdb3e2c8Sopenharmony_ci    ///
608cdb3e2c8Sopenharmony_ci    /// # Examples
609cdb3e2c8Sopenharmony_ci    ///
610cdb3e2c8Sopenharmony_ci    /// ```
611cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
612cdb3e2c8Sopenharmony_ci    ///
613cdb3e2c8Sopenharmony_ci    /// let raw = RawOsStr::from_str("foobar");
614cdb3e2c8Sopenharmony_ci    /// assert!(raw.starts_with("foo"));
615cdb3e2c8Sopenharmony_ci    /// assert!(!raw.starts_with("bar"));
616cdb3e2c8Sopenharmony_ci    /// ```
617cdb3e2c8Sopenharmony_ci    #[inline]
618cdb3e2c8Sopenharmony_ci    #[must_use]
619cdb3e2c8Sopenharmony_ci    pub fn starts_with<P>(&self, pat: P) -> bool
620cdb3e2c8Sopenharmony_ci    where
621cdb3e2c8Sopenharmony_ci        P: Pattern,
622cdb3e2c8Sopenharmony_ci    {
623cdb3e2c8Sopenharmony_ci        let pat = pat.__encode();
624cdb3e2c8Sopenharmony_ci        let pat = pat.__get();
625cdb3e2c8Sopenharmony_ci
626cdb3e2c8Sopenharmony_ci        self.0.starts_with(pat)
627cdb3e2c8Sopenharmony_ci    }
628cdb3e2c8Sopenharmony_ci
629cdb3e2c8Sopenharmony_ci    /// Equivalent to [`str::starts_with`] but accepts this type for the
630cdb3e2c8Sopenharmony_ci    /// pattern.
631cdb3e2c8Sopenharmony_ci    ///
632cdb3e2c8Sopenharmony_ci    /// # Examples
633cdb3e2c8Sopenharmony_ci    ///
634cdb3e2c8Sopenharmony_ci    /// ```
635cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
636cdb3e2c8Sopenharmony_ci    ///
637cdb3e2c8Sopenharmony_ci    /// let raw = RawOsStr::from_str("foobar");
638cdb3e2c8Sopenharmony_ci    /// assert!(raw.starts_with_os(RawOsStr::from_str("foo")));
639cdb3e2c8Sopenharmony_ci    /// assert!(!raw.starts_with_os(RawOsStr::from_str("bar")));
640cdb3e2c8Sopenharmony_ci    /// ```
641cdb3e2c8Sopenharmony_ci    #[inline]
642cdb3e2c8Sopenharmony_ci    #[must_use]
643cdb3e2c8Sopenharmony_ci    pub fn starts_with_os(&self, pat: &Self) -> bool {
644cdb3e2c8Sopenharmony_ci        raw::starts_with(&self.0, &pat.0)
645cdb3e2c8Sopenharmony_ci    }
646cdb3e2c8Sopenharmony_ci
647cdb3e2c8Sopenharmony_ci    /// Equivalent to [`str::strip_prefix`].
648cdb3e2c8Sopenharmony_ci    ///
649cdb3e2c8Sopenharmony_ci    /// # Examples
650cdb3e2c8Sopenharmony_ci    ///
651cdb3e2c8Sopenharmony_ci    /// ```
652cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
653cdb3e2c8Sopenharmony_ci    ///
654cdb3e2c8Sopenharmony_ci    /// let raw = RawOsStr::from_str("111foo1bar111");
655cdb3e2c8Sopenharmony_ci    /// assert_eq!(
656cdb3e2c8Sopenharmony_ci    ///     Some(RawOsStr::from_str("11foo1bar111")),
657cdb3e2c8Sopenharmony_ci    ///     raw.strip_prefix("1"),
658cdb3e2c8Sopenharmony_ci    /// );
659cdb3e2c8Sopenharmony_ci    /// assert_eq!(None, raw.strip_prefix("o"));
660cdb3e2c8Sopenharmony_ci    /// ```
661cdb3e2c8Sopenharmony_ci    #[inline]
662cdb3e2c8Sopenharmony_ci    #[must_use]
663cdb3e2c8Sopenharmony_ci    pub fn strip_prefix<P>(&self, pat: P) -> Option<&Self>
664cdb3e2c8Sopenharmony_ci    where
665cdb3e2c8Sopenharmony_ci        P: Pattern,
666cdb3e2c8Sopenharmony_ci    {
667cdb3e2c8Sopenharmony_ci        let pat = pat.__encode();
668cdb3e2c8Sopenharmony_ci        let pat = pat.__get();
669cdb3e2c8Sopenharmony_ci
670cdb3e2c8Sopenharmony_ci        self.0.strip_prefix(pat).map(Self::from_inner)
671cdb3e2c8Sopenharmony_ci    }
672cdb3e2c8Sopenharmony_ci
673cdb3e2c8Sopenharmony_ci    /// Equivalent to [`str::strip_suffix`].
674cdb3e2c8Sopenharmony_ci    ///
675cdb3e2c8Sopenharmony_ci    /// # Examples
676cdb3e2c8Sopenharmony_ci    ///
677cdb3e2c8Sopenharmony_ci    /// ```
678cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
679cdb3e2c8Sopenharmony_ci    ///
680cdb3e2c8Sopenharmony_ci    /// let raw = RawOsStr::from_str("111foo1bar111");
681cdb3e2c8Sopenharmony_ci    /// assert_eq!(
682cdb3e2c8Sopenharmony_ci    ///     Some(RawOsStr::from_str("111foo1bar11")),
683cdb3e2c8Sopenharmony_ci    ///     raw.strip_suffix("1"),
684cdb3e2c8Sopenharmony_ci    /// );
685cdb3e2c8Sopenharmony_ci    /// assert_eq!(None, raw.strip_suffix("o"));
686cdb3e2c8Sopenharmony_ci    /// ```
687cdb3e2c8Sopenharmony_ci    #[inline]
688cdb3e2c8Sopenharmony_ci    #[must_use]
689cdb3e2c8Sopenharmony_ci    pub fn strip_suffix<P>(&self, pat: P) -> Option<&Self>
690cdb3e2c8Sopenharmony_ci    where
691cdb3e2c8Sopenharmony_ci        P: Pattern,
692cdb3e2c8Sopenharmony_ci    {
693cdb3e2c8Sopenharmony_ci        let pat = pat.__encode();
694cdb3e2c8Sopenharmony_ci        let pat = pat.__get();
695cdb3e2c8Sopenharmony_ci
696cdb3e2c8Sopenharmony_ci        self.0.strip_suffix(pat).map(Self::from_inner)
697cdb3e2c8Sopenharmony_ci    }
698cdb3e2c8Sopenharmony_ci
699cdb3e2c8Sopenharmony_ci    /// Converts this representation back to a platform-native string.
700cdb3e2c8Sopenharmony_ci    ///
701cdb3e2c8Sopenharmony_ci    /// When possible, use [`RawOsStrCow::into_os_str`] for a more efficient
702cdb3e2c8Sopenharmony_ci    /// conversion on some platforms.
703cdb3e2c8Sopenharmony_ci    ///
704cdb3e2c8Sopenharmony_ci    /// # Examples
705cdb3e2c8Sopenharmony_ci    ///
706cdb3e2c8Sopenharmony_ci    /// ```
707cdb3e2c8Sopenharmony_ci    /// use std::env;
708cdb3e2c8Sopenharmony_ci    /// # use std::io;
709cdb3e2c8Sopenharmony_ci    ///
710cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
711cdb3e2c8Sopenharmony_ci    ///
712cdb3e2c8Sopenharmony_ci    /// let os_string = env::current_exe()?.into_os_string();
713cdb3e2c8Sopenharmony_ci    /// let raw = RawOsStr::new(&os_string);
714cdb3e2c8Sopenharmony_ci    /// assert_eq!(os_string, raw.to_os_str());
715cdb3e2c8Sopenharmony_ci    /// #
716cdb3e2c8Sopenharmony_ci    /// # Ok::<_, io::Error>(())
717cdb3e2c8Sopenharmony_ci    /// ```
718cdb3e2c8Sopenharmony_ci    #[inline]
719cdb3e2c8Sopenharmony_ci    #[must_use]
720cdb3e2c8Sopenharmony_ci    pub fn to_os_str(&self) -> Cow<'_, OsStr> {
721cdb3e2c8Sopenharmony_ci        expect_encoded!(imp::os_str_from_bytes(&self.0))
722cdb3e2c8Sopenharmony_ci    }
723cdb3e2c8Sopenharmony_ci
724cdb3e2c8Sopenharmony_ci    /// Equivalent to [`OsStr::to_str`].
725cdb3e2c8Sopenharmony_ci    ///
726cdb3e2c8Sopenharmony_ci    /// # Examples
727cdb3e2c8Sopenharmony_ci    ///
728cdb3e2c8Sopenharmony_ci    /// ```
729cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
730cdb3e2c8Sopenharmony_ci    ///
731cdb3e2c8Sopenharmony_ci    /// let string = "foobar";
732cdb3e2c8Sopenharmony_ci    /// let raw = RawOsStr::from_str(string);
733cdb3e2c8Sopenharmony_ci    /// assert_eq!(Some(string), raw.to_str());
734cdb3e2c8Sopenharmony_ci    /// ```
735cdb3e2c8Sopenharmony_ci    #[inline]
736cdb3e2c8Sopenharmony_ci    #[must_use]
737cdb3e2c8Sopenharmony_ci    pub fn to_str(&self) -> Option<&str> {
738cdb3e2c8Sopenharmony_ci        str::from_utf8(&self.0).ok()
739cdb3e2c8Sopenharmony_ci    }
740cdb3e2c8Sopenharmony_ci
741cdb3e2c8Sopenharmony_ci    /// Converts this string to the best UTF-8 representation possible.
742cdb3e2c8Sopenharmony_ci    ///
743cdb3e2c8Sopenharmony_ci    /// Invalid sequences will be replaced with
744cdb3e2c8Sopenharmony_ci    /// [`char::REPLACEMENT_CHARACTER`].
745cdb3e2c8Sopenharmony_ci    ///
746cdb3e2c8Sopenharmony_ci    /// This method may return a different result than would
747cdb3e2c8Sopenharmony_ci    /// [`OsStr::to_string_lossy`] when called on same string, since [`OsStr`]
748cdb3e2c8Sopenharmony_ci    /// uses an unspecified encoding.
749cdb3e2c8Sopenharmony_ci    ///
750cdb3e2c8Sopenharmony_ci    /// # Examples
751cdb3e2c8Sopenharmony_ci    ///
752cdb3e2c8Sopenharmony_ci    /// ```
753cdb3e2c8Sopenharmony_ci    /// use std::env;
754cdb3e2c8Sopenharmony_ci    /// # use std::io;
755cdb3e2c8Sopenharmony_ci    ///
756cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
757cdb3e2c8Sopenharmony_ci    ///
758cdb3e2c8Sopenharmony_ci    /// let os_string = env::current_exe()?.into_os_string();
759cdb3e2c8Sopenharmony_ci    /// let raw = RawOsStr::new(&os_string);
760cdb3e2c8Sopenharmony_ci    /// println!("{}", raw.to_str_lossy());
761cdb3e2c8Sopenharmony_ci    /// #
762cdb3e2c8Sopenharmony_ci    /// # Ok::<_, io::Error>(())
763cdb3e2c8Sopenharmony_ci    /// ```
764cdb3e2c8Sopenharmony_ci    #[inline]
765cdb3e2c8Sopenharmony_ci    #[must_use]
766cdb3e2c8Sopenharmony_ci    pub fn to_str_lossy(&self) -> Cow<'_, str> {
767cdb3e2c8Sopenharmony_ci        String::from_utf8_lossy(&self.0)
768cdb3e2c8Sopenharmony_ci    }
769cdb3e2c8Sopenharmony_ci
770cdb3e2c8Sopenharmony_ci    fn trim_matches_raw_with<P, F>(&self, pat: &P, strip_fn: F) -> &Self
771cdb3e2c8Sopenharmony_ci    where
772cdb3e2c8Sopenharmony_ci        F: for<'a> Fn(&'a [u8], &[u8]) -> Option<&'a [u8]>,
773cdb3e2c8Sopenharmony_ci        P: EncodedPattern,
774cdb3e2c8Sopenharmony_ci    {
775cdb3e2c8Sopenharmony_ci        let pat = pat.__get();
776cdb3e2c8Sopenharmony_ci        if pat.is_empty() {
777cdb3e2c8Sopenharmony_ci            return self;
778cdb3e2c8Sopenharmony_ci        }
779cdb3e2c8Sopenharmony_ci
780cdb3e2c8Sopenharmony_ci        let mut string = &self.0;
781cdb3e2c8Sopenharmony_ci        while let Some(substring) = strip_fn(string, pat) {
782cdb3e2c8Sopenharmony_ci            string = substring;
783cdb3e2c8Sopenharmony_ci        }
784cdb3e2c8Sopenharmony_ci        Self::from_inner(string)
785cdb3e2c8Sopenharmony_ci    }
786cdb3e2c8Sopenharmony_ci
787cdb3e2c8Sopenharmony_ci    fn trim_end_matches_raw<P>(&self, pat: &P) -> &Self
788cdb3e2c8Sopenharmony_ci    where
789cdb3e2c8Sopenharmony_ci        P: EncodedPattern,
790cdb3e2c8Sopenharmony_ci    {
791cdb3e2c8Sopenharmony_ci        self.trim_matches_raw_with(pat, <[_]>::strip_suffix)
792cdb3e2c8Sopenharmony_ci    }
793cdb3e2c8Sopenharmony_ci
794cdb3e2c8Sopenharmony_ci    /// Equivalent to [`str::trim_end_matches`].
795cdb3e2c8Sopenharmony_ci    ///
796cdb3e2c8Sopenharmony_ci    /// # Examples
797cdb3e2c8Sopenharmony_ci    ///
798cdb3e2c8Sopenharmony_ci    /// ```
799cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
800cdb3e2c8Sopenharmony_ci    ///
801cdb3e2c8Sopenharmony_ci    /// let raw = RawOsStr::from_str("111foo1bar111");
802cdb3e2c8Sopenharmony_ci    /// assert_eq!("111foo1bar", raw.trim_end_matches("1"));
803cdb3e2c8Sopenharmony_ci    /// assert_eq!("111foo1bar111", raw.trim_end_matches("o"));
804cdb3e2c8Sopenharmony_ci    /// ```
805cdb3e2c8Sopenharmony_ci    #[inline]
806cdb3e2c8Sopenharmony_ci    #[must_use]
807cdb3e2c8Sopenharmony_ci    pub fn trim_end_matches<P>(&self, pat: P) -> &Self
808cdb3e2c8Sopenharmony_ci    where
809cdb3e2c8Sopenharmony_ci        P: Pattern,
810cdb3e2c8Sopenharmony_ci    {
811cdb3e2c8Sopenharmony_ci        self.trim_end_matches_raw(&pat.__encode())
812cdb3e2c8Sopenharmony_ci    }
813cdb3e2c8Sopenharmony_ci
814cdb3e2c8Sopenharmony_ci    /// Equivalent to [`str::trim_matches`].
815cdb3e2c8Sopenharmony_ci    ///
816cdb3e2c8Sopenharmony_ci    /// # Examples
817cdb3e2c8Sopenharmony_ci    ///
818cdb3e2c8Sopenharmony_ci    /// ```
819cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
820cdb3e2c8Sopenharmony_ci    ///
821cdb3e2c8Sopenharmony_ci    /// let raw = RawOsStr::from_str("111foo1bar111");
822cdb3e2c8Sopenharmony_ci    /// assert_eq!("foo1bar", raw.trim_matches("1"));
823cdb3e2c8Sopenharmony_ci    /// assert_eq!("111foo1bar111", raw.trim_matches("o"));
824cdb3e2c8Sopenharmony_ci    /// ```
825cdb3e2c8Sopenharmony_ci    #[inline]
826cdb3e2c8Sopenharmony_ci    #[must_use]
827cdb3e2c8Sopenharmony_ci    pub fn trim_matches<P>(&self, pat: P) -> &Self
828cdb3e2c8Sopenharmony_ci    where
829cdb3e2c8Sopenharmony_ci        P: Pattern,
830cdb3e2c8Sopenharmony_ci    {
831cdb3e2c8Sopenharmony_ci        let pat = pat.__encode();
832cdb3e2c8Sopenharmony_ci        self.trim_start_matches_raw(&pat).trim_end_matches_raw(&pat)
833cdb3e2c8Sopenharmony_ci    }
834cdb3e2c8Sopenharmony_ci
835cdb3e2c8Sopenharmony_ci    fn trim_start_matches_raw<P>(&self, pat: &P) -> &Self
836cdb3e2c8Sopenharmony_ci    where
837cdb3e2c8Sopenharmony_ci        P: EncodedPattern,
838cdb3e2c8Sopenharmony_ci    {
839cdb3e2c8Sopenharmony_ci        self.trim_matches_raw_with(pat, <[_]>::strip_prefix)
840cdb3e2c8Sopenharmony_ci    }
841cdb3e2c8Sopenharmony_ci
842cdb3e2c8Sopenharmony_ci    /// Equivalent to [`str::trim_start_matches`].
843cdb3e2c8Sopenharmony_ci    ///
844cdb3e2c8Sopenharmony_ci    /// # Examples
845cdb3e2c8Sopenharmony_ci    ///
846cdb3e2c8Sopenharmony_ci    /// ```
847cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
848cdb3e2c8Sopenharmony_ci    ///
849cdb3e2c8Sopenharmony_ci    /// let raw = RawOsStr::from_str("111foo1bar111");
850cdb3e2c8Sopenharmony_ci    /// assert_eq!("foo1bar111", raw.trim_start_matches("1"));
851cdb3e2c8Sopenharmony_ci    /// assert_eq!("111foo1bar111", raw.trim_start_matches("o"));
852cdb3e2c8Sopenharmony_ci    /// ```
853cdb3e2c8Sopenharmony_ci    #[inline]
854cdb3e2c8Sopenharmony_ci    #[must_use]
855cdb3e2c8Sopenharmony_ci    pub fn trim_start_matches<P>(&self, pat: P) -> &Self
856cdb3e2c8Sopenharmony_ci    where
857cdb3e2c8Sopenharmony_ci        P: Pattern,
858cdb3e2c8Sopenharmony_ci    {
859cdb3e2c8Sopenharmony_ci        self.trim_start_matches_raw(&pat.__encode())
860cdb3e2c8Sopenharmony_ci    }
861cdb3e2c8Sopenharmony_ci}
862cdb3e2c8Sopenharmony_ci
863cdb3e2c8Sopenharmony_ciimpl AsRef<Self> for RawOsStr {
864cdb3e2c8Sopenharmony_ci    #[inline]
865cdb3e2c8Sopenharmony_ci    fn as_ref(&self) -> &Self {
866cdb3e2c8Sopenharmony_ci        self
867cdb3e2c8Sopenharmony_ci    }
868cdb3e2c8Sopenharmony_ci}
869cdb3e2c8Sopenharmony_ci
870cdb3e2c8Sopenharmony_ciimpl AsRef<RawOsStr> for str {
871cdb3e2c8Sopenharmony_ci    #[inline]
872cdb3e2c8Sopenharmony_ci    fn as_ref(&self) -> &RawOsStr {
873cdb3e2c8Sopenharmony_ci        RawOsStr::from_str(self)
874cdb3e2c8Sopenharmony_ci    }
875cdb3e2c8Sopenharmony_ci}
876cdb3e2c8Sopenharmony_ci
877cdb3e2c8Sopenharmony_ciimpl AsRef<RawOsStr> for String {
878cdb3e2c8Sopenharmony_ci    #[inline]
879cdb3e2c8Sopenharmony_ci    fn as_ref(&self) -> &RawOsStr {
880cdb3e2c8Sopenharmony_ci        (**self).as_ref()
881cdb3e2c8Sopenharmony_ci    }
882cdb3e2c8Sopenharmony_ci}
883cdb3e2c8Sopenharmony_ci
884cdb3e2c8Sopenharmony_ciimpl Default for &RawOsStr {
885cdb3e2c8Sopenharmony_ci    #[inline]
886cdb3e2c8Sopenharmony_ci    fn default() -> Self {
887cdb3e2c8Sopenharmony_ci        RawOsStr::from_str("")
888cdb3e2c8Sopenharmony_ci    }
889cdb3e2c8Sopenharmony_ci}
890cdb3e2c8Sopenharmony_ci
891cdb3e2c8Sopenharmony_ciimpl<'a> From<&'a RawOsStr> for Cow<'a, RawOsStr> {
892cdb3e2c8Sopenharmony_ci    #[inline]
893cdb3e2c8Sopenharmony_ci    fn from(value: &'a RawOsStr) -> Self {
894cdb3e2c8Sopenharmony_ci        Cow::Borrowed(value)
895cdb3e2c8Sopenharmony_ci    }
896cdb3e2c8Sopenharmony_ci}
897cdb3e2c8Sopenharmony_ci
898cdb3e2c8Sopenharmony_ciimpl From<Box<str>> for Box<RawOsStr> {
899cdb3e2c8Sopenharmony_ci    #[inline]
900cdb3e2c8Sopenharmony_ci    fn from(value: Box<str>) -> Self {
901cdb3e2c8Sopenharmony_ci        value.into_boxed_bytes().transmute_box()
902cdb3e2c8Sopenharmony_ci    }
903cdb3e2c8Sopenharmony_ci}
904cdb3e2c8Sopenharmony_ci
905cdb3e2c8Sopenharmony_ciimpl ToOwned for RawOsStr {
906cdb3e2c8Sopenharmony_ci    type Owned = RawOsString;
907cdb3e2c8Sopenharmony_ci
908cdb3e2c8Sopenharmony_ci    #[inline]
909cdb3e2c8Sopenharmony_ci    fn to_owned(&self) -> Self::Owned {
910cdb3e2c8Sopenharmony_ci        RawOsString(self.0.to_owned())
911cdb3e2c8Sopenharmony_ci    }
912cdb3e2c8Sopenharmony_ci}
913cdb3e2c8Sopenharmony_ci
914cdb3e2c8Sopenharmony_ci/// Extensions to [`Cow<RawOsStr>`] for additional conversions.
915cdb3e2c8Sopenharmony_ci///
916cdb3e2c8Sopenharmony_ci/// [`Cow<RawOsStr>`]: Cow
917cdb3e2c8Sopenharmony_ci#[cfg_attr(os_str_bytes_docs_rs, doc(cfg(feature = "raw_os_str")))]
918cdb3e2c8Sopenharmony_cipub trait RawOsStrCow<'a>: private::Sealed {
919cdb3e2c8Sopenharmony_ci    /// Converts this representation back to a platform-native string.
920cdb3e2c8Sopenharmony_ci    ///
921cdb3e2c8Sopenharmony_ci    /// # Examples
922cdb3e2c8Sopenharmony_ci    ///
923cdb3e2c8Sopenharmony_ci    /// ```
924cdb3e2c8Sopenharmony_ci    /// use std::env;
925cdb3e2c8Sopenharmony_ci    /// # use std::io;
926cdb3e2c8Sopenharmony_ci    ///
927cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
928cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStrCow;
929cdb3e2c8Sopenharmony_ci    ///
930cdb3e2c8Sopenharmony_ci    /// let os_string = env::current_exe()?.into_os_string();
931cdb3e2c8Sopenharmony_ci    /// let raw = RawOsStr::new(&os_string);
932cdb3e2c8Sopenharmony_ci    /// assert_eq!(os_string, raw.into_os_str());
933cdb3e2c8Sopenharmony_ci    /// #
934cdb3e2c8Sopenharmony_ci    /// # Ok::<_, io::Error>(())
935cdb3e2c8Sopenharmony_ci    /// ```
936cdb3e2c8Sopenharmony_ci    #[must_use]
937cdb3e2c8Sopenharmony_ci    fn into_os_str(self) -> Cow<'a, OsStr>;
938cdb3e2c8Sopenharmony_ci
939cdb3e2c8Sopenharmony_ci    /// Returns the byte string stored by this container.
940cdb3e2c8Sopenharmony_ci    ///
941cdb3e2c8Sopenharmony_ci    /// The returned string will use an [unspecified encoding].
942cdb3e2c8Sopenharmony_ci    ///
943cdb3e2c8Sopenharmony_ci    /// # Examples
944cdb3e2c8Sopenharmony_ci    ///
945cdb3e2c8Sopenharmony_ci    /// ```
946cdb3e2c8Sopenharmony_ci    /// use std::borrow::Cow;
947cdb3e2c8Sopenharmony_ci    ///
948cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStr;
949cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsStrCow;
950cdb3e2c8Sopenharmony_ci    ///
951cdb3e2c8Sopenharmony_ci    /// let string = "foobar";
952cdb3e2c8Sopenharmony_ci    /// let raw = Cow::Borrowed(RawOsStr::from_str(string));
953cdb3e2c8Sopenharmony_ci    /// assert_eq!(string.as_bytes(), &*raw.into_raw_bytes());
954cdb3e2c8Sopenharmony_ci    /// ```
955cdb3e2c8Sopenharmony_ci    ///
956cdb3e2c8Sopenharmony_ci    /// [unspecified encoding]: super#encoding
957cdb3e2c8Sopenharmony_ci    #[must_use]
958cdb3e2c8Sopenharmony_ci    fn into_raw_bytes(self) -> Cow<'a, [u8]>;
959cdb3e2c8Sopenharmony_ci}
960cdb3e2c8Sopenharmony_ci
961cdb3e2c8Sopenharmony_ciimpl<'a> RawOsStrCow<'a> for Cow<'a, RawOsStr> {
962cdb3e2c8Sopenharmony_ci    #[inline]
963cdb3e2c8Sopenharmony_ci    fn into_os_str(self) -> Cow<'a, OsStr> {
964cdb3e2c8Sopenharmony_ci        match self {
965cdb3e2c8Sopenharmony_ci            Cow::Borrowed(string) => string.to_os_str(),
966cdb3e2c8Sopenharmony_ci            Cow::Owned(string) => Cow::Owned(string.into_os_string()),
967cdb3e2c8Sopenharmony_ci        }
968cdb3e2c8Sopenharmony_ci    }
969cdb3e2c8Sopenharmony_ci
970cdb3e2c8Sopenharmony_ci    #[inline]
971cdb3e2c8Sopenharmony_ci    fn into_raw_bytes(self) -> Cow<'a, [u8]> {
972cdb3e2c8Sopenharmony_ci        match self {
973cdb3e2c8Sopenharmony_ci            Cow::Borrowed(string) => Cow::Borrowed(&string.0),
974cdb3e2c8Sopenharmony_ci            Cow::Owned(string) => Cow::Owned(string.0),
975cdb3e2c8Sopenharmony_ci        }
976cdb3e2c8Sopenharmony_ci    }
977cdb3e2c8Sopenharmony_ci}
978cdb3e2c8Sopenharmony_ci
979cdb3e2c8Sopenharmony_ci/// A container for owned byte strings converted by this crate.
980cdb3e2c8Sopenharmony_ci///
981cdb3e2c8Sopenharmony_ci/// For more information, see [`RawOsStr`].
982cdb3e2c8Sopenharmony_ci#[derive(Clone, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
983cdb3e2c8Sopenharmony_ci#[cfg_attr(os_str_bytes_docs_rs, doc(cfg(feature = "raw_os_str")))]
984cdb3e2c8Sopenharmony_cipub struct RawOsString(Vec<u8>);
985cdb3e2c8Sopenharmony_ci
986cdb3e2c8Sopenharmony_ciimpl RawOsString {
987cdb3e2c8Sopenharmony_ci    /// Converts a platform-native string into a representation that can be
988cdb3e2c8Sopenharmony_ci    /// more easily manipulated.
989cdb3e2c8Sopenharmony_ci    ///
990cdb3e2c8Sopenharmony_ci    /// For more information, see [`RawOsStr::new`].
991cdb3e2c8Sopenharmony_ci    ///
992cdb3e2c8Sopenharmony_ci    /// # Examples
993cdb3e2c8Sopenharmony_ci    ///
994cdb3e2c8Sopenharmony_ci    /// ```
995cdb3e2c8Sopenharmony_ci    /// use std::env;
996cdb3e2c8Sopenharmony_ci    /// # use std::io;
997cdb3e2c8Sopenharmony_ci    ///
998cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsString;
999cdb3e2c8Sopenharmony_ci    ///
1000cdb3e2c8Sopenharmony_ci    /// let os_string = env::current_exe()?.into_os_string();
1001cdb3e2c8Sopenharmony_ci    /// println!("{:?}", RawOsString::new(os_string));
1002cdb3e2c8Sopenharmony_ci    /// #
1003cdb3e2c8Sopenharmony_ci    /// # Ok::<_, io::Error>(())
1004cdb3e2c8Sopenharmony_ci    /// ```
1005cdb3e2c8Sopenharmony_ci    #[inline]
1006cdb3e2c8Sopenharmony_ci    #[must_use]
1007cdb3e2c8Sopenharmony_ci    pub fn new(string: OsString) -> Self {
1008cdb3e2c8Sopenharmony_ci        Self(imp::os_string_into_vec(string))
1009cdb3e2c8Sopenharmony_ci    }
1010cdb3e2c8Sopenharmony_ci
1011cdb3e2c8Sopenharmony_ci    /// Wraps a string, without copying or encoding conversion.
1012cdb3e2c8Sopenharmony_ci    ///
1013cdb3e2c8Sopenharmony_ci    /// This method is much more efficient than [`RawOsString::new`], since the
1014cdb3e2c8Sopenharmony_ci    /// [encoding] used by this crate is compatible with UTF-8.
1015cdb3e2c8Sopenharmony_ci    ///
1016cdb3e2c8Sopenharmony_ci    /// # Examples
1017cdb3e2c8Sopenharmony_ci    ///
1018cdb3e2c8Sopenharmony_ci    /// ```
1019cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsString;
1020cdb3e2c8Sopenharmony_ci    ///
1021cdb3e2c8Sopenharmony_ci    /// let string = "foobar".to_owned();
1022cdb3e2c8Sopenharmony_ci    /// let raw = RawOsString::from_string(string.clone());
1023cdb3e2c8Sopenharmony_ci    /// assert_eq!(string, raw);
1024cdb3e2c8Sopenharmony_ci    /// ```
1025cdb3e2c8Sopenharmony_ci    ///
1026cdb3e2c8Sopenharmony_ci    /// [encoding]: super#encoding
1027cdb3e2c8Sopenharmony_ci    #[inline]
1028cdb3e2c8Sopenharmony_ci    #[must_use]
1029cdb3e2c8Sopenharmony_ci    pub fn from_string(string: String) -> Self {
1030cdb3e2c8Sopenharmony_ci        Self(string.into_bytes())
1031cdb3e2c8Sopenharmony_ci    }
1032cdb3e2c8Sopenharmony_ci
1033cdb3e2c8Sopenharmony_ci    /// Wraps a byte string, without copying or encoding conversion.
1034cdb3e2c8Sopenharmony_ci    ///
1035cdb3e2c8Sopenharmony_ci    /// # Panics
1036cdb3e2c8Sopenharmony_ci    ///
1037cdb3e2c8Sopenharmony_ci    /// Panics if the string is not valid for the [unspecified encoding] used
1038cdb3e2c8Sopenharmony_ci    /// by this crate.
1039cdb3e2c8Sopenharmony_ci    ///
1040cdb3e2c8Sopenharmony_ci    /// # Examples
1041cdb3e2c8Sopenharmony_ci    ///
1042cdb3e2c8Sopenharmony_ci    /// ```
1043cdb3e2c8Sopenharmony_ci    /// use std::env;
1044cdb3e2c8Sopenharmony_ci    /// # use std::io;
1045cdb3e2c8Sopenharmony_ci    ///
1046cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsString;
1047cdb3e2c8Sopenharmony_ci    ///
1048cdb3e2c8Sopenharmony_ci    /// let os_string = env::current_exe()?.into_os_string();
1049cdb3e2c8Sopenharmony_ci    /// let raw = RawOsString::new(os_string);
1050cdb3e2c8Sopenharmony_ci    /// let raw_bytes = raw.clone().into_raw_vec();
1051cdb3e2c8Sopenharmony_ci    /// assert_eq!(raw, RawOsString::assert_from_raw_vec(raw_bytes));
1052cdb3e2c8Sopenharmony_ci    /// #
1053cdb3e2c8Sopenharmony_ci    /// # Ok::<_, io::Error>(())
1054cdb3e2c8Sopenharmony_ci    /// ```
1055cdb3e2c8Sopenharmony_ci    ///
1056cdb3e2c8Sopenharmony_ci    /// [unspecified encoding]: super#encoding
1057cdb3e2c8Sopenharmony_ci    #[inline]
1058cdb3e2c8Sopenharmony_ci    #[must_use = "method should not be used for validation"]
1059cdb3e2c8Sopenharmony_ci    #[track_caller]
1060cdb3e2c8Sopenharmony_ci    pub fn assert_from_raw_vec(string: Vec<u8>) -> Self {
1061cdb3e2c8Sopenharmony_ci        expect_encoded!(raw::validate_bytes(&string));
1062cdb3e2c8Sopenharmony_ci
1063cdb3e2c8Sopenharmony_ci        Self(string)
1064cdb3e2c8Sopenharmony_ci    }
1065cdb3e2c8Sopenharmony_ci
1066cdb3e2c8Sopenharmony_ci    if_checked_conversions! {
1067cdb3e2c8Sopenharmony_ci        /// Wraps a byte string, without copying or encoding conversion.
1068cdb3e2c8Sopenharmony_ci        ///
1069cdb3e2c8Sopenharmony_ci        /// [`assert_from_raw_vec`] should almost always be used instead. For
1070cdb3e2c8Sopenharmony_ci        /// more information, see [`EncodingError`].
1071cdb3e2c8Sopenharmony_ci        ///
1072cdb3e2c8Sopenharmony_ci        /// # Errors
1073cdb3e2c8Sopenharmony_ci        ///
1074cdb3e2c8Sopenharmony_ci        /// See documentation for [`EncodingError`].
1075cdb3e2c8Sopenharmony_ci        ///
1076cdb3e2c8Sopenharmony_ci        /// # Examples
1077cdb3e2c8Sopenharmony_ci        ///
1078cdb3e2c8Sopenharmony_ci        /// ```
1079cdb3e2c8Sopenharmony_ci        /// use std::env;
1080cdb3e2c8Sopenharmony_ci        /// # use std::io;
1081cdb3e2c8Sopenharmony_ci        ///
1082cdb3e2c8Sopenharmony_ci        /// use os_str_bytes::RawOsString;
1083cdb3e2c8Sopenharmony_ci        ///
1084cdb3e2c8Sopenharmony_ci        /// let os_string = env::current_exe()?.into_os_string();
1085cdb3e2c8Sopenharmony_ci        /// let raw = RawOsString::new(os_string);
1086cdb3e2c8Sopenharmony_ci        /// let raw_clone = raw.clone();
1087cdb3e2c8Sopenharmony_ci        /// assert_eq!(Ok(raw), RawOsString::from_raw_vec(raw_clone.into_raw_vec()));
1088cdb3e2c8Sopenharmony_ci        /// #
1089cdb3e2c8Sopenharmony_ci        /// # Ok::<_, io::Error>(())
1090cdb3e2c8Sopenharmony_ci        /// ```
1091cdb3e2c8Sopenharmony_ci        ///
1092cdb3e2c8Sopenharmony_ci        /// [`assert_from_raw_vec`]: Self::assert_from_raw_vec
1093cdb3e2c8Sopenharmony_ci        #[cfg_attr(
1094cdb3e2c8Sopenharmony_ci            os_str_bytes_docs_rs,
1095cdb3e2c8Sopenharmony_ci            doc(cfg(feature = "checked_conversions"))
1096cdb3e2c8Sopenharmony_ci        )]
1097cdb3e2c8Sopenharmony_ci        #[inline]
1098cdb3e2c8Sopenharmony_ci        pub fn from_raw_vec(string: Vec<u8>) -> Result<Self> {
1099cdb3e2c8Sopenharmony_ci            raw::validate_bytes(&string)
1100cdb3e2c8Sopenharmony_ci                .map(|()| Self(string))
1101cdb3e2c8Sopenharmony_ci                .map_err(EncodingError)
1102cdb3e2c8Sopenharmony_ci        }
1103cdb3e2c8Sopenharmony_ci    }
1104cdb3e2c8Sopenharmony_ci
1105cdb3e2c8Sopenharmony_ci    /// Wraps a byte string, without copying or encoding conversion.
1106cdb3e2c8Sopenharmony_ci    ///
1107cdb3e2c8Sopenharmony_ci    /// # Safety
1108cdb3e2c8Sopenharmony_ci    ///
1109cdb3e2c8Sopenharmony_ci    /// The string must be valid for the [unspecified encoding] used by this
1110cdb3e2c8Sopenharmony_ci    /// crate.
1111cdb3e2c8Sopenharmony_ci    ///
1112cdb3e2c8Sopenharmony_ci    /// # Examples
1113cdb3e2c8Sopenharmony_ci    ///
1114cdb3e2c8Sopenharmony_ci    /// ```
1115cdb3e2c8Sopenharmony_ci    /// use std::env;
1116cdb3e2c8Sopenharmony_ci    /// # use std::io;
1117cdb3e2c8Sopenharmony_ci    ///
1118cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsString;
1119cdb3e2c8Sopenharmony_ci    ///
1120cdb3e2c8Sopenharmony_ci    /// let os_string = env::current_exe()?.into_os_string();
1121cdb3e2c8Sopenharmony_ci    /// let raw = RawOsString::new(os_string);
1122cdb3e2c8Sopenharmony_ci    /// let raw_bytes = raw.clone().into_raw_vec();
1123cdb3e2c8Sopenharmony_ci    /// assert_eq!(raw, unsafe {
1124cdb3e2c8Sopenharmony_ci    ///     RawOsString::from_raw_vec_unchecked(raw_bytes)
1125cdb3e2c8Sopenharmony_ci    /// });
1126cdb3e2c8Sopenharmony_ci    /// #
1127cdb3e2c8Sopenharmony_ci    /// # Ok::<_, io::Error>(())
1128cdb3e2c8Sopenharmony_ci    /// ```
1129cdb3e2c8Sopenharmony_ci    ///
1130cdb3e2c8Sopenharmony_ci    /// [unspecified encoding]: super#encoding
1131cdb3e2c8Sopenharmony_ci    #[inline]
1132cdb3e2c8Sopenharmony_ci    #[must_use]
1133cdb3e2c8Sopenharmony_ci    #[track_caller]
1134cdb3e2c8Sopenharmony_ci    pub unsafe fn from_raw_vec_unchecked(string: Vec<u8>) -> Self {
1135cdb3e2c8Sopenharmony_ci        if cfg!(debug_assertions) {
1136cdb3e2c8Sopenharmony_ci            expect_encoded!(raw::validate_bytes(&string));
1137cdb3e2c8Sopenharmony_ci        }
1138cdb3e2c8Sopenharmony_ci
1139cdb3e2c8Sopenharmony_ci        Self(string)
1140cdb3e2c8Sopenharmony_ci    }
1141cdb3e2c8Sopenharmony_ci
1142cdb3e2c8Sopenharmony_ci    /// Equivalent to [`String::clear`].
1143cdb3e2c8Sopenharmony_ci    ///
1144cdb3e2c8Sopenharmony_ci    /// # Examples
1145cdb3e2c8Sopenharmony_ci    ///
1146cdb3e2c8Sopenharmony_ci    /// ```
1147cdb3e2c8Sopenharmony_ci    /// use std::env;
1148cdb3e2c8Sopenharmony_ci    /// # use std::io;
1149cdb3e2c8Sopenharmony_ci    ///
1150cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsString;
1151cdb3e2c8Sopenharmony_ci    ///
1152cdb3e2c8Sopenharmony_ci    /// let os_string = env::current_exe()?.into_os_string();
1153cdb3e2c8Sopenharmony_ci    /// let mut raw = RawOsString::new(os_string);
1154cdb3e2c8Sopenharmony_ci    /// raw.clear();
1155cdb3e2c8Sopenharmony_ci    /// assert!(raw.is_empty());
1156cdb3e2c8Sopenharmony_ci    /// #
1157cdb3e2c8Sopenharmony_ci    /// # Ok::<_, io::Error>(())
1158cdb3e2c8Sopenharmony_ci    /// ```
1159cdb3e2c8Sopenharmony_ci    #[inline]
1160cdb3e2c8Sopenharmony_ci    pub fn clear(&mut self) {
1161cdb3e2c8Sopenharmony_ci        self.0.clear();
1162cdb3e2c8Sopenharmony_ci    }
1163cdb3e2c8Sopenharmony_ci
1164cdb3e2c8Sopenharmony_ci    /// Equivalent to [`String::into_boxed_str`].
1165cdb3e2c8Sopenharmony_ci    ///
1166cdb3e2c8Sopenharmony_ci    /// # Examples
1167cdb3e2c8Sopenharmony_ci    ///
1168cdb3e2c8Sopenharmony_ci    /// ```
1169cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsString;
1170cdb3e2c8Sopenharmony_ci    ///
1171cdb3e2c8Sopenharmony_ci    /// let string = "foobar".to_owned();
1172cdb3e2c8Sopenharmony_ci    /// let raw = RawOsString::from_string(string.clone());
1173cdb3e2c8Sopenharmony_ci    /// assert_eq!(string, *raw.into_box());
1174cdb3e2c8Sopenharmony_ci    /// ```
1175cdb3e2c8Sopenharmony_ci    #[inline]
1176cdb3e2c8Sopenharmony_ci    #[must_use]
1177cdb3e2c8Sopenharmony_ci    pub fn into_box(self) -> Box<RawOsStr> {
1178cdb3e2c8Sopenharmony_ci        self.0.into_boxed_slice().transmute_box()
1179cdb3e2c8Sopenharmony_ci    }
1180cdb3e2c8Sopenharmony_ci
1181cdb3e2c8Sopenharmony_ci    /// Converts this representation back to a platform-native string.
1182cdb3e2c8Sopenharmony_ci    ///
1183cdb3e2c8Sopenharmony_ci    /// # Examples
1184cdb3e2c8Sopenharmony_ci    ///
1185cdb3e2c8Sopenharmony_ci    /// ```
1186cdb3e2c8Sopenharmony_ci    /// use std::env;
1187cdb3e2c8Sopenharmony_ci    /// # use std::io;
1188cdb3e2c8Sopenharmony_ci    ///
1189cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsString;
1190cdb3e2c8Sopenharmony_ci    ///
1191cdb3e2c8Sopenharmony_ci    /// let os_string = env::current_exe()?.into_os_string();
1192cdb3e2c8Sopenharmony_ci    /// let raw = RawOsString::new(os_string.clone());
1193cdb3e2c8Sopenharmony_ci    /// assert_eq!(os_string, raw.into_os_string());
1194cdb3e2c8Sopenharmony_ci    /// #
1195cdb3e2c8Sopenharmony_ci    /// # Ok::<_, io::Error>(())
1196cdb3e2c8Sopenharmony_ci    /// ```
1197cdb3e2c8Sopenharmony_ci    #[inline]
1198cdb3e2c8Sopenharmony_ci    #[must_use]
1199cdb3e2c8Sopenharmony_ci    pub fn into_os_string(self) -> OsString {
1200cdb3e2c8Sopenharmony_ci        expect_encoded!(imp::os_string_from_vec(self.0))
1201cdb3e2c8Sopenharmony_ci    }
1202cdb3e2c8Sopenharmony_ci
1203cdb3e2c8Sopenharmony_ci    /// Returns the byte string stored by this container.
1204cdb3e2c8Sopenharmony_ci    ///
1205cdb3e2c8Sopenharmony_ci    /// The returned string will use an [unspecified encoding].
1206cdb3e2c8Sopenharmony_ci    ///
1207cdb3e2c8Sopenharmony_ci    /// # Examples
1208cdb3e2c8Sopenharmony_ci    ///
1209cdb3e2c8Sopenharmony_ci    /// ```
1210cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsString;
1211cdb3e2c8Sopenharmony_ci    ///
1212cdb3e2c8Sopenharmony_ci    /// let string = "foobar".to_owned();
1213cdb3e2c8Sopenharmony_ci    /// let raw = RawOsString::from_string(string.clone());
1214cdb3e2c8Sopenharmony_ci    /// assert_eq!(string.into_bytes(), raw.into_raw_vec());
1215cdb3e2c8Sopenharmony_ci    /// ```
1216cdb3e2c8Sopenharmony_ci    ///
1217cdb3e2c8Sopenharmony_ci    /// [unspecified encoding]: super#encoding
1218cdb3e2c8Sopenharmony_ci    #[inline]
1219cdb3e2c8Sopenharmony_ci    #[must_use]
1220cdb3e2c8Sopenharmony_ci    pub fn into_raw_vec(self) -> Vec<u8> {
1221cdb3e2c8Sopenharmony_ci        self.0
1222cdb3e2c8Sopenharmony_ci    }
1223cdb3e2c8Sopenharmony_ci
1224cdb3e2c8Sopenharmony_ci    /// Equivalent to [`OsString::into_string`].
1225cdb3e2c8Sopenharmony_ci    ///
1226cdb3e2c8Sopenharmony_ci    /// # Examples
1227cdb3e2c8Sopenharmony_ci    ///
1228cdb3e2c8Sopenharmony_ci    /// ```
1229cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsString;
1230cdb3e2c8Sopenharmony_ci    ///
1231cdb3e2c8Sopenharmony_ci    /// let string = "foobar".to_owned();
1232cdb3e2c8Sopenharmony_ci    /// let raw = RawOsString::from_string(string.clone());
1233cdb3e2c8Sopenharmony_ci    /// assert_eq!(Ok(string), raw.into_string());
1234cdb3e2c8Sopenharmony_ci    /// ```
1235cdb3e2c8Sopenharmony_ci    #[inline]
1236cdb3e2c8Sopenharmony_ci    pub fn into_string(self) -> result::Result<String, Self> {
1237cdb3e2c8Sopenharmony_ci        String::from_utf8(self.0).map_err(|x| Self(x.into_bytes()))
1238cdb3e2c8Sopenharmony_ci    }
1239cdb3e2c8Sopenharmony_ci
1240cdb3e2c8Sopenharmony_ci    /// Equivalent to [`String::shrink_to_fit`].
1241cdb3e2c8Sopenharmony_ci    ///
1242cdb3e2c8Sopenharmony_ci    /// # Examples
1243cdb3e2c8Sopenharmony_ci    ///
1244cdb3e2c8Sopenharmony_ci    /// ```
1245cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsString;
1246cdb3e2c8Sopenharmony_ci    ///
1247cdb3e2c8Sopenharmony_ci    /// let string = "foobar".to_owned();
1248cdb3e2c8Sopenharmony_ci    /// let mut raw = RawOsString::from_string(string.clone());
1249cdb3e2c8Sopenharmony_ci    /// raw.shrink_to_fit();
1250cdb3e2c8Sopenharmony_ci    /// assert_eq!(string, raw);
1251cdb3e2c8Sopenharmony_ci    /// ```
1252cdb3e2c8Sopenharmony_ci    #[inline]
1253cdb3e2c8Sopenharmony_ci    pub fn shrink_to_fit(&mut self) {
1254cdb3e2c8Sopenharmony_ci        self.0.shrink_to_fit();
1255cdb3e2c8Sopenharmony_ci    }
1256cdb3e2c8Sopenharmony_ci
1257cdb3e2c8Sopenharmony_ci    /// Equivalent to [`String::split_off`].
1258cdb3e2c8Sopenharmony_ci    ///
1259cdb3e2c8Sopenharmony_ci    /// # Panics
1260cdb3e2c8Sopenharmony_ci    ///
1261cdb3e2c8Sopenharmony_ci    /// Panics if the index is not a [valid boundary].
1262cdb3e2c8Sopenharmony_ci    ///
1263cdb3e2c8Sopenharmony_ci    /// # Examples
1264cdb3e2c8Sopenharmony_ci    ///
1265cdb3e2c8Sopenharmony_ci    /// ```
1266cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsString;
1267cdb3e2c8Sopenharmony_ci    ///
1268cdb3e2c8Sopenharmony_ci    /// let mut raw = RawOsString::from_string("foobar".to_owned());
1269cdb3e2c8Sopenharmony_ci    /// assert_eq!("bar", raw.split_off(3));
1270cdb3e2c8Sopenharmony_ci    /// assert_eq!("foo", raw);
1271cdb3e2c8Sopenharmony_ci    /// ```
1272cdb3e2c8Sopenharmony_ci    ///
1273cdb3e2c8Sopenharmony_ci    /// [valid boundary]: RawOsStr#indices
1274cdb3e2c8Sopenharmony_ci    #[inline]
1275cdb3e2c8Sopenharmony_ci    #[must_use]
1276cdb3e2c8Sopenharmony_ci    #[track_caller]
1277cdb3e2c8Sopenharmony_ci    pub fn split_off(&mut self, at: usize) -> Self {
1278cdb3e2c8Sopenharmony_ci        self.check_bound(at);
1279cdb3e2c8Sopenharmony_ci
1280cdb3e2c8Sopenharmony_ci        Self(self.0.split_off(at))
1281cdb3e2c8Sopenharmony_ci    }
1282cdb3e2c8Sopenharmony_ci
1283cdb3e2c8Sopenharmony_ci    /// Equivalent to [`String::truncate`].
1284cdb3e2c8Sopenharmony_ci    ///
1285cdb3e2c8Sopenharmony_ci    /// # Panics
1286cdb3e2c8Sopenharmony_ci    ///
1287cdb3e2c8Sopenharmony_ci    /// Panics if the index is not a [valid boundary].
1288cdb3e2c8Sopenharmony_ci    ///
1289cdb3e2c8Sopenharmony_ci    /// # Examples
1290cdb3e2c8Sopenharmony_ci    ///
1291cdb3e2c8Sopenharmony_ci    /// ```
1292cdb3e2c8Sopenharmony_ci    /// use os_str_bytes::RawOsString;
1293cdb3e2c8Sopenharmony_ci    ///
1294cdb3e2c8Sopenharmony_ci    /// let mut raw = RawOsString::from_string("foobar".to_owned());
1295cdb3e2c8Sopenharmony_ci    /// raw.truncate(3);
1296cdb3e2c8Sopenharmony_ci    /// assert_eq!("foo", raw);
1297cdb3e2c8Sopenharmony_ci    /// ```
1298cdb3e2c8Sopenharmony_ci    ///
1299cdb3e2c8Sopenharmony_ci    /// [valid boundary]: RawOsStr#indices
1300cdb3e2c8Sopenharmony_ci    #[inline]
1301cdb3e2c8Sopenharmony_ci    #[track_caller]
1302cdb3e2c8Sopenharmony_ci    pub fn truncate(&mut self, new_len: usize) {
1303cdb3e2c8Sopenharmony_ci        self.check_bound(new_len);
1304cdb3e2c8Sopenharmony_ci
1305cdb3e2c8Sopenharmony_ci        self.0.truncate(new_len);
1306cdb3e2c8Sopenharmony_ci    }
1307cdb3e2c8Sopenharmony_ci}
1308cdb3e2c8Sopenharmony_ci
1309cdb3e2c8Sopenharmony_ciimpl AsRef<RawOsStr> for RawOsString {
1310cdb3e2c8Sopenharmony_ci    #[inline]
1311cdb3e2c8Sopenharmony_ci    fn as_ref(&self) -> &RawOsStr {
1312cdb3e2c8Sopenharmony_ci        self
1313cdb3e2c8Sopenharmony_ci    }
1314cdb3e2c8Sopenharmony_ci}
1315cdb3e2c8Sopenharmony_ci
1316cdb3e2c8Sopenharmony_ciimpl Borrow<RawOsStr> for RawOsString {
1317cdb3e2c8Sopenharmony_ci    #[inline]
1318cdb3e2c8Sopenharmony_ci    fn borrow(&self) -> &RawOsStr {
1319cdb3e2c8Sopenharmony_ci        self
1320cdb3e2c8Sopenharmony_ci    }
1321cdb3e2c8Sopenharmony_ci}
1322cdb3e2c8Sopenharmony_ci
1323cdb3e2c8Sopenharmony_ciimpl Deref for RawOsString {
1324cdb3e2c8Sopenharmony_ci    type Target = RawOsStr;
1325cdb3e2c8Sopenharmony_ci
1326cdb3e2c8Sopenharmony_ci    #[inline]
1327cdb3e2c8Sopenharmony_ci    fn deref(&self) -> &Self::Target {
1328cdb3e2c8Sopenharmony_ci        RawOsStr::from_inner(&self.0)
1329cdb3e2c8Sopenharmony_ci    }
1330cdb3e2c8Sopenharmony_ci}
1331cdb3e2c8Sopenharmony_ci
1332cdb3e2c8Sopenharmony_ciimpl From<RawOsString> for Box<RawOsStr> {
1333cdb3e2c8Sopenharmony_ci    #[inline]
1334cdb3e2c8Sopenharmony_ci    fn from(value: RawOsString) -> Self {
1335cdb3e2c8Sopenharmony_ci        value.into_box()
1336cdb3e2c8Sopenharmony_ci    }
1337cdb3e2c8Sopenharmony_ci}
1338cdb3e2c8Sopenharmony_ci
1339cdb3e2c8Sopenharmony_ciimpl From<Box<RawOsStr>> for RawOsString {
1340cdb3e2c8Sopenharmony_ci    #[inline]
1341cdb3e2c8Sopenharmony_ci    fn from(value: Box<RawOsStr>) -> Self {
1342cdb3e2c8Sopenharmony_ci        Self(value.transmute_box::<[_]>().into_vec())
1343cdb3e2c8Sopenharmony_ci    }
1344cdb3e2c8Sopenharmony_ci}
1345cdb3e2c8Sopenharmony_ci
1346cdb3e2c8Sopenharmony_ciimpl From<RawOsString> for Cow<'_, RawOsStr> {
1347cdb3e2c8Sopenharmony_ci    #[inline]
1348cdb3e2c8Sopenharmony_ci    fn from(value: RawOsString) -> Self {
1349cdb3e2c8Sopenharmony_ci        Cow::Owned(value)
1350cdb3e2c8Sopenharmony_ci    }
1351cdb3e2c8Sopenharmony_ci}
1352cdb3e2c8Sopenharmony_ci
1353cdb3e2c8Sopenharmony_ciimpl From<String> for RawOsString {
1354cdb3e2c8Sopenharmony_ci    #[inline]
1355cdb3e2c8Sopenharmony_ci    fn from(value: String) -> Self {
1356cdb3e2c8Sopenharmony_ci        Self::from_string(value)
1357cdb3e2c8Sopenharmony_ci    }
1358cdb3e2c8Sopenharmony_ci}
1359cdb3e2c8Sopenharmony_ci
1360cdb3e2c8Sopenharmony_cistruct DebugBuffer<'a>(&'a [u8]);
1361cdb3e2c8Sopenharmony_ci
1362cdb3e2c8Sopenharmony_ciimpl Debug for DebugBuffer<'_> {
1363cdb3e2c8Sopenharmony_ci    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1364cdb3e2c8Sopenharmony_ci        f.write_str("\"")?;
1365cdb3e2c8Sopenharmony_ci
1366cdb3e2c8Sopenharmony_ci        let mut string = self.0;
1367cdb3e2c8Sopenharmony_ci        let mut invalid_length = 0;
1368cdb3e2c8Sopenharmony_ci        while !string.is_empty() {
1369cdb3e2c8Sopenharmony_ci            let (invalid, substring) = string.split_at(invalid_length);
1370cdb3e2c8Sopenharmony_ci
1371cdb3e2c8Sopenharmony_ci            let valid = match str::from_utf8(substring) {
1372cdb3e2c8Sopenharmony_ci                Ok(valid) => {
1373cdb3e2c8Sopenharmony_ci                    string = &[];
1374cdb3e2c8Sopenharmony_ci                    valid
1375cdb3e2c8Sopenharmony_ci                }
1376cdb3e2c8Sopenharmony_ci                Err(error) => {
1377cdb3e2c8Sopenharmony_ci                    let (valid, substring) =
1378cdb3e2c8Sopenharmony_ci                        substring.split_at(error.valid_up_to());
1379cdb3e2c8Sopenharmony_ci
1380cdb3e2c8Sopenharmony_ci                    let invalid_char_length =
1381cdb3e2c8Sopenharmony_ci                        error.error_len().unwrap_or_else(|| substring.len());
1382cdb3e2c8Sopenharmony_ci                    if valid.is_empty() {
1383cdb3e2c8Sopenharmony_ci                        invalid_length += invalid_char_length;
1384cdb3e2c8Sopenharmony_ci                        continue;
1385cdb3e2c8Sopenharmony_ci                    }
1386cdb3e2c8Sopenharmony_ci                    string = substring;
1387cdb3e2c8Sopenharmony_ci                    invalid_length = invalid_char_length;
1388cdb3e2c8Sopenharmony_ci
1389cdb3e2c8Sopenharmony_ci                    // SAFETY: This slice was validated to be UTF-8.
1390cdb3e2c8Sopenharmony_ci                    unsafe { str::from_utf8_unchecked(valid) }
1391cdb3e2c8Sopenharmony_ci                }
1392cdb3e2c8Sopenharmony_ci            };
1393cdb3e2c8Sopenharmony_ci
1394cdb3e2c8Sopenharmony_ci            raw::debug(invalid, f)?;
1395cdb3e2c8Sopenharmony_ci            Display::fmt(&valid.escape_debug(), f)?;
1396cdb3e2c8Sopenharmony_ci        }
1397cdb3e2c8Sopenharmony_ci
1398cdb3e2c8Sopenharmony_ci        f.write_str("\"")
1399cdb3e2c8Sopenharmony_ci    }
1400cdb3e2c8Sopenharmony_ci}
1401cdb3e2c8Sopenharmony_ci
1402cdb3e2c8Sopenharmony_cimacro_rules! r#impl {
1403cdb3e2c8Sopenharmony_ci    ( $type:ty ) => {
1404cdb3e2c8Sopenharmony_ci        impl Debug for $type {
1405cdb3e2c8Sopenharmony_ci            #[inline]
1406cdb3e2c8Sopenharmony_ci            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1407cdb3e2c8Sopenharmony_ci                f.debug_tuple(stringify!($type))
1408cdb3e2c8Sopenharmony_ci                    .field(&DebugBuffer(&self.0))
1409cdb3e2c8Sopenharmony_ci                    .finish()
1410cdb3e2c8Sopenharmony_ci            }
1411cdb3e2c8Sopenharmony_ci        }
1412cdb3e2c8Sopenharmony_ci    };
1413cdb3e2c8Sopenharmony_ci}
1414cdb3e2c8Sopenharmony_cir#impl!(RawOsStr);
1415cdb3e2c8Sopenharmony_cir#impl!(RawOsString);
1416cdb3e2c8Sopenharmony_ci
1417cdb3e2c8Sopenharmony_cimacro_rules! r#impl {
1418cdb3e2c8Sopenharmony_ci    ( $index_type:ty $(, $index_var:ident , $($bound:expr),+)? ) => {
1419cdb3e2c8Sopenharmony_ci        impl Index<$index_type> for RawOsStr {
1420cdb3e2c8Sopenharmony_ci            type Output = Self;
1421cdb3e2c8Sopenharmony_ci
1422cdb3e2c8Sopenharmony_ci            #[inline]
1423cdb3e2c8Sopenharmony_ci            fn index(&self, idx: $index_type) -> &Self::Output {
1424cdb3e2c8Sopenharmony_ci                $(
1425cdb3e2c8Sopenharmony_ci                    let $index_var = &idx;
1426cdb3e2c8Sopenharmony_ci                    $(self.check_bound($bound);)+
1427cdb3e2c8Sopenharmony_ci                )?
1428cdb3e2c8Sopenharmony_ci
1429cdb3e2c8Sopenharmony_ci                Self::from_inner(&self.0[idx])
1430cdb3e2c8Sopenharmony_ci            }
1431cdb3e2c8Sopenharmony_ci        }
1432cdb3e2c8Sopenharmony_ci
1433cdb3e2c8Sopenharmony_ci        impl Index<$index_type> for RawOsString {
1434cdb3e2c8Sopenharmony_ci            type Output = RawOsStr;
1435cdb3e2c8Sopenharmony_ci
1436cdb3e2c8Sopenharmony_ci            #[allow(clippy::indexing_slicing)]
1437cdb3e2c8Sopenharmony_ci            #[inline]
1438cdb3e2c8Sopenharmony_ci            fn index(&self, idx: $index_type) -> &Self::Output {
1439cdb3e2c8Sopenharmony_ci                &(**self)[idx]
1440cdb3e2c8Sopenharmony_ci            }
1441cdb3e2c8Sopenharmony_ci        }
1442cdb3e2c8Sopenharmony_ci    };
1443cdb3e2c8Sopenharmony_ci}
1444cdb3e2c8Sopenharmony_cir#impl!(Range<usize>, x, x.start, x.end);
1445cdb3e2c8Sopenharmony_cir#impl!(RangeFrom<usize>, x, x.start);
1446cdb3e2c8Sopenharmony_cir#impl!(RangeFull);
1447cdb3e2c8Sopenharmony_ci// [usize::MAX] will always be a valid inclusive end index.
1448cdb3e2c8Sopenharmony_ci#[rustfmt::skip]
1449cdb3e2c8Sopenharmony_cir#impl!(RangeInclusive<usize>, x, *x.start(), x.end().wrapping_add(1));
1450cdb3e2c8Sopenharmony_cir#impl!(RangeTo<usize>, x, x.end);
1451cdb3e2c8Sopenharmony_cir#impl!(RangeToInclusive<usize>, x, x.end.wrapping_add(1));
1452cdb3e2c8Sopenharmony_ci
1453cdb3e2c8Sopenharmony_cimacro_rules! r#impl {
1454cdb3e2c8Sopenharmony_ci    ( $type:ty , $other_type:ty ) => {
1455cdb3e2c8Sopenharmony_ci        impl PartialEq<$other_type> for $type {
1456cdb3e2c8Sopenharmony_ci            #[inline]
1457cdb3e2c8Sopenharmony_ci            fn eq(&self, other: &$other_type) -> bool {
1458cdb3e2c8Sopenharmony_ci                let raw: &RawOsStr = self;
1459cdb3e2c8Sopenharmony_ci                let other: &RawOsStr = other.as_ref();
1460cdb3e2c8Sopenharmony_ci                raw == other
1461cdb3e2c8Sopenharmony_ci            }
1462cdb3e2c8Sopenharmony_ci        }
1463cdb3e2c8Sopenharmony_ci
1464cdb3e2c8Sopenharmony_ci        impl PartialEq<$type> for $other_type {
1465cdb3e2c8Sopenharmony_ci            #[inline]
1466cdb3e2c8Sopenharmony_ci            fn eq(&self, other: &$type) -> bool {
1467cdb3e2c8Sopenharmony_ci                other == self
1468cdb3e2c8Sopenharmony_ci            }
1469cdb3e2c8Sopenharmony_ci        }
1470cdb3e2c8Sopenharmony_ci    };
1471cdb3e2c8Sopenharmony_ci}
1472cdb3e2c8Sopenharmony_cir#impl!(RawOsStr, RawOsString);
1473cdb3e2c8Sopenharmony_cir#impl!(&RawOsStr, RawOsString);
1474cdb3e2c8Sopenharmony_cir#impl!(RawOsStr, str);
1475cdb3e2c8Sopenharmony_cir#impl!(RawOsStr, String);
1476cdb3e2c8Sopenharmony_cir#impl!(&RawOsStr, String);
1477cdb3e2c8Sopenharmony_cir#impl!(RawOsString, str);
1478cdb3e2c8Sopenharmony_cir#impl!(RawOsString, &str);
1479cdb3e2c8Sopenharmony_cir#impl!(RawOsString, String);
1480cdb3e2c8Sopenharmony_ci
1481cdb3e2c8Sopenharmony_ci#[cfg(feature = "print_bytes")]
1482cdb3e2c8Sopenharmony_ci#[cfg_attr(os_str_bytes_docs_rs, doc(cfg(feature = "print_bytes")))]
1483cdb3e2c8Sopenharmony_cimod print_bytes {
1484cdb3e2c8Sopenharmony_ci    use print_bytes::ByteStr;
1485cdb3e2c8Sopenharmony_ci    use print_bytes::ToBytes;
1486cdb3e2c8Sopenharmony_ci    #[cfg(windows)]
1487cdb3e2c8Sopenharmony_ci    use print_bytes::WideStr;
1488cdb3e2c8Sopenharmony_ci
1489cdb3e2c8Sopenharmony_ci    #[cfg(windows)]
1490cdb3e2c8Sopenharmony_ci    use crate::imp::raw;
1491cdb3e2c8Sopenharmony_ci
1492cdb3e2c8Sopenharmony_ci    use super::RawOsStr;
1493cdb3e2c8Sopenharmony_ci    use super::RawOsString;
1494cdb3e2c8Sopenharmony_ci
1495cdb3e2c8Sopenharmony_ci    impl ToBytes for RawOsStr {
1496cdb3e2c8Sopenharmony_ci        #[inline]
1497cdb3e2c8Sopenharmony_ci        fn to_bytes(&self) -> ByteStr<'_> {
1498cdb3e2c8Sopenharmony_ci            self.0.to_bytes()
1499cdb3e2c8Sopenharmony_ci        }
1500cdb3e2c8Sopenharmony_ci
1501cdb3e2c8Sopenharmony_ci        #[cfg(windows)]
1502cdb3e2c8Sopenharmony_ci        #[inline]
1503cdb3e2c8Sopenharmony_ci        fn to_wide(&self) -> Option<WideStr> {
1504cdb3e2c8Sopenharmony_ci            Some(WideStr::new(raw::encode_wide_unchecked(&self.0).collect()))
1505cdb3e2c8Sopenharmony_ci        }
1506cdb3e2c8Sopenharmony_ci    }
1507cdb3e2c8Sopenharmony_ci
1508cdb3e2c8Sopenharmony_ci    impl ToBytes for RawOsString {
1509cdb3e2c8Sopenharmony_ci        #[inline]
1510cdb3e2c8Sopenharmony_ci        fn to_bytes(&self) -> ByteStr<'_> {
1511cdb3e2c8Sopenharmony_ci            (**self).to_bytes()
1512cdb3e2c8Sopenharmony_ci        }
1513cdb3e2c8Sopenharmony_ci
1514cdb3e2c8Sopenharmony_ci        #[cfg(windows)]
1515cdb3e2c8Sopenharmony_ci        #[inline]
1516cdb3e2c8Sopenharmony_ci        fn to_wide(&self) -> Option<WideStr> {
1517cdb3e2c8Sopenharmony_ci            (**self).to_wide()
1518cdb3e2c8Sopenharmony_ci        }
1519cdb3e2c8Sopenharmony_ci    }
1520cdb3e2c8Sopenharmony_ci}
1521cdb3e2c8Sopenharmony_ci
1522cdb3e2c8Sopenharmony_ci#[cfg(feature = "uniquote")]
1523cdb3e2c8Sopenharmony_ci#[cfg_attr(os_str_bytes_docs_rs, doc(cfg(feature = "uniquote")))]
1524cdb3e2c8Sopenharmony_cimod uniquote {
1525cdb3e2c8Sopenharmony_ci    use uniquote::Formatter;
1526cdb3e2c8Sopenharmony_ci    use uniquote::Quote;
1527cdb3e2c8Sopenharmony_ci    use uniquote::Result;
1528cdb3e2c8Sopenharmony_ci
1529cdb3e2c8Sopenharmony_ci    use crate::imp::raw;
1530cdb3e2c8Sopenharmony_ci
1531cdb3e2c8Sopenharmony_ci    use super::RawOsStr;
1532cdb3e2c8Sopenharmony_ci    use super::RawOsString;
1533cdb3e2c8Sopenharmony_ci
1534cdb3e2c8Sopenharmony_ci    impl Quote for RawOsStr {
1535cdb3e2c8Sopenharmony_ci        #[inline]
1536cdb3e2c8Sopenharmony_ci        fn escape(&self, f: &mut Formatter<'_>) -> Result {
1537cdb3e2c8Sopenharmony_ci            raw::uniquote::escape(&self.0, f)
1538cdb3e2c8Sopenharmony_ci        }
1539cdb3e2c8Sopenharmony_ci    }
1540cdb3e2c8Sopenharmony_ci
1541cdb3e2c8Sopenharmony_ci    impl Quote for RawOsString {
1542cdb3e2c8Sopenharmony_ci        #[inline]
1543cdb3e2c8Sopenharmony_ci        fn escape(&self, f: &mut Formatter<'_>) -> Result {
1544cdb3e2c8Sopenharmony_ci            (**self).escape(f)
1545cdb3e2c8Sopenharmony_ci        }
1546cdb3e2c8Sopenharmony_ci    }
1547cdb3e2c8Sopenharmony_ci}
1548