use super::chunk::{Chunk, ChunkPart};
use std::iter::Peekable;
pub fn prefix<I>(
tokens: &mut Peekable<I>,
width: usize,
offset: &mut ChunkPart,
) -> Vec<Chunk>
where
I: Iterator<Item = Chunk>,
{
let mut available = width;
let mut chunks = Vec::new();
loop {
let result = {
let next_chunk = match tokens.peek() {
None => break,
Some(chunk) => chunk,
};
consider_chunk(available + offset.width, next_chunk)
};
match result {
ChunkFitResult::Fits => {
let mut chunk = tokens.next().unwrap();
chunk.remove_front(*offset);
offset.length = 0;
offset.width = 0;
available -= chunk.width;
chunks.push(chunk);
continue;
}
ChunkFitResult::FitsBarely => {
let mut chunk = tokens.next().unwrap();
chunk.remove_front(*offset);
offset.length = 0;
offset.width = 0;
chunk.remove_last_char();
chunks.push(chunk);
break;
}
ChunkFitResult::DoesNotFit => {
break;
}
}
}
chunks
}
enum ChunkFitResult {
Fits,
FitsBarely,
DoesNotFit,
}
fn consider_chunk(available: usize, chunk: &Chunk) -> ChunkFitResult {
if chunk.width <= available {
if chunk.hard_stop {
ChunkFitResult::FitsBarely
} else {
ChunkFitResult::Fits
}
} else if chunk.width == available + 1 {
if chunk.ends_with_space {
ChunkFitResult::FitsBarely
} else {
ChunkFitResult::DoesNotFit
}
} else {
ChunkFitResult::DoesNotFit
}
}