error-location 0.1.0

A lightweight utility for capturing and displaying error locations in Rust
Documentation
//! # error-location
//!
//! A lightweight utility for capturing and displaying error locations in Rust.
//!
//! This crate provides a simple wrapper around `std::panic::Location` to make it easier
//! to track where errors originate in your code. It's particularly useful when building
//! custom error types with crates like `thiserror`.
//!
//! ## Usage
//!
//! ```rust, ignore
//! use error_location::ErrorLocation;
//! use std::panic::Location;
//!
//! #[track_caller]
//! fn might_fail() -> Result<(), String> {
//!     let location = ErrorLocation::from(Location::caller());
//!     Err(format!("Something went wrong at {}", location))
//! }
//!
//! fn main() {
//!     match might_fail() {
//!         Ok(_) => println!("Success!"),
//!         Err(e) => eprintln!("Error: {}", e),
//!     }
//! }
//! ```
//!
//! ## Example with `thiserror`
//!
//! ```rust, ignore
//! use error_location::ErrorLocation;
//! use std::panic::Location;
//! use thiserror::Error;
//!
//! #[derive(Error, Debug)]
//! pub enum MyError {
//!     #[error("Database error at {location}: {message}")]
//!     Database {
//!         message: String,
//!         location: ErrorLocation,
//!     },
//! }
//!
//! #[track_caller]
//! fn query_database() -> Result<(), MyError> {
//!     Err(MyError::Database {
//!         message: "Connection failed".to_string(),
//!         location: ErrorLocation::from(Location::caller()),
//!     })
//! }
//! ```

#![deny(missing_docs)]
#![deny(unsafe_code)]
#![warn(clippy::all)]
#![cfg_attr(docsrs, feature(doc_cfg))]

use std::fmt::{Display, Formatter, Result as FormatResult};
use std::panic::Location as PanicLocation;

/// A lightweight wrapper around `std::panic::Location` for tracking error origins.
///
/// This struct captures the file, line, and column information of where an error
/// was created. It's designed to be used with the `#[track_caller]` attribute.
///
/// # Examples
///
/// ```rust, ignore
/// use error_location::ErrorLocation;
/// use std::panic::Location;
///
/// #[track_caller]
/// fn create_error() -> ErrorLocation {
///     ErrorLocation::from(Location::caller())
/// }
///
/// let location = create_error();
/// println!("Error occurred at: {}", location);
/// ```
#[derive(Debug, Clone, Copy)]
pub struct ErrorLocation {
    /// The file path where the error occurred
    pub file: &'static str,
    /// The line number where the error occurred
    pub line: u32,
    /// The column number where the error occurred
    pub column: u32,
}

impl ErrorLocation {
    /// Creates an `ErrorLocation` from a `std::panic::Location`.
    ///
    /// This method is designed to be used with `Location::caller()` in functions
    /// marked with `#[track_caller]`.
    ///
    /// # Examples
    ///
    /// ```rust, ignore
    /// use error_location::ErrorLocation;
    /// use std::panic::Location;
    ///
    /// #[track_caller]
    /// fn get_location() -> ErrorLocation {
    ///     ErrorLocation::from(Location::caller())
    /// }
    /// ```
    pub const fn from(location: &'static PanicLocation<'static>) -> Self {
        Self {
            file: location.file(),
            line: location.line(),
            column: location.column(),
        }
    }
}

impl Display for ErrorLocation {
    fn fmt(&self, formatter: &mut Formatter<'_>) -> FormatResult {
        write!(formatter, "[{}:{}:{}]", self.file, self.line, self.column)
    }
}