Skip to content

Commit cc5ae85

Browse files
bors[bot]Ten0
andauthored
Merge #608
608: Make Format/FormatWith use Cell r=jswrenn a=Ten0 Resolves #607 Co-authored-by: Thomas BESSOU <[email protected]>
2 parents e2447dd + dce7378 commit cc5ae85

File tree

1 file changed

+75
-20
lines changed

1 file changed

+75
-20
lines changed

src/format.rs

+75-20
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
1+
use std::cell::Cell;
12
use std::fmt;
2-
use std::cell::RefCell;
33

44
/// Format all iterator elements lazily, separated by `sep`.
55
///
66
/// The format value can only be formatted once, after that the iterator is
77
/// exhausted.
88
///
99
/// See [`.format_with()`](crate::Itertools::format_with) for more information.
10-
#[derive(Clone)]
1110
pub struct FormatWith<'a, I, F> {
1211
sep: &'a str,
1312
/// FormatWith uses interior mutability because Display::fmt takes &self.
14-
inner: RefCell<Option<(I, F)>>,
13+
inner: Cell<Option<(I, F)>>,
1514
}
1615

1716
/// Format all iterator elements lazily, separated by `sep`.
@@ -21,38 +20,40 @@ pub struct FormatWith<'a, I, F> {
2120
///
2221
/// See [`.format()`](crate::Itertools::format)
2322
/// for more information.
24-
#[derive(Clone)]
2523
pub struct Format<'a, I> {
2624
sep: &'a str,
2725
/// Format uses interior mutability because Display::fmt takes &self.
28-
inner: RefCell<Option<I>>,
26+
inner: Cell<Option<I>>,
2927
}
3028

3129
pub fn new_format<I, F>(iter: I, separator: &str, f: F) -> FormatWith<'_, I, F>
32-
where I: Iterator,
33-
F: FnMut(I::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result
30+
where
31+
I: Iterator,
32+
F: FnMut(I::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result,
3433
{
3534
FormatWith {
3635
sep: separator,
37-
inner: RefCell::new(Some((iter, f))),
36+
inner: Cell::new(Some((iter, f))),
3837
}
3938
}
4039

4140
pub fn new_format_default<I>(iter: I, separator: &str) -> Format<'_, I>
42-
where I: Iterator,
41+
where
42+
I: Iterator,
4343
{
4444
Format {
4545
sep: separator,
46-
inner: RefCell::new(Some(iter)),
46+
inner: Cell::new(Some(iter)),
4747
}
4848
}
4949

5050
impl<'a, I, F> fmt::Display for FormatWith<'a, I, F>
51-
where I: Iterator,
52-
F: FnMut(I::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result
51+
where
52+
I: Iterator,
53+
F: FnMut(I::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result,
5354
{
5455
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
55-
let (mut iter, mut format) = match self.inner.borrow_mut().take() {
56+
let (mut iter, mut format) = match self.inner.take() {
5657
Some(t) => t,
5758
None => panic!("FormatWith: was already formatted once"),
5859
};
@@ -71,12 +72,15 @@ impl<'a, I, F> fmt::Display for FormatWith<'a, I, F>
7172
}
7273

7374
impl<'a, I> Format<'a, I>
74-
where I: Iterator,
75+
where
76+
I: Iterator,
7577
{
76-
fn format<F>(&self, f: &mut fmt::Formatter, mut cb: F) -> fmt::Result
77-
where F: FnMut(&I::Item, &mut fmt::Formatter) -> fmt::Result,
78-
{
79-
let mut iter = match self.inner.borrow_mut().take() {
78+
fn format(
79+
&self,
80+
f: &mut fmt::Formatter,
81+
cb: fn(&I::Item, &mut fmt::Formatter) -> fmt::Result,
82+
) -> fmt::Result {
83+
let mut iter = match self.inner.take() {
8084
Some(t) => t,
8185
None => panic!("Format: was already formatted once"),
8286
};
@@ -109,5 +113,56 @@ macro_rules! impl_format {
109113
}
110114
}
111115

112-
impl_format!{Display Debug
113-
UpperExp LowerExp UpperHex LowerHex Octal Binary Pointer}
116+
impl_format! {Display Debug UpperExp LowerExp UpperHex LowerHex Octal Binary Pointer}
117+
118+
impl<'a, I, F> Clone for FormatWith<'a, I, F>
119+
where
120+
(I, F): Clone,
121+
{
122+
fn clone(&self) -> Self {
123+
struct PutBackOnDrop<'r, 'a, I, F> {
124+
into: &'r FormatWith<'a, I, F>,
125+
inner: Option<(I, F)>,
126+
}
127+
// This ensures we preserve the state of the original `FormatWith` if `Clone` panics
128+
impl<'r, 'a, I, F> Drop for PutBackOnDrop<'r, 'a, I, F> {
129+
fn drop(&mut self) {
130+
self.into.inner.set(self.inner.take())
131+
}
132+
}
133+
let pbod = PutBackOnDrop {
134+
inner: self.inner.take(),
135+
into: self,
136+
};
137+
Self {
138+
inner: Cell::new(pbod.inner.clone()),
139+
sep: self.sep,
140+
}
141+
}
142+
}
143+
144+
impl<'a, I> Clone for Format<'a, I>
145+
where
146+
I: Clone,
147+
{
148+
fn clone(&self) -> Self {
149+
struct PutBackOnDrop<'r, 'a, I> {
150+
into: &'r Format<'a, I>,
151+
inner: Option<I>,
152+
}
153+
// This ensures we preserve the state of the original `FormatWith` if `Clone` panics
154+
impl<'r, 'a, I> Drop for PutBackOnDrop<'r, 'a, I> {
155+
fn drop(&mut self) {
156+
self.into.inner.set(self.inner.take())
157+
}
158+
}
159+
let pbod = PutBackOnDrop {
160+
inner: self.inner.take(),
161+
into: self,
162+
};
163+
Self {
164+
inner: Cell::new(pbod.inner.clone()),
165+
sep: self.sep,
166+
}
167+
}
168+
}

0 commit comments

Comments
 (0)