Skip to main content

WtfStr

Struct WtfStr 

Source
pub struct WtfStr<E: WtfEncoding> { /* private fields */ }
Expand description

A borrowed string slice of code units in encoding E (the analog of OsStr / str).

This is #[repr(transparent)] over [E::Unit], so a &WtfStr<E> can be created from a &[E::Unit] without copying. The units are the string’s content: there is no terminator here, since the always-terminated invariant is a property of the owned WtfString, not of an arbitrary borrowed slice.

Implementations§

Source§

impl WtfStr<Wtf16>

Source

pub fn to_os_string(&self) -> OsString

Decode the content into an owned OsString, losslessly.

The OsStringExt::from_wide bridge: unpaired surrogates are preserved.

Source

pub fn encode_wide(&self) -> impl Iterator<Item = u16> + '_

Iterate the content as wide code units, zero-copy: the OsStrExt::encode_wide analog over our own slice.

Source§

impl<E: WtfEncoding> WtfStr<E>

Source

pub fn from_units(units: &[E::Unit]) -> &WtfStr<E>

Wrap a slice of code units as a &WtfStr<E> without copying.

Examples found in repository?
examples/win32_round_trip.rs (line 83)
67    pub fn run() {
68        let input = Wtf16String::from(r"C:\Windows\System32\..\Temp");
69        println!("input : {input}");
70
71        match full_path(&input) {
72            Some(expanded) => println!("expanded: {expanded}"),
73            None => println!("expanded: <GetFullPathNameW failed>"),
74        }
75
76        compare(&Wtf16String::from("alpha"), &Wtf16String::from("beta"));
77        compare(&Wtf16String::from("beta"), &Wtf16String::from("alpha"));
78        compare(&Wtf16String::from("same"), &Wtf16String::from("same"));
79
80        // The counted pair works on a borrowed slice, which has no terminator
81        // of its own -- the length is what makes it well-defined.
82        let units: Vec<u16> = "borrowed".encode_utf16().collect();
83        let borrowed = Wtf16Str::from_units(&units);
84        println!(
85            "borrowed slice of {} units compares equal to itself: {}",
86            borrowed.len(),
87            ordinal(borrowed, borrowed) == CSTR_EQUAL
88        );
89    }
Source

pub fn as_units(&self) -> &[E::Unit]

The content code units (there is no terminator on a borrowed slice).

Source

pub fn len(&self) -> usize

The number of content code units (not bytes, not code points).

Examples found in repository?
examples/win32_round_trip.rs (line 86)
67    pub fn run() {
68        let input = Wtf16String::from(r"C:\Windows\System32\..\Temp");
69        println!("input : {input}");
70
71        match full_path(&input) {
72            Some(expanded) => println!("expanded: {expanded}"),
73            None => println!("expanded: <GetFullPathNameW failed>"),
74        }
75
76        compare(&Wtf16String::from("alpha"), &Wtf16String::from("beta"));
77        compare(&Wtf16String::from("beta"), &Wtf16String::from("alpha"));
78        compare(&Wtf16String::from("same"), &Wtf16String::from("same"));
79
80        // The counted pair works on a borrowed slice, which has no terminator
81        // of its own -- the length is what makes it well-defined.
82        let units: Vec<u16> = "borrowed".encode_utf16().collect();
83        let borrowed = Wtf16Str::from_units(&units);
84        println!(
85            "borrowed slice of {} units compares equal to itself: {}",
86            borrowed.len(),
87            ordinal(borrowed, borrowed) == CSTR_EQUAL
88        );
89    }
90
91    /// Terminated input, then buffer-fill output -- both without converting.
92    fn full_path(input: &Wtf16String) -> Option<Wtf16String> {
93        // Pass 1: ask for the size. The terminator is already in the buffer, so
94        // handing over an `LPCWSTR` costs nothing.
95        // SAFETY: `as_terminated_ptr` is NUL-terminated and valid while
96        // `input` is borrowed; a zero length asks for the required size only.
97        let needed = unsafe {
98            GetFullPathNameW(
99                input.as_terminated_ptr(),
100                0,
101                core::ptr::null_mut(),
102                core::ptr::null_mut(),
103            )
104        };
105        if needed == 0 {
106            return None;
107        }
108
109        // `needed` counts the terminator; our capacity is a *content* length,
110        // and `with_capacity` reserves the terminator slot itself.
111        let mut out = Wtf16String::with_capacity(needed as usize - 1);
112
113        // Pass 2: let the API write straight into our buffer.
114        // SAFETY: the buffer has room for `needed` units (content + the
115        // reserved terminator slot), which is exactly what pass 1 asked for.
116        let written = unsafe {
117            GetFullPathNameW(
118                input.as_terminated_ptr(),
119                needed,
120                out.as_mut_ptr(),
121                core::ptr::null_mut(),
122            )
123        };
124        if written == 0 || written >= needed {
125            // Failed, or raced a directory change and now wants more room.
126            // `out`'s invariant is still broken here, so republish an empty
127            // string before dropping it (see `as_mut_ptr`'s contract).
128            // SAFETY: publishing zero content units is always in bounds.
129            unsafe { out.set_len_from_ffi(0) };
130            return None;
131        }
132
133        // `written` excludes the terminator, which is precisely the content
134        // length `set_len_from_ffi` wants -- no guessing about conventions.
135        // SAFETY: the API initialized `written` units and `written < needed`,
136        // so the appended terminator still fits.
137        unsafe { out.set_len_from_ffi(written as usize) };
138        Some(out)
139    }
140
141    /// Counted input: pointer + length, no terminator required.
142    fn ordinal(a: &Wtf16Str, b: &Wtf16Str) -> i32 {
143        // SAFETY: each pointer is valid for exactly its own `len()` units while
144        // borrowed, which is the contract `CompareStringOrdinal` expects.
145        unsafe {
146            CompareStringOrdinal(
147                a.as_ptr(),
148                a.len() as i32,
149                b.as_ptr(),
150                b.len() as i32,
151                0, // case-sensitive
152            )
153        }
154    }
Source

