error-location 0.1.0

A lightweight utility for capturing and displaying error locations in Rust
Documentation
# error-location

[![Crates.io](https://img.shields.io/crates/v/error-location.svg)](https://crates.io/crates/error-location)
[![Documentation](https://docs.rs/error-location/badge.svg)](https://docs.rs/error-location)
[![License](https://img.shields.io/crates/l/error-location.svg)](https://github.com/yourusername/error-location#license)
[![Build Status](https://github.com/yourusername/error-location/workflows/CI/badge.svg)](https://github.com/yourusername/error-location/actions)

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`.

## Features

- **Zero dependencies**: Only uses `std`
- **Lightweight**: Minimal overhead with compile-time tracking
- **Type-safe**: Leverages Rust's `#[track_caller]` attribute
- **Display formatting**: Clean, readable output format `[file:line:column]`

## Installation

Add this to your `Cargo.toml`:

```toml
[dependencies]
error-location = "0.1"
```

## Usage

### Basic Usage

```rust
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),
        // Output: Error: Something went wrong at [src/main.rs:15:5]
    }
}
```

### With `thiserror`

The crate shines when used with `thiserror` for custom error types:

```rust
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,
    },
    
    #[error("API error at {location}: {status}")]
    Api {
        status: u16,
        location: ErrorLocation,
    },
}

#[track_caller]
fn query_database() -> Result<String, MyError> {
    Err(MyError::Database {
        message: "Connection failed".to_string(),
        location: ErrorLocation::from(Location::caller()),
    })
}

#[track_caller]
fn call_api() -> Result<String, MyError> {
    Err(MyError::Api {
        status: 404,
        location: ErrorLocation::from(Location::caller()),
    })
}

fn main() {
    match query_database() {
        Ok(data) => println!("Data: {}", data),
        Err(e) => eprintln!("Error: {}", e),
        // Output: Error: Database error at [src/main.rs:34:5]: Connection failed
    }
}
```

### Creating Helper Functions

You can create helper functions to reduce boilerplate:

```rust
use error_location::ErrorLocation;
use std::panic::Location;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum AppError {
    #[error("Error at {location}: {message}")]
    WithLocation {
        message: String,
        location: ErrorLocation,
    },
}

#[track_caller]
fn err_loc(message: impl Into<String>) -> AppError {
    AppError::WithLocation {
        message: message.into(),
        location: ErrorLocation::from(Location::caller()),
    }
}

#[track_caller]
fn do_work() -> Result<(), AppError> {
    Err(err_loc("Work failed"))
}
```

## How It Works

The `ErrorLocation` struct uses Rust's `#[track_caller]` attribute and `std::panic::Location` to capture the file, line, and column where an error is created. This information is stored at compile time, resulting in zero runtime overhead for location tracking.

When you mark a function with `#[track_caller]` and call `Location::caller()`, Rust automatically provides the caller's location information. The `ErrorLocation` struct wraps this in a convenient, Display-friendly format.

## Output Format

The `Display` implementation formats locations as:
```
[file/path.rs:line:column]
```

For example:
```
[src/database/query.rs:42:10]
```

## Why Use This?

While `std::panic::Location` is available in the standard library, this crate provides:

1. **A dedicated type**: Makes it clear when you're working with error locations
2. **Ergonomic Display**: Pre-formatted output that's consistent across your codebase
3. **Documentation**: Clear examples of usage patterns
4. **Semantic meaning**: `ErrorLocation` conveys intent better than raw `Location`

## Minimum Supported Rust Version (MSRV)

This crate requires Rust 1.70 or later.

## License

Licensed under either of:

- Apache License, Version 2.0 ([LICENSE-APACHE]LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT]LICENSE-MIT or http://opensource.org/licenses/MIT)

at your option.

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.