Skip to content

Commit 2c97d10

Browse files
committed
Fix wrong assumption in DecodeUtf16::size_hint
`self.buf` can contain a surrogate, but only a leading one.
1 parent 9c8cd1f commit 2c97d10

File tree

2 files changed

+11
-5
lines changed

2 files changed

+11
-5
lines changed

library/core/src/char/decode.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,15 @@ impl<I: Iterator<Item = u16>> Iterator for DecodeUtf16<I> {
121121
fn size_hint(&self) -> (usize, Option<usize>) {
122122
let (low, high) = self.iter.size_hint();
123123

124-
// `self.buf` will never contain the first part of a surrogate,
125-
// so the presence of `buf == Some(...)` always means +1
126-
// on lower and upper bound.
127-
let addition_from_buf = self.buf.is_some() as usize;
124+
// If
125+
// - `self.buf` contains a non surrogate (`u < 0xD800 || 0xDFFF < u`), or
126+
// - `high == Some(0)` (and `self.buf` contains a leading surrogate since
127+
// it can never contain a trailing surrogate)
128+
//
129+
// then buf contains an additional character or error that doesn't
130+
// need a pair from `self.iter`, so it's +1 additional element.
131+
let addition_from_buf =
132+
self.buf.map_or(false, |u| u < 0xD800 || 0xDFFF < u || high == Some(0)) as usize;
128133

129134
// `self.iter` could contain entirely valid surrogates (2 elements per
130135
// char), or entirely non-surrogates (1 element per char).

library/core/tests/char.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ fn test_decode_utf16_size_hint() {
319319

320320
assert!(
321321
lower <= count && count <= upper.unwrap(),
322-
"lower = {lower}, upper = {upper:?}"
322+
"lower = {lower}, count = {count}, upper = {upper:?}"
323323
);
324324

325325
if let None = iter.next() {
@@ -328,6 +328,7 @@ fn test_decode_utf16_size_hint() {
328328
}
329329
}
330330

331+
check(&[0xD800, 0xD800, 0xDC00]);
331332
check(&[0xD800, 0x41, 0x42]);
332333
check(&[0xD800, 0]);
333334
check(&[0xD834, 0x006d]);

0 commit comments

Comments
 (0)