wstr.rs - source
Description: Source of the Rust file `library/std/src/sys/helpers/wstr.rs`.

#
std/sys/helpers/
wstr.rs

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