error-path 0.1.0

Attach stable, structured error paths to Result-based Rust errors with lightweight adapters.
Documentation
use error_path::{ErrorPath, ErrorPathExt, WithErrorPath};

#[derive(Debug)]
struct ServiceError {
    path: ErrorPath,
}

impl WithErrorPath for ServiceError {
    fn with_error_path(mut self, path: &'static str) -> Self {
        self.path.prepend_path(path);
        self
    }
}

impl ErrorPathExt for ServiceError {
    fn error_path(&self) -> Option<ErrorPath> {
        Some(self.path.clone())
    }
}

struct OpaqueError;

impl ErrorPathExt for OpaqueError {}

#[test]
fn parses_default_delimiter_separated_segments() {
    let path = ErrorPath::from_path(".login..api.");

    assert_eq!(path.segments(), &["login", "api"]);
    assert_eq!(path.to_string(), "login.api");
}

#[test]
fn builds_structured_address_for_custom_errors() {
    let mut path = ErrorPath::from_segment("http.0405");
    path.prepend_path("login.api");
    path.prepend("service");

    assert_eq!(path.segments(), &["service", "login", "api", "http.0405"]);
    assert_eq!(path.to_string_with("/"), "service/login/api/http.0405");
}

#[test]
fn pushes_segment_at_end() {
    let mut path = ErrorPath::from_path("service.login");
    path.push("http.0405");

    assert_eq!(path.segments(), &["service", "login", "http.0405"]);
}

#[test]
fn custom_error_exposes_structured_path() {
    let error = ServiceError {
        path: ErrorPath::from_segment("http.0405"),
    }
    .with_error_path("login.api.request_login");

    assert_eq!(
        error.error_path().unwrap().segments(),
        &["login", "api", "request_login", "http.0405"]
    );
}

#[test]
fn path_extension_defaults_to_none() {
    assert_eq!(OpaqueError.error_path(), None);
}