From 4547b622d8d29df964fa2914213088b148c498fc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:18:32 +0200 Subject: Merging upstream version 1.67.1+dfsg1. Signed-off-by: Daniel Baumann --- library/std/src/sys_common/wstr.rs | 59 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 library/std/src/sys_common/wstr.rs (limited to 'library/std/src/sys_common/wstr.rs') diff --git a/library/std/src/sys_common/wstr.rs b/library/std/src/sys_common/wstr.rs new file mode 100644 index 000000000..b230fd1a8 --- /dev/null +++ b/library/std/src/sys_common/wstr.rs @@ -0,0 +1,59 @@ +//! This module contains constructs to work with 16-bit characters (UCS-2 or UTF-16) +#![allow(dead_code)] + +use crate::marker::PhantomData; +use crate::num::NonZeroU16; +use crate::ptr::NonNull; + +/// A safe iterator over a LPWSTR +/// (aka a pointer to a series of UTF-16 code units terminated by a NULL). +pub struct WStrUnits<'a> { + // The pointer must never be null... + lpwstr: NonNull, + // ...and the memory it points to must be valid for this lifetime. + lifetime: PhantomData<&'a [u16]>, +} + +impl WStrUnits<'_> { + /// Create the iterator. Returns `None` if `lpwstr` is null. + /// + /// SAFETY: `lpwstr` must point to a null-terminated wide string that lives + /// at least as long as the lifetime of this struct. + pub unsafe fn new(lpwstr: *const u16) -> Option { + Some(Self { lpwstr: NonNull::new(lpwstr as _)?, lifetime: PhantomData }) + } + + pub fn peek(&self) -> Option { + // SAFETY: It's always safe to read the current item because we don't + // ever move out of the array's bounds. + unsafe { NonZeroU16::new(*self.lpwstr.as_ptr()) } + } + + /// Advance the iterator while `predicate` returns true. + /// Returns the number of items it advanced by. + pub fn advance_while bool>(&mut self, mut predicate: P) -> usize { + let mut counter = 0; + while let Some(w) = self.peek() { + if !predicate(w) { + break; + } + counter += 1; + self.next(); + } + counter + } +} + +impl Iterator for WStrUnits<'_> { + // This can never return zero as that marks the end of the string. + type Item = NonZeroU16; + fn next(&mut self) -> Option { + // SAFETY: If NULL is reached we immediately return. + // Therefore it's safe to advance the pointer after that. + unsafe { + let next = self.peek()?; + self.lpwstr = NonNull::new_unchecked(self.lpwstr.as_ptr().add(1)); + Some(next) + } + } +} -- cgit v1.2.3