diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
commit | 698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch) | |
tree | 173a775858bd501c378080a10dca74132f05bc50 /vendor/unic-char-range/src/iter.rs | |
parent | Initial commit. (diff) | |
download | rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip |
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/unic-char-range/src/iter.rs')
-rw-r--r-- | vendor/unic-char-range/src/iter.rs | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/vendor/unic-char-range/src/iter.rs b/vendor/unic-char-range/src/iter.rs new file mode 100644 index 000000000..44901dfe3 --- /dev/null +++ b/vendor/unic-char-range/src/iter.rs @@ -0,0 +1,151 @@ +// Copyright 2017 The UNIC Project Developers. +// +// See the COPYRIGHT file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::{char, ops}; + +use crate::{step, CharRange}; + +const SURROGATE_RANGE: ops::Range<u32> = 0xD800..0xE000; + +/// An iterator over a range of unicode code points. +/// +/// Constructed via `CharRange::iter`. See `CharRange` for more information. +#[derive(Clone, Debug)] +pub struct CharIter { + /// The lowest uniterated character (inclusive). + /// + /// Iteration is finished if this is higher than `high`. + low: char, + + /// The highest uniterated character (inclusive). + /// + /// Iteration is finished if this is lower than `low`. + high: char, +} + +impl From<CharRange> for CharIter { + fn from(range: CharRange) -> CharIter { + CharIter { + low: range.low, + high: range.high, + } + } +} + +impl From<CharIter> for CharRange { + fn from(iter: CharIter) -> CharRange { + CharRange { + low: iter.low, + high: iter.high, + } + } +} + +impl CharIter { + #[inline] + #[allow(unsafe_code)] + // When stepping `self.low` forward would go over `char::MAX`, + // Set `self.high` to `'\0'` instead. It will have the same effect -- + // consuming the last element from the iterator and ending iteration. + fn step_forward(&mut self) { + if self.low == char::MAX { + self.high = '\0' + } else { + self.low = unsafe { step::forward(self.low) } + } + } + + #[inline] + #[allow(unsafe_code)] + // When stepping `self.high` backward would cause underflow, + // set `self.low` to `char::MAX` instead. It will have the same effect -- + // consuming the last element from the iterator and ending iteration. + fn step_backward(&mut self) { + if self.high == '\0' { + self.low = char::MAX; + } else { + self.high = unsafe { step::backward(self.high) } + } + } + + #[inline] + /// ExactSizeIterator::is_empty() for stable + fn is_finished(&self) -> bool { + self.low > self.high + } +} + +impl Iterator for CharIter { + type Item = char; + + #[inline] + fn next(&mut self) -> Option<char> { + if self.is_finished() { + return None; + } + + let ch = self.low; + self.step_forward(); + Some(ch) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + let len = self.len(); + (len, Some(len)) + } + + fn last(self) -> Option<char> { + if self.is_finished() { + None + } else { + Some(self.high) + } + } + + fn max(self) -> Option<char> { + self.last() + } + + fn min(mut self) -> Option<char> { + self.next() + } +} + +impl DoubleEndedIterator for CharIter { + #[inline] + fn next_back(&mut self) -> Option<Self::Item> { + if self.is_finished() { + None + } else { + let ch = self.high; + self.step_backward(); + Some(ch) + } + } +} + +impl ExactSizeIterator for CharIter { + fn len(&self) -> usize { + if self.is_finished() { + return 0; + } + let naive_range = (self.low as u32)..(self.high as u32 + 1); + if naive_range.start <= SURROGATE_RANGE.start && SURROGATE_RANGE.end <= naive_range.end { + naive_range.len() - SURROGATE_RANGE.len() + } else { + naive_range.len() + } + } + + #[cfg(feature = "exact-size-is-empty")] + fn is_empty(&self) -> bool { + self.is_finished() + } +} |