pub fn is_empty(&self) -> bool

Whether the string has no content units.

Source

pub fn has_interior_nul(&self) -> bool

Whether the content contains a NUL (E::NUL) code unit.

For the Wtf16 arm, a terminated LPCWSTR view of an owned string is a valid C string only when this is false (see Wtf16String::as_terminated_ptr); counted access is always valid regardless of this encoding’s storage width.

Source

pub fn to_string_checked(&self) -> Option<String>

Decode to a String if the content is well-formed for this encoding.

Returns None for content a strict String cannot hold (e.g. an unpaired surrogate in WTF-16); use to_string_lossy to decode with replacement instead.

Source

pub fn to_string_lossy(&self) -> String

Decode to a String, replacing any ill-formed sequence with U+FFFD.

Source§

impl WtfStr<Wtf16>

Source

pub fn as_ptr(&self) -> *const u16

A pointer to the content code units, for counted FFI paired with len.

The pointer is not guaranteed to be NUL-terminated (a borrowed slice carries no terminator); use it only with the matching unit count. It is valid while self is borrowed and unmodified. For a terminated LPCWSTR, start from an owned Wtf16String and use Wtf16String::as_terminated_ptr.

Examples found in repository?
examples/win32_round_trip.rs (line 147)
142    fn ordinal(a: &Wtf16Str, b: &Wtf16Str) -> i32 {
143        // SAFETY: each pointer is valid for exactly its own `len()` units while
144        // borrowed, which is the contract `CompareStringOrdinal` expects.
145        unsafe {
146            CompareStringOrdinal(
147                a.as_ptr(),
148                a.len() as i32,
149                b.as_ptr(),
150                b.len() as i32,
151                0, // case-sensitive
152            )
153        }
154    }

Trait Implementations§

Source§

impl<E: WtfEncoding> AsRef<WtfStr<E>> for WtfString<E>

Source§

fn as_ref(&self) -> &WtfStr<E>

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl<E: WtfEncoding> AsRef<WtfStr<E>> for WtfStr<E>

Source§

fn as_ref(&self) -> &WtfStr<E>

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl<E: WtfEncoding> Borrow<WtfStr<E>> for WtfString<E>

Source§

fn borrow(&self) -> &WtfStr<E>

Immutably borrows from an owned value. Read more
Source§

impl<E: WtfEncoding> Debug for WtfStr<E>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<E: WtfEncoding> Display for WtfStr<E>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<E: WtfEncoding> Eq for WtfStr<E>

Source§

impl From<&WtfStr<Wtf16>> for OsString

Source§

fn from(s: &Wtf16Str) -> Self

Converts to this type from the input type.
Source§

impl<E: WtfEncoding> Hash for WtfStr<E>

Source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
Source§

impl<E: WtfEncoding> Ord for WtfStr<E>

Source§

fn cmp(&self, other: &Self) -> Ordering

This method returns an Ordering between self and other. Read more
Source§

impl<E: WtfEncoding> PartialEq for WtfStr<E>

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl<E: WtfEncoding> PartialEq<&str> for WtfStr<E>

Source§

fn eq(&self, other: &&str) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl<E: WtfEncoding> PartialEq<str> for WtfStr<E>

Source§

fn eq(&self, other: &str) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl<E: WtfEncoding> PartialOrd for WtfStr<E>

Source§

fn partial_cmp(&self, other: &Self) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 (const: unstable) · Source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 (const: unstable) · Source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 (const: unstable) · Source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 (const: unstable) · Source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Source§

impl<E: WtfEncoding> ToOwned for WtfStr<E>

Source§

type Owned = WtfString<E>

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> WtfString<E>

Creates owned data from borrowed data, usually by cloning. Read more
1.63.0 · Source§

fn clone_into(&self, target: &mut Self::Owned)

Uses borrowed data to replace owned data, usually by cloning. Read more

Auto Trait Implementations§

§

impl<E> !Sized for WtfStr<E>

§

impl<E> Freeze for WtfStr<E>
where [<E as WtfEncoding>::Unit]: Freeze,

§

impl<E> RefUnwindSafe for WtfStr<E>
where [<E as WtfEncoding>::Unit]: RefUnwindSafe,

§

impl<E> Send for WtfStr<E>
where [<E as WtfEncoding>::Unit]: Send,

§

impl<E> Sync for WtfStr<E>
where [<E as WtfEncoding>::Unit]: Sync,

§

impl<E> Unpin for WtfStr<E>
where [<E as WtfEncoding>::Unit]: Unpin,

§

impl<E> UnsafeUnpin for WtfStr<E>
where [<E as WtfEncoding>::Unit]: UnsafeUnpin,

§

impl<E> UnwindSafe for WtfStr<E>
where [<E as WtfEncoding>::Unit]: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more