1 //! This module contains constructs to work with 16-bit characters (UCS-2 or UTF-16)
4 use crate::marker
::PhantomData
;
5 use crate::num
::NonZeroU16
;
6 use crate::ptr
::NonNull
;
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...
13 // ...and the memory it points to must be valid for this lifetime.
14 lifetime
: PhantomData
<&'a
[u16]>,
18 /// Create the iterator. Returns `None` if `lpwstr` is null.
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 }
)
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()) }
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 {
36 while let Some(w
) = self.peek() {
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.
54 let next
= self.peek()?
;
55 self.lpwstr
= NonNull
::new_unchecked(self.lpwstr
.as_ptr().add(1));