summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/library/par.rs4
-rw-r--r--src/util/mod.rs54
2 files changed, 39 insertions, 19 deletions
diff --git a/src/library/par.rs b/src/library/par.rs
index e87d5f67..4568a214 100644
--- a/src/library/par.rs
+++ b/src/library/par.rs
@@ -239,9 +239,9 @@ impl<'a> ParLayouter<'a> {
ParChild::Text(_) => {
// TODO: Also split by language and script.
let mut cursor = range.start;
- for (level, group) in bidi.levels[range].group_by_key(|&lvl| lvl) {
+ for (level, count) in bidi.levels[range].group() {
let start = cursor;
- cursor += group.len();
+ cursor += count;
let subrange = start .. cursor;
let text = &bidi.text[subrange.clone()];
let shaped = shape(ctx.fonts, text, styles, level.dir());
diff --git a/src/util/mod.rs b/src/util/mod.rs
index de37354e..2f91100f 100644
--- a/src/util/mod.rs
+++ b/src/util/mod.rs
@@ -82,9 +82,14 @@ where
/// Additional methods for slices.
pub trait SliceExt<T> {
- /// Split a slice into consecutive groups with the same key.
- ///
- /// Returns an iterator of pairs of a key and the group with that key.
+ /// Find consecutive runs of the same elements in a slice and yield for
+ /// each such run the element and number of times it appears.
+ fn group(&self) -> Group<'_, T>
+ where
+ T: PartialEq;
+
+ /// Split a slice into consecutive runs with the same key and yield for
+ /// each such run the key and the slice of elements with that key.
fn group_by_key<K, F>(&self, f: F) -> GroupByKey<'_, T, F>
where
F: FnMut(&T) -> K,
@@ -92,15 +97,35 @@ pub trait SliceExt<T> {
}
impl<T> SliceExt<T> for [T] {
- fn group_by_key<K, F>(&self, f: F) -> GroupByKey<'_, T, F>
- where
- F: FnMut(&T) -> K,
- K: PartialEq,
- {
+ fn group(&self) -> Group<'_, T> {
+ Group { slice: self }
+ }
+
+ fn group_by_key<K, F>(&self, f: F) -> GroupByKey<'_, T, F> {
GroupByKey { slice: self, f }
}
}
+/// This struct is created by [`SliceExt::group`].
+pub struct Group<'a, T> {
+ slice: &'a [T],
+}
+
+impl<'a, T> Iterator for Group<'a, T>
+where
+ T: PartialEq,
+{
+ type Item = (&'a T, usize);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let mut iter = self.slice.iter();
+ let first = iter.next()?;
+ let count = 1 + iter.take_while(|&t| t == first).count();
+ self.slice = &self.slice[count ..];
+ Some((first, count))
+ }
+}
+
/// This struct is created by [`SliceExt::group_by_key`].
pub struct GroupByKey<'a, T, F> {
slice: &'a [T],
@@ -115,15 +140,10 @@ where
type Item = (K, &'a [T]);
fn next(&mut self) -> Option<Self::Item> {
- let first = self.slice.first()?;
- let key = (self.f)(first);
-
- let mut i = 1;
- while self.slice.get(i).map_or(false, |t| (self.f)(t) == key) {
- i += 1;
- }
-
- let (head, tail) = self.slice.split_at(i);
+ let mut iter = self.slice.iter();
+ let key = (self.f)(iter.next()?);
+ let count = 1 + iter.take_while(|t| (self.f)(t) == key).count();
+ let (head, tail) = self.slice.split_at(count);
self.slice = tail;
Some((key, head))
}