Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose format_into and format_into_io for DelayedFormat #1653

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions bench/benches/chrono.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,33 @@ fn bench_format_with_items(c: &mut Criterion) {
});
}

fn benches_delayed_format(c: &mut Criterion) {
let mut group = c.benchmark_group("delayed_format");
let dt = Local::now();
group.bench_function(BenchmarkId::new("with_display", dt), |b| {
b.iter_batched(
|| dt.format("%Y-%m-%dT%H:%M:%S%.f%:z"),
|df| black_box(df).to_string(),
criterion::BatchSize::SmallInput,
)
});
group.bench_function(BenchmarkId::new("with_string_buffer", dt), |b| {
b.iter_batched(
|| (dt.format("%Y-%m-%dT%H:%M:%S%.f%:z"), String::with_capacity(256)),
|(df, string)| black_box(df).format_into(&mut black_box(string)),
criterion::BatchSize::SmallInput,
)
});
group.bench_function(BenchmarkId::new("with_vec_buffer", dt), |b| {
b.iter_batched(
|| (dt.format("%Y-%m-%dT%H:%M:%S%.f%:z"), String::with_capacity(256)),
|(df, string)| black_box(df).format_into(&mut black_box(string)),
criterion::BatchSize::SmallInput,
)
});
group.finish();
}

fn bench_format_manual(c: &mut Criterion) {
let dt = Local::now();
c.bench_function("bench_format_manual", |b| {
Expand Down Expand Up @@ -237,6 +264,7 @@ criterion_group!(
bench_format,
bench_format_with_items,
bench_format_manual,
benches_delayed_format,
bench_naivedate_add_signed,
bench_datetime_with,
);
Expand Down
64 changes: 61 additions & 3 deletions src/format/formatting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,30 @@ impl<'a, I: Iterator<Item = B> + Clone, B: Borrow<Item<'a>>> DelayedFormat<I> {
DelayedFormat { date, time, off: Some(name_and_diff), items, locale }
}

fn format(&self, w: &mut impl Write) -> fmt::Result {
/// Formats `DelayedFormat` into an `std::io::Write` instance.
/// # Errors
/// This function returns an error if formatting into the `std::io::Write` instance fails.
#[cfg(feature = "std")]
pub fn format_into_io(self, w: &mut impl std::io::Write) -> fmt::Result {
// wrapper to allow reuse of the existing string based
// writers
struct IoWriter<W: std::io::Write> {
writer: W,
}
impl<W: std::io::Write> fmt::Write for IoWriter<W> {
#[inline]
fn write_str(&mut self, s: &str) -> fmt::Result {
self.writer.write_all(s.as_bytes()).map_err(|_| fmt::Error)
}
}
let mut writer = IoWriter { writer: w };
self.format_into(&mut writer)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really interested in taking this. Callers can construct their own adapter if that is important to them.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

made it into an example instead.


/// Formats `DelayedFormat` into a `core::fmt::Write` instance.
/// # Errors
/// This function returns an error if formatting into the `core::fmt::Write` instance fails.
pub fn format_into(&self, w: &mut impl Write) -> fmt::Result {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest we call this write_to().

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

for item in self.items.clone() {
match *item.borrow() {
Item::Literal(s) | Item::Space(s) => w.write_str(s),
Expand Down Expand Up @@ -321,7 +344,7 @@ impl<'a, I: Iterator<Item = B> + Clone, B: Borrow<Item<'a>>> DelayedFormat<I> {
impl<'a, I: Iterator<Item = B> + Clone, B: Borrow<Item<'a>>> Display for DelayedFormat<I> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut result = String::new();
self.format(&mut result)?;
self.format_into(&mut result)?;
f.pad(&result)
}
}
Expand Down Expand Up @@ -353,7 +376,7 @@ where

/// Formats single formatting item
#[cfg(feature = "alloc")]
#[deprecated(since = "0.4.32", note = "Use DelayedFormat::fmt instead")]
#[deprecated(since = "0.4.32", note = "Use DelayedFormat::fmt or DelayedFormat::format instead")]
pub fn format_item(
w: &mut fmt::Formatter,
date: Option<&NaiveDate>,
Expand Down Expand Up @@ -611,6 +634,41 @@ mod tests {
#[cfg(feature = "alloc")]
use crate::{NaiveDate, NaiveTime, TimeZone, Timelike, Utc};

#[cfg(all(feature = "std", feature = "alloc"))]
#[test]
fn test_delayed_format_into_io_matches_format_into() {
let dt = crate::DateTime::from_timestamp(1643723400, 123456789).unwrap();
let df = dt.format("%Y-%m-%d %H:%M:%S%.9f");

let mut dt_str = String::new();
let mut dt_vec_str = Vec::new();

df.format_into(&mut dt_str).unwrap();
df.format_into_io(&mut dt_vec_str).unwrap();

assert_eq!(dt_str, String::from_utf8(dt_vec_str).unwrap());
assert_eq!(dt_str, "2022-02-01 13:50:00.123456789");
}

#[cfg(all(feature = "std", feature = "unstable-locales", feature = "alloc"))]
#[test]
fn test_with_locale_delayed_format_into_io_matches_format_into() {
use crate::format::locales::Locale;
use crate::DateTime;

let dt = DateTime::from_timestamp(1643723400, 123456789).unwrap();
let df = dt.format_localized("%A, %B %d, %Y", Locale::ja_JP);

let mut dt_str = String::new();
let mut dt_vec_str = Vec::new();

df.format_into(&mut dt_str).unwrap();
df.format_into_io(&mut dt_vec_str).unwrap();

assert_eq!(dt_str, String::from_utf8(dt_vec_str).unwrap());
assert_eq!(dt_str, "火曜日, 2月 01, 2022");
}

#[test]
#[cfg(feature = "alloc")]
fn test_date_format() {
Expand Down
Loading