Skip to content

Instantly share code, notes, and snippets.

@florianpircher
Created December 28, 2020 18:23
Show Gist options
  • Save florianpircher/6995c12b37088e445cb65ea6e161096c to your computer and use it in GitHub Desktop.
Save florianpircher/6995c12b37088e445cb65ea6e161096c to your computer and use it in GitHub Desktop.
struct Segment {
start: u16,
end: u16,
id_delta: i16,
}
fn format4_segments(map: &BTreeMap<char, u32>) -> Vec<Segment> {
let mut segments = Vec::<Segment>::new();
let char_spans = map
.iter()
.take_while(|(c, _)| (**c as u32) < 0xFFFF)
.spans(|(c1, _), (c2, _)| (*c1 as u32) + 1 == (*c2 as u32));
for char_span in char_spans {
let glyph_spans = char_span.iter().spans(|(_, g1), (_, g2)| **g1 + 1 == **g2);
for glyph_span in glyph_spans {
let (c1, g1) = glyph_span.first().unwrap();
let (c2, _) = glyph_span.last().unwrap();
let segment = Segment {
start: **c1 as u16,
end: **c2 as u16,
id_delta: ((**g1 as i64) - (**c1 as i64)) as i16,
};
segments.push(segment);
}
}
segments
}
use std::iter::Peekable;
pub struct Spans<I>
where
I: Iterator,
I::Item: Copy,
{
underlying: Peekable<I>,
are_connected: fn(I::Item, I::Item) -> bool,
}
impl<I> Iterator for Spans<I>
where
I: Iterator,
I::Item: Copy,
{
type Item = Vec<I::Item>;
fn next(&mut self) -> Option<Self::Item> {
if let Some(first) = self.underlying.next() {
let mut span = vec![first];
while let Some(next) = self.underlying.peek() {
if (self.are_connected)(*span.last().unwrap(), *next) {
span.push(*next);
self.underlying.next();
} else {
break;
}
}
return Some(span);
}
None
}
}
pub trait SpansExt: Iterator {
fn spans(self, are_connected: fn(Self::Item, Self::Item) -> bool) -> Spans<Self>
where
Self: Sized,
Self::Item: Copy,
{
Spans {
underlying: self.peekable(),
are_connected,
}
}
}
impl<I: Iterator> SpansExt for I {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment