Skip to content

Commit e967372

Browse files
committed
Auto merge of #104160 - Ayush1325:windows-args, r=m-ou-se
Extract WStrUnits to sys_common::wstr This commit extracts WStrUnits from sys::windows::args to sys_common::wstr. This allows using the same structure for other targets which use wtf8 (example UEFI). This was originally a part of rust-lang/rust#100316 Signed-off-by: Ayush Singh <[email protected]>
2 parents 7e7f389 + 1d92492 commit e967372

File tree

3 files changed

+62
-52
lines changed

3 files changed

+62
-52
lines changed

std/src/sys/windows/args.rs

+2-52
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,16 @@ mod tests;
99
use crate::ffi::OsString;
1010
use crate::fmt;
1111
use crate::io;
12-
use crate::marker::PhantomData;
1312
use crate::num::NonZeroU16;
1413
use crate::os::windows::prelude::*;
1514
use crate::path::PathBuf;
16-
use crate::ptr::NonNull;
1715
use crate::sys::c;
1816
use crate::sys::process::ensure_no_nuls;
1917
use crate::sys::windows::os::current_exe;
18+
use crate::sys_common::wstr::WStrUnits;
2019
use crate::vec;
2120

22-
use core::iter;
21+
use crate::iter;
2322

2423
/// This is the const equivalent to `NonZeroU16::new(n).unwrap()`
2524
///
@@ -199,55 +198,6 @@ impl ExactSizeIterator for Args {
199198
}
200199
}
201200

202-
/// A safe iterator over a LPWSTR
203-
/// (aka a pointer to a series of UTF-16 code units terminated by a NULL).
204-
struct WStrUnits<'a> {
205-
// The pointer must never be null...
206-
lpwstr: NonNull<u16>,
207-
// ...and the memory it points to must be valid for this lifetime.
208-
lifetime: PhantomData<&'a [u16]>,
209-
}
210-
impl WStrUnits<'_> {
211-
/// Create the iterator. Returns `None` if `lpwstr` is null.
212-
///
213-
/// SAFETY: `lpwstr` must point to a null-terminated wide string that lives
214-
/// at least as long as the lifetime of this struct.
215-
unsafe fn new(lpwstr: *const u16) -> Option<Self> {
216-
Some(Self { lpwstr: NonNull::new(lpwstr as _)?, lifetime: PhantomData })
217-
}
218-
fn peek(&self) -> Option<NonZeroU16> {
219-
// SAFETY: It's always safe to read the current item because we don't
220-
// ever move out of the array's bounds.
221-
unsafe { NonZeroU16::new(*self.lpwstr.as_ptr()) }
222-
}
223-
/// Advance the iterator while `predicate` returns true.
224-
/// Returns the number of items it advanced by.
225-
fn advance_while<P: FnMut(NonZeroU16) -> bool>(&mut self, mut predicate: P) -> usize {
226-
let mut counter = 0;
227-
while let Some(w) = self.peek() {
228-
if !predicate(w) {
229-
break;
230-
}
231-
counter += 1;
232-
self.next();
233-
}
234-
counter
235-
}
236-
}
237-
impl Iterator for WStrUnits<'_> {
238-
// This can never return zero as that marks the end of the string.
239-
type Item = NonZeroU16;
240-
fn next(&mut self) -> Option<NonZeroU16> {
241-
// SAFETY: If NULL is reached we immediately return.
242-
// Therefore it's safe to advance the pointer after that.
243-
unsafe {
244-
let next = self.peek()?;
245-
self.lpwstr = NonNull::new_unchecked(self.lpwstr.as_ptr().add(1));
246-
Some(next)
247-
}
248-
}
249-
}
250-
251201
#[derive(Debug)]
252202
pub(crate) enum Arg {
253203
/// Add quotes (if needed)

std/src/sys_common/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ pub mod thread;
3232
pub mod thread_info;
3333
pub mod thread_local_dtor;
3434
pub mod thread_parker;
35+
pub mod wstr;
3536
pub mod wtf8;
3637

3738
cfg_if::cfg_if! {

std/src/sys_common/wstr.rs

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
//! This module contains constructs to work with 16-bit characters (UCS-2 or UTF-16)
2+
#![allow(dead_code)]
3+
4+
use crate::marker::PhantomData;
5+
use crate::num::NonZeroU16;
6+
use crate::ptr::NonNull;
7+
8+
/// A safe iterator over a LPWSTR
9+
/// (aka a pointer to a series of UTF-16 code units terminated by a NULL).
10+
pub struct WStrUnits<'a> {
11+
// The pointer must never be null...
12+
lpwstr: NonNull<u16>,
13+
// ...and the memory it points to must be valid for this lifetime.
14+
lifetime: PhantomData<&'a [u16]>,
15+
}
16+
17+
impl WStrUnits<'_> {
18+
/// Create the iterator. Returns `None` if `lpwstr` is null.
19+
///
20+
/// SAFETY: `lpwstr` must point to a null-terminated wide string that lives
21+
/// at least as long as the lifetime of this struct.
22+
pub unsafe fn new(lpwstr: *const u16) -> Option<Self> {
23+
Some(Self { lpwstr: NonNull::new(lpwstr as _)?, lifetime: PhantomData })
24+
}
25+
26+
pub fn peek(&self) -> Option<NonZeroU16> {
27+
// SAFETY: It's always safe to read the current item because we don't
28+
// ever move out of the array's bounds.
29+
unsafe { NonZeroU16::new(*self.lpwstr.as_ptr()) }
30+
}
31+
32+
/// Advance the iterator while `predicate` returns true.
33+
/// Returns the number of items it advanced by.
34+
pub fn advance_while<P: FnMut(NonZeroU16) -> bool>(&mut self, mut predicate: P) -> usize {
35+
let mut counter = 0;
36+
while let Some(w) = self.peek() {
37+
if !predicate(w) {
38+
break;
39+
}
40+
counter += 1;
41+
self.next();
42+
}
43+
counter
44+
}
45+
}
46+
47+
impl Iterator for WStrUnits<'_> {
48+
// This can never return zero as that marks the end of the string.
49+
type Item = NonZeroU16;
50+
fn next(&mut self) -> Option<NonZeroU16> {
51+
// SAFETY: If NULL is reached we immediately return.
52+
// Therefore it's safe to advance the pointer after that.
53+
unsafe {
54+
let next = self.peek()?;
55+
self.lpwstr = NonNull::new_unchecked(self.lpwstr.as_ptr().add(1));
56+
Some(next)
57+
}
58+
}
59+
}

0 commit comments

Comments
 (0)