mycelium_trace/writer.rs
1//! Abstractions for creating [`fmt::Write`] instances.
2//!
3//! [`fmt::Write`]: mycelium_util::fmt::Write
4use crate::color::{Color, SetColor};
5use maitake::sync::{
6 blocking::{Mutex, MutexGuard, RawMutex},
7 spin::Spinlock,
8};
9use mycelium_util::fmt::{self, Debug};
10use tracing_core::Metadata;
11
12/// A type that can create [`fmt::Write`] instances.
13///
14/// This trait is already implemented for function pointers and
15/// immutably-borrowing closures that return an instance of [`fmt::Write`],
16/// Additionally, it is implemented for [`maitake::sync::blocking::Mutex`]
17/// when the type inside the mutex implements [`fmt::Write`] and the `Lock` type
18/// implements [`RawMutex`].
19///
20/// The [`MakeWriter::make_writer_for`] method takes [`Metadata`] describing a
21/// span or event and returns a writer. `MakeWriter`s can optionally provide
22/// implementations of this method with behaviors that differ based on the span
23/// or event being written. For example, events at different [levels] might be
24/// written to different output streams, or data from different [targets] might
25/// be written to separate log files. When the `MakeWriter` has no custom
26/// behavior based on metadata, the default implementation of `make_writer_for`
27/// simply calls `self.make_writer()`, ignoring the metadata. Therefore, when
28/// metadata _is_ available, callers should prefer to call `make_writer_for`,
29/// passing in that metadata, so that the `MakeWriter` implementation can choose
30/// the appropriate behavior.
31///
32/// [`fmt::Write`]: mycelium_util::fmt::Write
33/// [`Event`]: tracing_core::event::Event
34/// [`MakeWriter::make_writer_for`]: MakeWriter::make_writer_for
35/// [`Metadata`]: tracing_core::Metadata
36/// [levels]: tracing_core::Level
37/// [targets]: tracing_core::Metadata::target
38pub trait MakeWriter<'a> {
39 /// The concrete [`fmt::Write`] implementation returned by [`make_writer`].
40 ///
41 /// [`fmt::Write`]: mycelium_util::fmt::Write
42 /// [`make_writer`]: MakeWriter::make_writer
43 type Writer: fmt::Write;
44
45 /// Returns an instance of [`Writer`].
46 ///
47 /// # Implementer notes
48 ///
49 /// A [`Subscriber`] will call this method each time an event is recorded.
50 /// Ensure any state that must be saved across writes is not lost when the
51 /// [`Writer`] instance is dropped. If creating a [`fmt::Write`] instance is
52 /// expensive, be sure to cache it when implementing [`MakeWriter`] to
53 /// improve performance.
54 ///
55 /// [`Writer`]: MakeWriter::Writer
56 /// [`Subscriber`]: crate::Subscriber
57 /// [`fmt::Write`]: mycelium_util::fmt::Write
58 fn make_writer(&'a self) -> Self::Writer;
59
60 fn enabled(&self, meta: &Metadata<'_>) -> bool {
61 let _ = meta;
62 true
63 }
64
65 /// Returns a [`Writer`] for writing data from the span or event described
66 /// by the provided [`Metadata`].
67 ///
68 /// By default, this calls [`self.make_writer()`][make_writer], ignoring
69 /// the provided metadata, but implementations can override this to provide
70 /// metadata-specific behaviors.
71 ///
72 /// This method allows `MakeWriter` implementations to implement different
73 /// behaviors based on the span or event being written. The `MakeWriter`
74 /// type might return different writers based on the provided metadata, or
75 /// might write some values to the writer before or after providing it to
76 /// the caller.
77 ///
78 /// [`Writer`]: MakeWriter::Writer
79 /// [`Metadata`]: tracing_core::Metadata
80 /// [make_writer]: MakeWriter::make_writer
81 /// [`WARN`]: tracing_core::Level::WARN
82 /// [`ERROR`]: tracing_core::Level::ERROR
83 #[inline]
84 fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Option<Self::Writer> {
85 if self.enabled(meta) {
86 return Some(self.make_writer());
87 }
88
89 None
90 }
91
92 fn line_len(&self) -> usize {
93 80
94 }
95}
96
97/// Extension trait adding combinators for working with types implementing
98/// [`MakeWriter`].
99///
100/// This is not intended to be implemented directly for user-defined
101/// [`MakeWriter`]s; instead, it should be imported when the desired methods are
102/// used.
103pub trait MakeWriterExt<'a>: MakeWriter<'a> {
104 /// Wraps `self` and returns a [`MakeWriter`] that will only write output
105 /// for events at or below the provided verbosity [`Level`]. For instance,
106 /// `Level::TRACE` is considered to be _more verbose` than `Level::INFO`.
107 ///
108 /// Events whose level is more verbose than `level` will be ignored, and no
109 /// output will be written.
110 ///
111 /// [`Level`]: tracing_core::Level
112 /// [`fmt::Write`]: mycelium_util::fmt::Write
113 fn with_max_level(self, level: tracing_core::Level) -> WithMaxLevel<Self>
114 where
115 Self: Sized,
116 {
117 WithMaxLevel::new(self, level)
118 }
119
120 /// Wraps `self` and returns a [`MakeWriter`] that will only write output
121 /// for events at or above the provided verbosity [`Level`].
122 ///
123 /// Events whose level is less verbose than `level` will be ignored, and no
124 /// output will be written.
125 ///
126 /// [`Level`]: tracing_core::Level
127 /// [`fmt::Write`]: mycelium_util::fmt::Write
128 fn with_min_level(self, level: tracing_core::Level) -> WithMinLevel<Self>
129 where
130 Self: Sized,
131 {
132 WithMinLevel::new(self, level)
133 }
134
135 /// Wraps `self` with a predicate that takes a span or event's [`Metadata`]
136 /// and returns a `bool`. The returned [`MakeWriter`]'s
137 /// [`MakeWriter::make_writer_for`] method will check the predicate to
138 /// determine if a writer should be produced for a given span or event.
139 ///
140 /// If the predicate returns `false`, the wrapped [`MakeWriter`]'s
141 /// [`make_writer_for`][mwf] will return [`None`].
142 /// Otherwise, it calls the wrapped [`MakeWriter`]'s
143 /// [`make_writer_for`][mwf] method, and returns the produced writer.
144 ///
145 /// This can be used to filter an output based on arbitrary [`Metadata`]
146 /// parameters.
147 ///
148 /// [`Metadata`]: tracing_core::Metadata
149 /// [mwf]: MakeWriter::make_writer_for
150 fn with_filter<F>(self, filter: F) -> WithFilter<Self, F>
151 where
152 Self: Sized,
153 F: Fn(&Metadata<'_>) -> bool,
154 {
155 WithFilter::new(self, filter)
156 }
157
158 /// Combines `self` with another type implementing [`MakeWriter`], returning
159 /// a new [`MakeWriter`] that produces [writers] that write to *both*
160 /// outputs.
161 ///
162 /// If writing to either writer returns an error, the returned writer will
163 /// return that error. However, both writers will still be written to before
164 /// the error is returned, so it is possible for one writer to fail while
165 /// the other is written to successfully.
166 ///
167 /// [writers]: mycelium_util::fmt::Write
168 fn and<B>(self, other: B) -> Tee<Self, B>
169 where
170 Self: Sized,
171 B: MakeWriter<'a> + Sized,
172 {
173 Tee::new(self, other)
174 }
175
176 /// Combines `self` with another type implementing [`MakeWriter`], returning
177 /// a new [`MakeWriter`] that calls `other`'s [`make_writer`] if `self`'s
178 /// `make_writer` returns [`None`].
179 ///
180 /// [`make_writer`]: MakeWriter::make_writer
181 fn or_else<B>(self, other: B) -> OrElse<Self, B>
182 where
183 Self: MakeWriter<'a> + Sized,
184 B: MakeWriter<'a> + Sized,
185 {
186 OrElse::new(self, other)
187 }
188
189 fn with_line_len(self, len: usize) -> WithLineLen<Self>
190 where
191 Self: MakeWriter<'a> + Sized,
192 {
193 WithLineLen::new(self, len)
194 }
195}
196
197/// A type implementing [`fmt::Write`] for a [`MutexGuard`] where the type
198/// inside the [`Mutex`] implements [`fmt::Write`].
199///
200/// This is used by the [`MakeWriter`] implementation for [`Mutex`], because
201/// [`MutexGuard`] itself will not implement [`fmt::Write`] — instead, it
202/// _dereferences_ to a type implementing [`fmt::Write`]. Because [`MakeWriter`]
203/// requires the `Writer` type to implement [`fmt::Write`], it's necessary to add
204/// a newtype that forwards the trait implementation.
205///
206/// [`fmt::Write`]: mycelium_util::fmt::Write
207/// [`MutexGuard`]: maitake::sync::blocking::MutexGuard
208/// [`Mutex`]: maitake::sync::blocking::Mutex
209/// [`MakeWriter`]: trait.MakeWriter.html
210#[derive(Debug)]
211pub struct MutexGuardWriter<'a, W, Lock: RawMutex = Spinlock>(MutexGuard<'a, W, Lock>);
212
213// TODO(eliza): put this back if needed
214/*
215/// A writer that erases the specific [`fmt::Write`] and [`MakeWriter`] types being used.
216///
217/// This is useful in cases where the concrete type of the writer cannot be known
218/// until runtime.
219///
220/// # Examples
221///
222/// A function that returns a [`Collect`] that will write to either stdout or stderr:
223///
224/// ```rust
225/// # use tracing::Collect;
226/// # use tracing_subscriber::fmt::writer::BoxMakeWriter;
227///
228/// fn dynamic_writer(use_stderr: bool) -> impl Collect {
229/// let writer = if use_stderr {
230/// BoxMakeWriter::new(core::io::stderr)
231/// } else {
232/// BoxMakeWriter::new(core::io::stdout)
233/// };
234///
235/// tracing_subscriber::fmt().with_writer(writer).finish()
236/// }
237/// ```
238///
239/// [`Collect`]: tracing::Collect
240/// [`fmt::Write`]: mycelium_util::fmt::Write
241pub struct BoxMakeWriter {
242 inner: Box<dyn for<'a> MakeWriter<'a, Writer = Box<dyn Write + 'a>> + Send + Sync>,
243 name: &'static str,
244}
245 */
246
247/// A [writer] that is one of two types implementing [`fmt::Write`].
248///
249/// This may be used by [`MakeWriter`] implementations that may conditionally
250/// return one of two writers.
251///
252/// [writer]: mycelium_util::fmt::Write
253#[derive(Copy, Clone, Debug, Eq, PartialEq)]
254pub enum EitherWriter<A, B> {
255 /// A writer of type `A`.
256 A(A),
257 /// A writer of type `B`.
258 B(B),
259}
260
261/// A [`MakeWriter`] combinator that only returns an enabled [writer] for spans
262/// and events with metadata at or below a specified verbosity [`Level`].
263///
264/// This is returned by the [`MakeWriterExt::with_max_level] method. See the
265/// method documentation for details.
266///
267/// [writer]: mycelium_util::fmt::Write
268/// [`Level`]: tracing_core::Level
269#[derive(Copy, Clone, Debug, Eq, PartialEq)]
270pub struct WithMaxLevel<M> {
271 make: M,
272 level: tracing_core::Level,
273}
274
275/// A [`MakeWriter`] combinator that only returns an enabled [writer] for spans
276/// and events with metadata at or above a specified verbosity [`Level`].
277///
278/// This is returned by the [`MakeWriterExt::with_min_level] method. See the
279/// method documentation for details.
280///
281/// [writer]: mycelium_util::fmt::Write
282/// [`Level`]: tracing_core::Level
283#[derive(Copy, Clone, Debug, Eq, PartialEq)]
284pub struct WithMinLevel<M> {
285 make: M,
286 level: tracing_core::Level,
287}
288
289/// A [`MakeWriter`] combinator that wraps a [`MakeWriter`] with a predicate for
290/// span and event [`Metadata`], so that the [`MakeWriter::make_writer_for`]
291/// method returns [`Some`] when the predicate returns `true`,
292/// and [`None`] when the predicate returns `false`.
293///
294/// This is returned by the [`MakeWriterExt::with_filter`] method. See the
295/// method documentation for details.
296///
297/// [`Metadata`]: tracing_core::Metadata
298#[derive(Copy, Clone, Debug, Eq, PartialEq)]
299pub struct WithFilter<M, F> {
300 make: M,
301 filter: F,
302}
303
304/// Combines a [`MakeWriter`] that returns an [`Option`] of another
305/// [`MakeWriter`], so that the second [`MakeWriter`] is used when the first
306/// [`MakeWriter`] returns [`None`].
307///
308/// This is returned by the [`MakeWriterExt::or_else] method. See the
309/// method documentation for details.
310#[derive(Copy, Clone, Debug, Eq, PartialEq)]
311pub struct OrElse<A, B> {
312 inner: A,
313 or_else: B,
314}
315
316/// Combines two types implementing [`MakeWriter`] (or [`mycelium_util::fmt::Write`]) to
317/// produce a writer that writes to both [`MakeWriter`]'s returned writers.
318///
319/// This is returned by the [`MakeWriterExt::and`] method. See the method
320/// documentation for details.
321#[derive(Copy, Clone, Debug, Eq, PartialEq)]
322pub struct Tee<A, B> {
323 a: A,
324 b: B,
325}
326
327#[derive(Copy, Clone, Debug, Eq, PartialEq)]
328pub struct WithLineLen<W> {
329 make: W,
330 len: usize,
331}
332
333#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
334pub struct NoWriter(());
335
336pub const fn none() -> NoWriter {
337 NoWriter(())
338}
339
340impl<'a, F, W> MakeWriter<'a> for F
341where
342 F: Fn() -> W,
343 W: fmt::Write,
344{
345 type Writer = W;
346
347 fn make_writer(&'a self) -> Self::Writer {
348 (self)()
349 }
350}
351
352impl<'a, M> MakeWriter<'a> for Option<M>
353where
354 M: MakeWriter<'a>,
355{
356 type Writer = EitherWriter<M::Writer, NoWriter>;
357 #[inline]
358 fn make_writer(&'a self) -> Self::Writer {
359 self.as_ref()
360 .map(MakeWriter::make_writer)
361 .map(EitherWriter::A)
362 .unwrap_or(EitherWriter::B(NoWriter(())))
363 }
364
365 #[inline]
366 fn enabled(&self, meta: &Metadata<'_>) -> bool {
367 self.as_ref()
368 .map(|make| make.enabled(meta))
369 .unwrap_or(false)
370 }
371
372 #[inline]
373 fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Option<Self::Writer> {
374 self.as_ref()
375 .and_then(|make| make.make_writer_for(meta))
376 .map(EitherWriter::A)
377 }
378
379 #[inline]
380 fn line_len(&self) -> usize {
381 self.as_ref().map(MakeWriter::line_len).unwrap_or(80)
382 }
383}
384
385// === impl Mutex/MutexGuardWriter ===
386
387impl<'a, W, Lock> MakeWriter<'a> for Mutex<W, Lock>
388where
389 W: fmt::Write + 'a,
390 Lock: RawMutex + 'a,
391{
392 type Writer = MutexGuardWriter<'a, W, Lock>;
393
394 fn make_writer(&'a self) -> Self::Writer {
395 MutexGuardWriter(self.lock())
396 }
397}
398
399impl<W, Lock> fmt::Write for MutexGuardWriter<'_, W, Lock>
400where
401 W: fmt::Write,
402 Lock: RawMutex,
403{
404 #[inline]
405 fn write_str(&mut self, s: &str) -> fmt::Result {
406 self.0.write_str(s)
407 }
408
409 #[inline]
410 fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> fmt::Result {
411 self.0.write_fmt(fmt)
412 }
413}
414
415// === impl EitherWriter ===
416
417impl<A, B> fmt::Write for EitherWriter<A, B>
418where
419 A: fmt::Write,
420 B: fmt::Write,
421{
422 #[inline]
423 fn write_str(&mut self, s: &str) -> fmt::Result {
424 match self {
425 EitherWriter::A(a) => a.write_str(s),
426 EitherWriter::B(b) => b.write_str(s),
427 }
428 }
429
430 #[inline]
431 fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> fmt::Result {
432 match self {
433 EitherWriter::A(a) => a.write_fmt(fmt),
434 EitherWriter::B(b) => b.write_fmt(fmt),
435 }
436 }
437}
438
439impl<A, B> SetColor for EitherWriter<A, B>
440where
441 A: fmt::Write + SetColor,
442 B: fmt::Write + SetColor,
443{
444 fn set_fg_color(&mut self, color: Color) {
445 match self {
446 EitherWriter::A(a) => a.set_fg_color(color),
447 EitherWriter::B(b) => b.set_fg_color(color),
448 }
449 }
450
451 fn fg_color(&self) -> Color {
452 match self {
453 EitherWriter::A(a) => a.fg_color(),
454 EitherWriter::B(b) => b.fg_color(),
455 }
456 }
457
458 fn set_bold(&mut self, bold: bool) {
459 match self {
460 EitherWriter::A(a) => a.set_bold(bold),
461 EitherWriter::B(b) => b.set_bold(bold),
462 }
463 }
464}
465
466// === impl WithMaxLevel ===
467
468impl<M> WithMaxLevel<M> {
469 /// Wraps the provided [`MakeWriter`] with a maximum [`Level`], so that it
470 /// returns [`None`] for spans and events whose level is
471 /// more verbose than the maximum level.
472 ///
473 /// See [`MakeWriterExt::with_max_level`] for details.
474 ///
475 /// [`Level`]: tracing_core::Level
476 pub fn new(make: M, level: tracing_core::Level) -> Self {
477 Self { make, level }
478 }
479}
480
481impl<'a, M: MakeWriter<'a>> MakeWriter<'a> for WithMaxLevel<M> {
482 type Writer = M::Writer;
483
484 #[inline(always)]
485 fn make_writer(&'a self) -> Self::Writer {
486 self.make.make_writer()
487 }
488
489 #[inline(always)]
490 fn enabled(&self, meta: &Metadata<'_>) -> bool {
491 meta.level() <= &self.level && self.make.enabled(meta)
492 }
493
494 #[inline(always)]
495 fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Option<Self::Writer> {
496 if self.enabled(meta) {
497 return self.make.make_writer_for(meta);
498 }
499
500 None
501 }
502
503 #[inline(always)]
504 fn line_len(&self) -> usize {
505 self.make.line_len()
506 }
507}
508
509// === impl WithMinLevel ===
510
511impl<M> WithMinLevel<M> {
512 /// Wraps the provided [`MakeWriter`] with a minimum [`Level`], so that it
513 /// returns [`None`] for spans and events whose level is
514 /// less verbose than the maximum level.
515 ///
516 /// See [`MakeWriterExt::with_min_level`] for details.
517 ///
518 /// [`Level`]: tracing_core::Level
519 pub fn new(make: M, level: tracing_core::Level) -> Self {
520 Self { make, level }
521 }
522}
523
524impl<'a, M: MakeWriter<'a>> MakeWriter<'a> for WithMinLevel<M> {
525 type Writer = M::Writer;
526
527 #[inline]
528 fn make_writer(&'a self) -> Self::Writer {
529 self.make.make_writer()
530 }
531
532 fn enabled(&self, meta: &Metadata<'_>) -> bool {
533 meta.level() >= &self.level && self.make.enabled(meta)
534 }
535
536 #[inline]
537 fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Option<Self::Writer> {
538 if self.enabled(meta) {
539 return self.make.make_writer_for(meta);
540 }
541
542 None
543 }
544
545 #[inline]
546 fn line_len(&self) -> usize {
547 self.make.line_len()
548 }
549}
550
551// ==== impl WithFilter ===
552
553impl<M, F> WithFilter<M, F> {
554 /// Wraps `make` with the provided `filter`, returning a [`MakeWriter`] that
555 /// will call `make.make_writer_for()` when `filter` returns `true` for a
556 /// span or event's [`Metadata`], and returns [`None`] otherwise.
557 ///
558 /// See [`MakeWriterExt::with_filter`] for details.
559 ///
560 /// [`Metadata`]: tracing_core::Metadata
561 pub fn new(make: M, filter: F) -> Self
562 where
563 F: Fn(&Metadata<'_>) -> bool,
564 {
565 Self { make, filter }
566 }
567}
568
569impl<'a, M, F> MakeWriter<'a> for WithFilter<M, F>
570where
571 M: MakeWriter<'a>,
572 F: Fn(&Metadata<'_>) -> bool,
573{
574 type Writer = M::Writer;
575
576 #[inline]
577 fn make_writer(&'a self) -> Self::Writer {
578 self.make.make_writer()
579 }
580
581 #[inline]
582 fn enabled(&self, meta: &Metadata<'_>) -> bool {
583 (self.filter)(meta) && self.make.enabled(meta)
584 }
585
586 #[inline]
587 fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Option<Self::Writer> {
588 if self.enabled(meta) {
589 return self.make.make_writer_for(meta);
590 }
591
592 None
593 }
594
595 #[inline]
596 fn line_len(&self) -> usize {
597 self.make.line_len()
598 }
599}
600
601// === impl Tee ===
602
603impl<A, B> Tee<A, B> {
604 /// Combines two types implementing [`MakeWriter`], returning
605 /// a new [`MakeWriter`] that produces [writers] that write to *both*
606 /// outputs.
607 ///
608 /// See the documentation for [`MakeWriterExt::and`] for details.
609 ///
610 /// [writers]: fmt::Write
611 pub fn new(a: A, b: B) -> Self {
612 Self { a, b }
613 }
614}
615
616// impl<'a, A, B> MakeWriter<'a> for Tee<A, B>
617// where
618// A: MakeWriter<'a>,
619// B: MakeWriter<'a>,
620// {
621// type Writer = Tee<A::Writer, B::Writer>;
622
623// #[inline]
624// fn make_writer(&'a self) -> Self::Writer {
625// Tee::new(self.a.make_writer(), self.b.make_writer())
626// }
627
628// #[inline]
629// fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer {
630// Tee::new(self.a.make_writer_for(meta), self.b.make_writer_for(meta))
631// }
632// }
633
634// macro_rules! impl_tee {
635// ($self_:ident.$f:ident($($arg:ident),*)) => {
636// {
637// let res_a = $self_.a.$f($($arg),*);
638// let res_b = $self_.b.$f($($arg),*);
639// (res_a?, res_b?)
640// }
641// }
642// }
643
644// impl<A, B> fmt::Write for Tee<A, B>
645// where
646// A: fmt::Write,
647// B: fmt::Write,
648// {
649// #[inline]
650// fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
651// let (a, b) = impl_tee!(self.write(buf));
652// Ok(core::cmp::max(a, b))
653// }
654
655// #[inline]
656// fn flush(&mut self) -> io::Result<()> {
657// impl_tee!(self.flush());
658// Ok(())
659// }
660
661// #[inline]
662// fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
663// impl_tee!(self.write_all(buf));
664// Ok(())
665// }
666
667// #[inline]
668// fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
669// impl_tee!(self.write_fmt(fmt));
670// Ok(())
671// }
672// }
673
674// === impl OrElse ===
675
676impl<A, B> OrElse<A, B> {
677 /// Combines
678 pub fn new<'a>(inner: A, or_else: B) -> Self
679 where
680 A: MakeWriter<'a>,
681 B: MakeWriter<'a>,
682 {
683 Self { inner, or_else }
684 }
685}
686
687impl<'a, A, B> MakeWriter<'a> for OrElse<A, B>
688where
689 A: MakeWriter<'a>,
690 B: MakeWriter<'a>,
691{
692 type Writer = EitherWriter<A::Writer, B::Writer>;
693
694 #[inline]
695 fn make_writer(&'a self) -> Self::Writer {
696 EitherWriter::A(self.inner.make_writer())
697 }
698
699 #[inline]
700 fn enabled(&self, meta: &Metadata<'_>) -> bool {
701 self.inner.enabled(meta) || self.or_else.enabled(meta)
702 }
703
704 fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Option<Self::Writer> {
705 self.inner
706 .make_writer_for(meta)
707 .map(EitherWriter::A)
708 .or_else(|| self.or_else.make_writer_for(meta).map(EitherWriter::B))
709 }
710
711 #[inline]
712 fn line_len(&self) -> usize {
713 core::cmp::min(self.inner.line_len(), self.or_else.line_len())
714 }
715}
716
717// === impl WithLineLen ===
718
719impl<W> WithLineLen<W> {
720 /// Combines
721 pub fn new(make: W, len: usize) -> Self {
722 Self { make, len }
723 }
724}
725
726impl<'a, W> MakeWriter<'a> for WithLineLen<W>
727where
728 W: MakeWriter<'a>,
729{
730 type Writer = W::Writer;
731
732 #[inline]
733 fn make_writer(&'a self) -> Self::Writer {
734 self.make.make_writer()
735 }
736
737 #[inline]
738 fn enabled(&self, meta: &Metadata<'_>) -> bool {
739 self.make.enabled(meta)
740 }
741
742 #[inline]
743 fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Option<Self::Writer> {
744 self.make.make_writer_for(meta)
745 }
746
747 #[inline]
748 fn line_len(&self) -> usize {
749 self.len
750 }
751}
752
753// === impl NoWriter ===
754
755impl fmt::Write for NoWriter {
756 #[inline]
757 fn write_str(&mut self, _: &str) -> fmt::Result {
758 Ok(())
759 }
760
761 #[inline]
762 fn write_fmt(&mut self, _: fmt::Arguments<'_>) -> fmt::Result {
763 Ok(())
764 }
765}
766
767impl<'a> MakeWriter<'a> for NoWriter {
768 type Writer = Self;
769
770 #[inline]
771 fn make_writer(&'a self) -> Self::Writer {
772 Self(())
773 }
774
775 #[inline]
776 fn enabled(&self, _: &Metadata<'_>) -> bool {
777 false
778 }
779
780 #[inline]
781 fn make_writer_for(&'a self, _: &Metadata<'_>) -> Option<Self::Writer> {
782 None
783 }
784}
785
786impl SetColor for NoWriter {
787 fn set_fg_color(&mut self, _: Color) {
788 // nop
789 }
790
791 fn fg_color(&self) -> Color {
792 Color::Default
793 }
794
795 fn set_bold(&mut self, _: bool) {
796 // nop
797 }
798}
799
800// === blanket impls ===
801
802impl<'a, M> MakeWriterExt<'a> for M where M: MakeWriter<'a> {}