summaryrefslogtreecommitdiffstats
path: root/vendor/unic-char-range/src/iter.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/unic-char-range/src/iter.rs')
-rw-r--r--vendor/unic-char-range/src/iter.rs151
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()
+ }
+}