From d8f7e7330624e90cf5ffd797aa6cef0f4ba8cbc5 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 15 Oct 2025 11:32:14 -0700 Subject: [PATCH] Allow writing to &mut dyn WriteStyle --- codespan-reporting/src/term/config.rs | 2 +- codespan-reporting/src/term/mod.rs | 25 ++++---- codespan-reporting/src/term/renderer.rs | 78 +++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 11 deletions(-) diff --git a/codespan-reporting/src/term/config.rs b/codespan-reporting/src/term/config.rs index 1faf3366..764d93f1 100644 --- a/codespan-reporting/src/term/config.rs +++ b/codespan-reporting/src/term/config.rs @@ -308,7 +308,7 @@ pub mod styles { #[cfg(feature = "termcolor")] impl super::renderer::WriteStyle for T where - T: termcolor::WriteColor, + T: termcolor::WriteColor + ?Sized, { fn set_header( &mut self, diff --git a/codespan-reporting/src/term/mod.rs b/codespan-reporting/src/term/mod.rs index 4c0b5239..ab01954e 100644 --- a/codespan-reporting/src/term/mod.rs +++ b/codespan-reporting/src/term/mod.rs @@ -40,7 +40,7 @@ pub fn emit_to_string<'files, F: Files<'files> + ?Sized>( { let mut buffer = Vec::new(); emit_with_style( - &mut renderer::PlainWriter::new(&mut buffer), + renderer::PlainWriter::new(&mut buffer), config, files, diagnostic, @@ -54,7 +54,7 @@ pub fn emit_to_string<'files, F: Files<'files> + ?Sized>( #[cfg(not(feature = "std"))] { emit_with_style( - &mut renderer::PlainWriter::new(writer), + renderer::PlainWriter::new(writer), config, files, diagnostic, @@ -63,27 +63,32 @@ pub fn emit_to_string<'files, F: Files<'files> + ?Sized>( } #[cfg(feature = "std")] -pub fn emit_to_io_write<'files, F: Files<'files> + ?Sized, W: std::io::Write>( +pub fn emit_to_io_write<'files, F: Files<'files> + ?Sized, W: std::io::Write + ?Sized>( writer: &mut W, config: &Config, files: &'files F, diagnostic: &Diagnostic, ) -> Result<(), super::files::Error> { emit_with_style( - &mut renderer::PlainWriter::new(writer), + renderer::PlainWriter::new(writer), config, files, diagnostic, ) } -pub fn emit_to_write_style<'files, F: Files<'files> + ?Sized, W: WriteStyle>( +pub fn emit_to_write_style<'files, F: Files<'files> + ?Sized, W: WriteStyle + ?Sized>( writer: &mut W, config: &Config, files: &'files F, diagnostic: &Diagnostic, ) -> Result<(), super::files::Error> { - emit_with_style(writer, config, files, diagnostic) + emit_with_style( + renderer::WriteStyleByRef::new(writer), + config, + files, + diagnostic, + ) } #[deprecated( @@ -96,14 +101,14 @@ pub fn emit_to_write_style<'files, F: Files<'files> + ?Sized, W: WriteStyle>( /// * a file was removed from the file database. /// * a file was changed so that it is too small to have an index /// * IO fails -pub fn emit<'files, F: Files<'files> + ?Sized, W: renderer::GeneralWrite>( +pub fn emit<'files, F: Files<'files> + ?Sized, W: renderer::GeneralWrite + ?Sized>( writer: &mut W, config: &Config, files: &'files F, diagnostic: &Diagnostic, ) -> Result<(), super::files::Error> { emit_with_style( - &mut renderer::PlainWriter::new(writer), + renderer::PlainWriter::new(writer), config, files, diagnostic, @@ -111,12 +116,12 @@ pub fn emit<'files, F: Files<'files> + ?Sized, W: renderer::GeneralWrite>( } fn emit_with_style<'files, F: Files<'files> + ?Sized, W: WriteStyle>( - writer: &mut W, + mut writer: W, config: &Config, files: &'files F, diagnostic: &Diagnostic, ) -> Result<(), super::files::Error> { - let mut renderer = Renderer::new(writer, config); + let mut renderer = Renderer::new(&mut writer, config); match config.display_style { DisplayStyle::Rich => RichDiagnostic::new(diagnostic, config).render(files, &mut renderer), DisplayStyle::Medium => ShortDiagnostic::new(diagnostic, true).render(files, &mut renderer), diff --git a/codespan-reporting/src/term/renderer.rs b/codespan-reporting/src/term/renderer.rs index 27089ce0..b4dd9524 100644 --- a/codespan-reporting/src/term/renderer.rs +++ b/codespan-reporting/src/term/renderer.rs @@ -108,6 +108,84 @@ impl WriteStyle for PlainWriter { } } +pub(crate) struct WriteStyleByRef<'a, W: ?Sized> { + w: &'a mut W, +} + +impl<'a, W> WriteStyleByRef<'a, W> +where + W: ?Sized, +{ + pub fn new(writer: &'a mut W) -> Self { + Self { w: writer } + } +} + +#[cfg(feature = "std")] +impl<'a, W> std::io::Write for WriteStyleByRef<'a, W> +where + W: std::io::Write + ?Sized, +{ + fn write(&mut self, buf: &[u8]) -> std::io::Result { + self.w.write(buf) + } + + fn flush(&mut self) -> std::io::Result<()> { + self.w.flush() + } +} + +#[cfg(not(feature = "std"))] +impl<'a, W> core::fmt::Write for WriteStyleByRef<'a, W> +where + W: core::fmt::Write + ?Sized, +{ + fn write_str(&mut self, s: &str) -> core::fmt::Result { + self.w.write_str(s) + } + + fn write_char(&mut self, c: char) -> core::fmt::Result { + self.w.write_char(c) + } + + fn write_fmt(&mut self, args: core::fmt::Arguments<'_>) -> core::fmt::Result { + self.w.write_fmt(args) + } +} + +impl<'a, W> WriteStyle for WriteStyleByRef<'a, W> +where + W: WriteStyle + ?Sized, +{ + fn set_header(&mut self, severity: Severity) -> GeneralWriteResult { + self.w.set_header(severity) + } + + fn set_header_message(&mut self) -> GeneralWriteResult { + self.w.set_header_message() + } + + fn set_line_number(&mut self) -> GeneralWriteResult { + self.w.set_line_number() + } + + fn set_note_bullet(&mut self) -> GeneralWriteResult { + self.w.set_note_bullet() + } + + fn set_source_border(&mut self) -> GeneralWriteResult { + self.w.set_source_border() + } + + fn set_label(&mut self, severity: Severity, label_style: LabelStyle) -> GeneralWriteResult { + self.w.set_label(severity, label_style) + } + + fn reset(&mut self) -> GeneralWriteResult { + self.w.reset() + } +} + /// The 'location focus' of a source code snippet. pub struct Locus { /// The user-facing name of the file.