Skip to main content

wtf_string/string/
param.rs

1// Copyright (c) 2026 Mike Grier
2//! `windows`-crate `Param<PCWSTR>` interop, behind the `windows-core` feature.
3//!
4//! The high-level `windows` crate spells a wide string parameter as
5//! `impl Param<PCWSTR>` rather than a bare `*const u16`, so a call site cannot
6//! hand it our type without a conversion unless we satisfy that bound. This
7//! module supplies exactly that (D-10): the terminated pointer that
8//! [`Wtf16String`] already keeps for free (D-7) is wrapped in a `PCWSTR` and
9//! handed over, so the zero-conversion, zero-allocation path reaches `windows`
10//! call sites as well as raw `windows-sys` ones.
11//!
12//! See DESIGN-NOTES `D-17` for the two constraints this seam carries: it is
13//! written against one `windows-core` version, and it binds to that crate's
14//! `#[doc(hidden)]` `Param` machinery because implementing the trait is the only
15//! way to satisfy the bound.
16
17use windows_core::{PCWSTR, Param, ParamValue};
18
19use super::Wtf16String;
20
21/// Pass a `&Wtf16String` directly to a `windows` API taking `impl Param<PCWSTR>`.
22///
23/// The pointer handed over is [`as_terminated_ptr`](Wtf16String::as_terminated_ptr):
24/// no conversion, no allocation, and no copy. It stays valid for the call because
25/// the borrow keeps the owning `Wtf16String` alive and unmodified.
26///
27/// This carries exactly the C-string caveat of the pointer it wraps (D-7): the
28/// callee stops at the first NUL, so a value with an interior NUL is seen
29/// truncated. Check [`has_interior_nul`](super::WtfStr::has_interior_nul) first
30/// when the content may contain one. `&HSTRING`'s own `Param<PCWSTR>` impl has
31/// the same property, so this is parity with the ecosystem, not a new hazard.
32///
33/// There is deliberately **no** impl for `&Wtf16Str`: a borrowed slice carries no
34/// terminator (D-7), so it has no valid `PCWSTR` to give. Borrowed content
35/// reaches Win32 through the counted pair
36/// [`as_ptr`](super::Wtf16Str::as_ptr) + [`len`](super::WtfStr::len) instead.
37impl Param<PCWSTR> for &Wtf16String {
38    unsafe fn param(self) -> ParamValue<PCWSTR> {
39        // `Owned` names the *`PCWSTR` value*, not the string data: `PCWSTR` is a
40        // `Copy` pointer wrapper that owns nothing and is never freed by the
41        // callee. This mirrors `&HSTRING`'s impl, which likewise wraps a borrowed
42        // interior pointer. The borrow in `self` is what keeps the data alive.
43        ParamValue::Owned(PCWSTR(self.as_terminated_ptr()))
44    }
45}
46
47#[cfg(test)]
48mod tests;