Report

Struct Report 

Source
pub struct Report<'a> { /* private fields */ }
Expand description

A diagnostic report builder.

The lifetime 'a indicates that all string references passed to the report must live at least as long as the report itself. This enables zero-copy string passing to the underlying C library.

§Source Management

Sources are managed through a Cache and assigned IDs based on registration order: first source is 0, second is 1, etc. The cache is then passed to rendering methods.

§Example

use musubi::{Report, Cache, Level};

let cache = Cache::new()
    .with_source(("let x = 42;", "main.rs"))   // src_id = 0
    .with_source(("fn foo() {}", "lib.rs"));   // src_id = 1

let mut report = Report::new()
    .with_title(Level::Error, "Error")
    .with_label((0..3, 0)) // label in source 0
    .with_message("here")
    .with_label((3..6, 1)) // label in source 1
    .with_message("and here");

report.render_to_stdout(&cache)?;

§Lifetime Safety

Source strings must outlive the report. This will not compile:

use musubi::{Report, Level};

fn bad() -> String {
    let mut report = Report::new();
    {
        let code = String::from("let x = 42;");
        report.with_source((code.as_str(), "test.rs"));
    }  // code dropped here, but report still holds reference
    report.render_to_string(0, 0)
}

Implementations§

Source§

impl<'a> Report<'a>

Source

pub fn new() -> Self

Create a new report.

Source

pub fn with_config(self, config: Config<'a>) -> Self

Configure the report.

Source

pub fn reset(self) -> Self

Reset the report for reuse.

Clears all labels, messages, and configuration, allowing the same Report instance to be used for rendering a different diagnostic.

§Example
let mut report = Report::new()
    .with_title(Level::Error, "First error");
// ... render ...
report.render_to_string("")?;

let mut report = report.reset()
    .with_title(Level::Warning, "Second warning");
// ... render again ...
report.render_to_string("")?;
Source

pub fn with_title<L: Into<TitleLevel<'a>>>( self, level: L, message: &'a str, ) -> Self

Set the title and level.

Accepts either a standard level or a custom level name:

  • with_title(Level::Error, "message") - standard level
  • with_title("Note", "message") - custom level name
§Example
Report::new()
    .with_title(Level::Error, "Something went wrong")
    // Or with custom level:
    .with_title("Note", "Something to note")
    // ...
Source

