Format should not panic if you try to format it more than once
Some logging frameworks will format things sent to the error! macro twice.
Some possible solutions:
- Print a "iterator exhausted" message instead of panicking
- Impose a
Clonebound on the iterator being formatted so that we can format it multiple times - Doesn't
fmtreturn aResultanyway? Why not just returnErr?
(3) From previous discussion I have understood that fmt's error return should not be used by the thing that is being formatted. It's used to relay the information that an I/O error happened through the formatting chain.
I don't know how to solve it, I think this is a drawback that comes from our skirting the rules a bit for formatting.
As an alternative to changing the behavior of the existing format, how about a separate extension-trait on copyable sources of iterators providing a "safe format" type, so that into_iter() is called every time fmt is called?
trait IterSafeFormatExt {
type I;
fn safe_format(&self, separator: &'static str) -> SafeFormat<Self::I>;
}
struct SafeFormat<I>{
iterable: I,
separator: &'static str,
}
impl<I: IntoIterator<Item = E> + Copy, E: fmt::Display> fmt::Display for SafeFormat<I> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.iterable.into_iter().format(self.separator).fmt(f)
}
}
impl<I: IntoIterator<Item = E> + Copy, E: fmt::Display> IterSafeFormatExt for I {
type I = I;
fn safe_format(&self, separator: &'static str) -> SafeFormat<I> {
SafeFormat { iterable: *self, separator }
}
}
The common case would be to call safe_format on a shared reference to a container:
fn main() {
let mut v = Vec::new();
v.push("foo");
let formatter = (&v).safe_format(", ");
println!(
"{}{}",
formatter, formatter,
);
}
Edit: I'd like to have some way to accept an arbitrary callback that generates the appropriate iterator on-demand, but I can't figure out how to make the types work out for that.