]> git.lizzy.rs Git - rust.git/blob - library/std/src/sys_common/wstr.rs
Rollup merge of #107061 - compiler-errors:new-solver-new-candidates-3, r=lcnr
[rust.git] / library / std / src / sys_common / wstr.rs
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 }