summaryrefslogtreecommitdiffstats
path: root/vendor/unic-char-range/src/par_iter.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/unic-char-range/src/par_iter.rs')
-rw-r--r--vendor/unic-char-range/src/par_iter.rs110
1 files changed, 110 insertions, 0 deletions
diff --git a/vendor/unic-char-range/src/par_iter.rs b/vendor/unic-char-range/src/par_iter.rs
new file mode 100644
index 000000000..5b40d221a
--- /dev/null
+++ b/vendor/unic-char-range/src/par_iter.rs
@@ -0,0 +1,110 @@
+// Copyright 2018 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 rayon;
+
+use self::rayon::iter::plumbing::{Consumer, ProducerCallback, UnindexedConsumer};
+use self::rayon::prelude::*;
+use crate::step::{AFTER_SURROGATE, BEFORE_SURROGATE};
+use crate::CharRange;
+use core::char;
+use core::ops::Range;
+
+const SKIP_LENGTH: u32 =
+ crate::step::AFTER_SURROGATE as u32 - crate::step::BEFORE_SURROGATE as u32 - 1;
+
+#[derive(Clone, Debug)]
+pub struct Iter(rayon::iter::Map<rayon::range::Iter<u32>, fn(u32) -> char>);
+
+impl ParallelIterator for Iter {
+ type Item = char;
+
+ fn drive_unindexed<C>(self, consumer: C) -> C::Result
+ where
+ C: UnindexedConsumer<Self::Item>,
+ {
+ self.0.drive_unindexed(consumer)
+ }
+}
+
+impl IndexedParallelIterator for Iter {
+ fn len(&self) -> usize {
+ self.0.len()
+ }
+
+ fn drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result {
+ self.0.drive(consumer)
+ }
+
+ fn with_producer<CB: ProducerCallback<Self::Item>>(self, callback: CB) -> CB::Output {
+ self.0.with_producer(callback)
+ }
+}
+
+impl CharRange {
+ fn compact_range(&self) -> Range<u32> {
+ let low = self.low as u32;
+ let high = self.high as u32 + 1;
+ low..(if self.high >= AFTER_SURROGATE {
+ high - SKIP_LENGTH
+ } else {
+ high
+ })
+ }
+}
+
+impl IntoParallelIterator for CharRange {
+ type Item = char;
+ type Iter = Iter;
+
+ fn into_par_iter(self) -> Self::Iter {
+ Iter(self.compact_range().into_par_iter().map(|c| {
+ let c = if c > BEFORE_SURROGATE as u32 {
+ c + SKIP_LENGTH
+ } else {
+ c
+ };
+ debug_assert!(c <= BEFORE_SURROGATE as u32 || c >= AFTER_SURROGATE as u32);
+ debug_assert!(c <= char::MAX as u32);
+ #[allow(unsafe_code)]
+ unsafe {
+ char::from_u32_unchecked(c)
+ }
+ }))
+ }
+}
+
+impl<'a> IntoParallelIterator for &'a CharRange {
+ type Item = char;
+ type Iter = Iter;
+
+ fn into_par_iter(self) -> Self::Iter {
+ (*self).into_par_iter()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn length_agrees() {
+ assert_eq!(chars!(..).iter().count(), chars!(..).par_iter().count())
+ }
+
+ #[test]
+ #[cfg(feature = "std")]
+ fn content_agrees() {
+ assert_eq!(
+ chars!(..).iter().collect::<Vec<_>>(),
+ chars!(..).par_iter().collect::<Vec<_>>()
+ )
+ }
+}