This gives me a "duplicated code" warning. write_iter_fmt is used inside Display implementations, write_iter_io everywhere else. Any way to avoid the duplication? Thanks!
fn write_iter_fmt<T: Display, W: std::fmt::Write>(w: &mut W, iter: &mut Iter<T>, sep: &str)
-> std::fmt::Result {
if let Some(first) = iter.next() {
write!(w, "{}", first)?;
for item in iter {
write!(w, "{}{}", sep, item)?;
}
}
Ok(())
}
fn write_iter_io<T: Display, W: std::io::Write>(w: &mut W, iter: &mut Iter<T>, sep: &str)
-> std::io::Result<()> {
if let Some(first) = iter.next() {
write!(w, "{}", first)?;
for item in iter {
write!(w, "{}{}", sep, item)?;
}
}
Ok(())
}
(Internally, the actual adaptation happens in std::io::Write::write_fmt(), the method that write!() calls.)
As long as you don't write a public function that demands fmt::Write, you won't encounter a need to have a separate one for io::Write. I feel that this approach is elegant and makes the best use of the flexibility already provided by the standard library.
Note though that with a &I where I: Iterator you can't really do much, since iterating it requires an &mut reference. Storing I or &mut I won't help either because Display::fmt takes a &self. You'll have to do something like storing a Cell<Option<I>> and .take() it.
I'm sorry, I made a think-o — that should have been ownership, and I briefly thought “well we're just formatting, so we don't need to take ownership”, but no. Fixed. [Edit again: or not fixed, due to the &self issue you point out.]
This does make things a little weird since the DisplayIter value can only be printed once.
A better idea might be to keep the original write_iter_fmt function, and say “This should only be used from a formatting trait implementation that creates the iterator to be formatted”.