// Copyright Mozilla Foundation // // Licensed under the Apache License (Version 2.0), or the MIT license, // (the "Licenses") at your option. You may not use this file except in // compliance with one of the Licenses. You may obtain copies of the // Licenses at: // // https://www.apache.org/licenses/LICENSE-2.0 // https://opensource.org/licenses/MIT // // Unless required by applicable law or agreed to in writing, software // distributed under the Licenses is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the Licenses for the specific language governing permissions and // limitations under the Licenses.
usecrate::in_inclusive_range16; use core::fmt::Formatter; use core::iter::FusedIterator;
/// A type for signaling UTF-16 errors. /// /// The value of the unpaired surrogate is not exposed in order /// to keep the `Result` type (and `Option`-wrapping thereof) /// the same size as `char`. See an [issue about the representation][1]. /// /// Note: `core::error::Error` is not implemented due to implementing it /// being an [unstable feature][2] at the time of writing. /// /// [1]: https://github.com/rust-lang/rust/issues/118367 /// [2]: https://github.com/rust-lang/rust/issues/103765 #[derive(Debug, PartialEq)] #[non_exhaustive] pubstruct Utf16CharsError;
/// Iterator by `Result<char,Utf16CharsError>` over `&[u16]` that contains /// potentially-invalid UTF-16. There is exactly one `Utf16CharsError` per /// each unpaired surrogate. #[derive(Debug, Clone)] pubstruct ErrorReportingUtf16Chars<'a> {
remaining: &'a [u16],
}
impl<'a> ErrorReportingUtf16Chars<'a> { #[inline(always)] /// Creates the iterator from a `u16` slice. pubfn new(code_units: &'a [u16]) -> Self {
ErrorReportingUtf16Chars::<'a> {
remaining: code_units,
}
}
/// Views the current remaining data in the iterator as a subslice /// of the original slice. #[inline(always)] pubfn as_slice(&self) -> &'a [u16] { self.remaining
}
impl<'a> Iterator for ErrorReportingUtf16Chars<'a> { type Item = Result<char, Utf16CharsError>;
#[inline(always)] fn next(&mutself) -> Option<Result<char, Utf16CharsError>> { // Not delegating directly to `ErrorReportingUtf16Chars` to avoid // an extra branch in the common case based on an inspection of // generated code. Be sure to inspect the generated code as inlined // into an actual usage site carefully if attempting to consolidate // the source code here. let (&first, tail) = self.remaining.split_first()?; self.remaining = tail; let surrogate_base = first.wrapping_sub(0xD800); if surrogate_base > (0xDFFF - 0xD800) { return Some(Ok(unsafe { char::from_u32_unchecked(u32::from(first)) }));
}
Some(self.surrogate_next(surrogate_base, first))
}
}
#[test] fn test_as_slice() { letmut iter = ErrorReportingUtf16Chars::new([0x0061u16, 0x0062u16].as_slice()); let at_start = iter.as_slice();
assert_eq!(iter.next(), Some(Ok('a'))); let in_middle = iter.as_slice();
assert_eq!(iter.next(), Some(Ok('b'))); let at_end = iter.as_slice();
assert_eq!(at_start.len(), 2);
assert_eq!(in_middle.len(), 1);
assert_eq!(at_end.len(), 0);
assert_eq!(at_start[0], 0x0061u16);
assert_eq!(at_start[1], 0x0062u16);
assert_eq!(in_middle[0], 0x0062u16);
}
// Should be a static assert, but not taking a dependency for this. #[test] fn test_size() {
assert_eq!(
core::mem::size_of::<Option<<ErrorReportingUtf16Chars<'_> as Iterator>::Item>>(),
core::mem::size_of::<Option<char>>()
);
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-07-02)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.