pub(crate) fn join_budgeted_sections<I, S>(
sections: I,
separator: &str,
budget: usize,
omit: impl Fn(usize) -> String,
) -> String
where
I: IntoIterator<Item = S>,
S: AsRef<str>,
{
let sections: Vec<S> = sections.into_iter().collect();
let mut body = String::new();
for (index, section) in sections.iter().enumerate() {
let section = section.as_ref();
let separator = if index == 0 { "" } else { separator };
let remaining = sections.len() - index;
let omission = {
let text = omit(remaining);
if body.is_empty() {
text
} else {
format!("{separator}{text}")
}
};
if body.len() + separator.len() + section.len() + omission.len() > budget {
if body.len() + omission.len() <= budget {
body.push_str(&omission);
}
break;
}
body.push_str(separator);
body.push_str(section);
}
body
}