diff options
Diffstat (limited to 'third_party/rust/itertools/src/format.rs')
-rw-r--r-- | third_party/rust/itertools/src/format.rs | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/third_party/rust/itertools/src/format.rs b/third_party/rust/itertools/src/format.rs new file mode 100644 index 0000000000..d87cee9503 --- /dev/null +++ b/third_party/rust/itertools/src/format.rs @@ -0,0 +1,113 @@ +use std::fmt; +use std::cell::RefCell; + +/// Format all iterator elements lazily, separated by `sep`. +/// +/// The format value can only be formatted once, after that the iterator is +/// exhausted. +/// +/// See [`.format_with()`](crate::Itertools::format_with) for more information. +#[derive(Clone)] +pub struct FormatWith<'a, I, F> { + sep: &'a str, + /// FormatWith uses interior mutability because Display::fmt takes &self. + inner: RefCell<Option<(I, F)>>, +} + +/// Format all iterator elements lazily, separated by `sep`. +/// +/// The format value can only be formatted once, after that the iterator is +/// exhausted. +/// +/// See [`.format()`](crate::Itertools::format) +/// for more information. +#[derive(Clone)] +pub struct Format<'a, I> { + sep: &'a str, + /// Format uses interior mutability because Display::fmt takes &self. + inner: RefCell<Option<I>>, +} + +pub fn new_format<I, F>(iter: I, separator: &str, f: F) -> FormatWith<'_, I, F> + where I: Iterator, + F: FnMut(I::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result +{ + FormatWith { + sep: separator, + inner: RefCell::new(Some((iter, f))), + } +} + +pub fn new_format_default<I>(iter: I, separator: &str) -> Format<'_, I> + where I: Iterator, +{ + Format { + sep: separator, + inner: RefCell::new(Some(iter)), + } +} + +impl<'a, I, F> fmt::Display for FormatWith<'a, I, F> + where I: Iterator, + F: FnMut(I::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let (mut iter, mut format) = match self.inner.borrow_mut().take() { + Some(t) => t, + None => panic!("FormatWith: was already formatted once"), + }; + + if let Some(fst) = iter.next() { + format(fst, &mut |disp: &dyn fmt::Display| disp.fmt(f))?; + iter.try_for_each(|elt| { + if !self.sep.is_empty() { + f.write_str(self.sep)?; + } + format(elt, &mut |disp: &dyn fmt::Display| disp.fmt(f)) + })?; + } + Ok(()) + } +} + +impl<'a, I> Format<'a, I> + where I: Iterator, +{ + fn format<F>(&self, f: &mut fmt::Formatter, mut cb: F) -> fmt::Result + where F: FnMut(&I::Item, &mut fmt::Formatter) -> fmt::Result, + { + let mut iter = match self.inner.borrow_mut().take() { + Some(t) => t, + None => panic!("Format: was already formatted once"), + }; + + if let Some(fst) = iter.next() { + cb(&fst, f)?; + iter.try_for_each(|elt| { + if !self.sep.is_empty() { + f.write_str(self.sep)?; + } + cb(&elt, f) + })?; + } + Ok(()) + } +} + +macro_rules! impl_format { + ($($fmt_trait:ident)*) => { + $( + impl<'a, I> fmt::$fmt_trait for Format<'a, I> + where I: Iterator, + I::Item: fmt::$fmt_trait, + { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format(f, fmt::$fmt_trait::fmt) + } + } + )* + } +} + +impl_format!{Display Debug + UpperExp LowerExp UpperHex LowerHex Octal Binary Pointer} |