Skip to main content

log_io/
format.rs

1//! Output formats.
2//!
3//! A [`Format`] turns a [`crate::Record`] into bytes on a writer. Three
4//! formats ship in the crate and are gated by feature flags. Custom
5//! formats can be supplied as a closure or by implementing the trait.
6//!
7//! All formatters write directly to the supplied writer without
8//! intermediate allocation.
9
10use core::fmt;
11
12use crate::record::Record;
13
14/// A record-to-bytes serializer.
15///
16/// Implementors should write exactly one logical "line" (or one
17/// logical document) per call. The included sinks add no extra
18/// separators between records; formatters that produce line-oriented
19/// output are expected to emit their own trailing newline.
20pub trait Format: Send + Sync {
21    /// Write the record to `writer` using a [`core::fmt::Write`] sink.
22    ///
23    /// `core::fmt::Write` is used (instead of `std::io::Write`) so that
24    /// formatters compile under `no_std` and can be used to format
25    /// into a `String` or fixed-size buffer.
26    ///
27    /// # Errors
28    ///
29    /// Returns [`core::fmt::Error`] if the underlying writer rejects a
30    /// write.
31    fn write_record<W: fmt::Write + ?Sized>(
32        &self,
33        record: &Record<'_>,
34        writer: &mut W,
35    ) -> fmt::Result;
36}
37
38/// Helper adapter that lets `&dyn Format` be used as `Format`.
39impl<T: Format + ?Sized> Format for &T {
40    fn write_record<W: fmt::Write + ?Sized>(
41        &self,
42        record: &Record<'_>,
43        writer: &mut W,
44    ) -> fmt::Result {
45        (**self).write_record(record, writer)
46    }
47}
48
49#[cfg(feature = "std")]
50impl<T: Format + ?Sized> Format for std::sync::Arc<T> {
51    fn write_record<W: fmt::Write + ?Sized>(
52        &self,
53        record: &Record<'_>,
54        writer: &mut W,
55    ) -> fmt::Result {
56        (**self).write_record(record, writer)
57    }
58}
59
60#[cfg(feature = "std")]
61impl<T: Format + ?Sized> Format for Box<T> {
62    fn write_record<W: fmt::Write + ?Sized>(
63        &self,
64        record: &Record<'_>,
65        writer: &mut W,
66    ) -> fmt::Result {
67        (**self).write_record(record, writer)
68    }
69}
70
71#[cfg(any(feature = "json", feature = "human"))]
72pub(crate) mod rfc3339;
73
74#[cfg(feature = "json")]
75mod json;
76#[cfg(feature = "json")]
77pub use self::json::JsonFormat;
78
79#[cfg(feature = "logfmt")]
80mod logfmt;
81#[cfg(feature = "logfmt")]
82pub use self::logfmt::LogfmtFormat;
83
84#[cfg(feature = "human")]
85mod human;
86#[cfg(feature = "human")]
87pub use self::human::HumanFormat;