pub fn with_code(self, code: &'a str) -> Self

Set the error code for this diagnostic.

The error code is typically displayed in brackets before the title, like [E0001] or [W123].

§Example
Report::new()
    .with_title(Level::Error, "Type mismatch")
    .with_code("E0308")  // Displayed as [E0308]
    // ...
Source

pub fn with_location(self, pos: usize, src_id: impl Into<mu_Id>) -> Self

Set the primary location for this diagnostic.

This location is displayed in the diagnostic header, showing where the error occurred.

§Parameters
  • pos: Byte or character position in the source (depending on IndexType)
  • src_id: Source ID (0 for first source, 1 for second, etc.)
§Example
Report::new()
    .with_title(Level::Error, "Syntax error")
    .with_location(42, 0)  // Position 42 in source 0
    // ...
Source

pub fn with_label<L: Into<LabelSpan>>(self, span: L) -> Self

Add a label at the given byte range.

The src_id is the source registration order (0 for first source, 1 for second, etc.).

§Example
Report::new()
    .with_title(Level::Error, "Error")
    .with_label((0..3, 0))  // label in source 0
    .with_message("here")
    // ...
Source

pub fn with_message(self, msg: &'a str) -> Self

Set the message for the last added label.

The message is displayed next to the label’s marker/arrow, providing explanation or context for the highlighted code.

§Example
Report::new()
    .with_label(0..3)
    .with_message("expected identifier here")  // ← message for this label
    .with_label(10..15)
    .with_message("found number instead")      // ← message for next label
    // ...
Source

pub fn with_color<C: IntoColor>(self, color: C) -> Self

Set the color for the last added label.

This method accepts anything that implements IntoColor, including:

  • &dyn Color - Custom color trait objects
  • &GenColor - Pre-generated colors from ColorGenerator
§Examples

Using a custom color:

struct MyColor;
impl Color for MyColor {
    fn color(&self, w: &mut dyn Write, kind: ColorKind) -> std::io::Result<()> {
        write!(w, "\x1b[31m") // Red
    }
}

let color = MyColor;
Report::new()
    // ...
    .with_label(0..4)
    .with_color(&color)
    // ...

Using a color generator:

let mut cg = ColorGenerator::new();

let report = Report::new()
    // ...
    .with_label(0..4)
    .with_color(&cg.next_color())
    // ...;
Source

pub fn with_order(self, order: i32) -> Self

Set the display order for the last added label.

Labels with lower order values are displayed first (closer to the code). Labels with the same order are displayed in the order they were added.

Default: 0

§Example
Report::new()
    // ...
    .with_label(0..4)
        .with_message("second")
        .with_order(1)   // Display this label later
    .with_title(Level::Error, "Error")
        .with_label(0..4)
        .with_message("first")
        .with_order(-1)  // Display this label first
    // ...
Source

pub fn with_priority(self, priority: i32) -> Self

Set the priority for the last added label.

Priority controls how overlapping labels are rendered when multiple labels cover the same source location. Labels with higher priority will be drawn on top, potentially obscuring lower-priority labels.

Higher values = higher priority = drawn on top.

Default: 0

§Example
Report::new()
    // ...
    .with_label(0..10)
        .with_message("low priority")
        .with_priority(0)   // May be obscured by overlapping labels
    .with_label(5..15)
        .with_message("high priority")
        .with_priority(10)  // Will be drawn on top
    // ...
Source

pub fn with_help(self, msg: &'a str) -> Self

Add a help message to the diagnostic.

Help messages appear at the end of the diagnostic, providing suggestions or additional context.

Multiple help messages can be added and will be displayed in order.

§Example
Report::new()
    .with_title(Level::Error, "Type error")
    .with_label(0..4)
        .with_message("expected String")
    .with_help("try converting with .to_string()")
    // ...
Source

pub fn with_note(self, msg: &'a str) -> Self

Add a note message to the diagnostic.

Notes appear at the end of the diagnostic, providing additional information or context.

Multiple notes can be added and will be displayed in order.

§Example
Report::new()
    // ...
    .with_title(Level::Warning, "Unused variable")
    .with_label(0..4)
        .with_message("never used")
    .with_note("consider prefixing with an underscore: `_code`")
    // ...
Source

pub fn render_to_string(&mut self, cache: impl Into<RawCache>) -> Result<String>

Render the report to a String.

This is a convenience method that captures the rendered output into a String instead of writing to stdout or a file.

§Parameters
  • cache: Source cache containing the code to display. Can be:
    • &Cache - A persistent cache with multiple sources
    • &str - A single source string (borrowed)
    • (&str, &str) - Source content and filename
    • (&str, &str, i32) - Source content, filename, and line offset for adjusting displayed line numbers
    • Custom types implementing Source trait
§Example
let output = Report::new()
    .with_title(Level::Error, "Syntax error")
    .with_label(0..3)
    .with_message("unexpected token")
    .render_to_string(("let x", "main.rs"))?;
println!("{}", output);
Source

pub fn render_to_stdout(&mut self, cache: impl Into<RawCache>) -> Result<()>

Render the report directly to stdout.

This is the most efficient way to display diagnostics, writing directly to the terminal without intermediate buffering.

§Parameters
  • cache: Source cache or source content. Can be &Cache, &str, (&str, &str), (&str, &str, i32), or custom Source implementations. The third element (if present) is a line offset for adjusting displayed line numbers.
§Example
Report::new()
    .with_title(Level::Error, "Error message")
    .with_label(0..5)
    .render_to_stdout(("let x = 42;", "main.rs"))?;
Source

pub fn render_to_writer<'b, W: Write>( &'b mut self, writer: &'b mut W, cache: impl Into<RawCache>, ) -> Result<()>

Render the report to any type implementing Write.

This allows rendering to files, buffers, or any custom writer.

§Parameters
  • writer: Mutable reference to any type implementing std::io::Write
  • cache: Source cache or source content. Can be &Cache, &str, (&str, &str), (&str, &str, i32), or custom Source implementations. The third element (if present) is a line offset for adjusting displayed line numbers.
§Example
let mut buffer = Vec::new();
Report::new()
    .with_title(Level::Warning, "Deprecated")
    .with_label(0..3)
    .render_to_writer(&mut buffer, "let x = 1;")?;
assert!(!buffer.is_empty());

Trait Implementations§

Source§

impl Default for Report<'_>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl Drop for Report<'_>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

§

impl<'a> Freeze for Report<'a>

§

impl<'a> !RefUnwindSafe for Report<'a>

§

impl<'a> !Send for Report<'a>

§

impl<'a> !Sync for Report<'a>

§

impl<'a> Unpin for Report<'a>

§

impl<'a> !UnwindSafe for Report<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.