Add group in addition to group_by_key

This commit is contained in:
Laurenz 2022-02-04 21:32:14 +01:00
parent bdc7127adf
commit 90fb28b4b6
2 changed files with 39 additions and 19 deletions

View File

@ -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());

View File

@ -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))
}