From 14fa737b02ab454de922ac5d4a6af6d7c89ccfaa Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Thu, 1 Jul 2021 11:17:35 +0200 Subject: [PATCH] Make word_splitters::Fragments generic over new trait This patch introduces the new word_splitters::Splittable trait and makes word_splitters::Fragments generic over that trait. This allows library users to use their own fragment types and not only core::Word. --- src/core.rs | 6 ++++ src/word_splitters.rs | 70 ++++++++++++++++++++++++------------------- 2 files changed, 45 insertions(+), 31 deletions(-) diff --git a/src/core.rs b/src/core.rs index af024603..e4d0924e 100644 --- a/src/core.rs +++ b/src/core.rs @@ -224,6 +224,12 @@ pub struct Word<'a> { pub(crate) width: usize, } +impl AsRef for Word<'_> { + fn as_ref(&self) -> &str { + &self.word + } +} + impl std::ops::Deref for Word<'_> { type Target = str; diff --git a/src/word_splitters.rs b/src/word_splitters.rs index d3104adb..fff1b2c3 100644 --- a/src/word_splitters.rs +++ b/src/word_splitters.rs @@ -196,39 +196,25 @@ where } #[allow(missing_docs)] -#[derive(Debug)] -pub struct Fragments<'a, I: Iterator> { - word: Word<'a>, - split_points: I, - prev: usize, -} +pub trait Splittable: AsRef { + type Output; -impl<'a> Fragments<'a, std::vec::IntoIter> { #[allow(missing_docs)] - pub fn new(word: Word<'a>, word_splitter: &impl WordSplitter) -> Self { - let split_points = word_splitter.split_points(&word).into_iter(); - Self { - word, - split_points, - prev: 0, - } - } + fn split(&self, range: std::ops::Range, keep_ending: bool) -> Self::Output; } -impl<'a, I: Iterator> Fragments<'a, I> { - fn split(&self, range: std::ops::Range, keep_ending: bool) -> Word<'a> { - let word = &self.word.word[range]; +impl<'a> Splittable for Word<'a> { + type Output = Self; + + fn split(&self, range: std::ops::Range, keep_ending: bool) -> Self::Output { + let word = &self.word[range]; Word { word, width: display_width(word), - whitespace: if keep_ending { - self.word.whitespace - } else { - "" - }, + whitespace: if keep_ending { self.whitespace } else { "" }, penalty: if keep_ending { - self.word.penalty - } else if word.ends_with('-') { + self.penalty + } else if !word.ends_with('-') { "-" } else { "" @@ -237,19 +223,41 @@ impl<'a, I: Iterator> Fragments<'a, I> { } } -impl<'a, I: Iterator> Iterator for Fragments<'a, I> { - type Item = Word<'a>; +#[allow(missing_docs)] +#[derive(Debug)] +pub struct Fragments> { + word: W, + split_points: I, + prev: usize, +} + +impl Fragments> { + #[allow(missing_docs)] + pub fn new(word: W, word_splitter: &impl WordSplitter) -> Self { + let split_points = word_splitter.split_points(word.as_ref()).into_iter(); + Self { + word, + split_points, + prev: 0, + } + } +} + +impl> Iterator for Fragments { + type Item = W::Output; fn next(&mut self) -> Option { if let Some(idx) = self.split_points.next() { - let w = self.split(self.prev..idx, false); + let w = self.word.split(self.prev..idx, false); self.prev = idx; return Some(w); } - if self.prev < self.word.word.len() || self.prev == 0 { - let w = self.split(self.prev..self.word.len(), true); - self.prev = self.word.word.len() + 1; + let len = self.word.as_ref().len(); + if self.prev < len || self.prev == 0 { + let w = self.word.split(self.prev..len, true); + // TODO: shouldn’t this be just len? + self.prev = len + 1; return Some(w); }