Files
sousa-gecko/third_party/rust/windows-strings/src/decode.rs
T
Erich Gubler 9c8a99ad31 Bug 1990905 - chore(rust): update to windows 0.62 r=glandium,supply-chain-reviewers
This required a coordinated upgrade of several crates at the same time:

- Backports in `third_party/rust/`, which have been merged upstream, and should pose no
  conflict when next integrated from mainline history:
	- `midir`: [Boddlnagg/midir#178](https://github.com/Boddlnagg/midir/pull/178)
	- `neqo`: [mozilla/neqo#3091](https://github.com/mozilla/neqo/pull/3091)
	- `memtest`: [mozilla/memtest#18](https://github.com/mozilla/memtest/pull/18)
		- Consumed by `toolkit/crashreporter/client/app/`.
	- `wgpu*` and `naga` crates: [wgpu#6876](https://github.com/gfx-rs/wgpu/pull/6876)
		- This is consumed by `gfx/wgpu_bindings/`.
		- Includes an upgrade to `gpu_allocator` 0.27.0 → 0.28.0. This could have been an incremental migration first, but I missed it while figuring out what supporting work to break out. Fortunately, this isn't difficult to review.
- `widget/windows/rust/` needed some migration in its direct dependencies, too.

All backports have already been merged upstream, and so should pose no conflict when next integrated.

Differential Revision: https://phabricator.services.mozilla.com/D266878
2025-11-18 22:51:22 +00:00

59 lines
2.2 KiB
Rust

/// An internal helper for decoding an iterator of chars and displaying them
pub struct Decode<F>(pub F);
impl<F, R, E> core::fmt::Display for Decode<F>
where
F: Clone + FnOnce() -> R,
R: IntoIterator<Item = core::result::Result<char, E>>,
{
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
use core::fmt::Write;
let iter = self.0.clone();
for c in iter().into_iter() {
f.write_char(c.unwrap_or(core::char::REPLACEMENT_CHARACTER))?
}
Ok(())
}
}
/// Mirror of `std::char::decode_utf16` for utf-8.
pub fn decode_utf8(
mut buffer: &[u8],
) -> impl Iterator<Item = core::result::Result<char, core::str::Utf8Error>> + '_ {
let mut current = "".chars();
let mut previous_error = None;
core::iter::from_fn(move || {
loop {
match (current.next(), previous_error) {
(Some(c), _) => return Some(Ok(c)),
// Return the previous error
(None, Some(e)) => {
previous_error = None;
return Some(Err(e));
}
// We're completely done
(None, None) if buffer.is_empty() => return None,
(None, None) => {
match core::str::from_utf8(buffer) {
Ok(s) => {
current = s.chars();
buffer = &[];
}
Err(e) => {
let (valid, rest) = buffer.split_at(e.valid_up_to());
// Skip the invalid sequence and stop completely if we ended early
let invalid_sequence_length = e.error_len()?;
buffer = &rest[invalid_sequence_length..];
// Set the current iterator to the valid section and indicate previous error
// SAFETY: `valid` is known to be valid utf-8 from error
current = unsafe { core::str::from_utf8_unchecked(valid) }.chars();
previous_error = Some(e);
}
}
}
}
}
})
}