use std::borrow::Cow;
use http::uri::{InvalidUri, InvalidUriParts};
use ohno::{ErrorLabel, Labeled};
const LABEL_URI_INVALID: ErrorLabel = ErrorLabel::from_static("uri_invalid");
const LABEL_URI_HTTP_ERROR: ErrorLabel = ErrorLabel::from_static("uri_http_error");
#[ohno::error]
#[from(http::Error(label: LABEL_URI_HTTP_ERROR))]
#[from(InvalidUri(label: LABEL_URI_INVALID))]
#[from(InvalidUriParts(label: LABEL_URI_INVALID))]
pub struct UriError {
label: ErrorLabel,
}
impl UriError {
pub(crate) fn invalid_uri(message: impl Into<Cow<'static, str>>) -> Self {
Self::caused_by(LABEL_URI_INVALID, message.into())
}
}
impl Labeled for UriError {
fn label(&self) -> &ErrorLabel {
&self.label
}
}
#[cfg(test)]
mod tests {
use std::error::Error;
use ohno::{ErrorLabel, Labeled};
use super::UriError;
#[test]
fn test_error_display() {
let error = UriError::caused_by(ErrorLabel::from_static("test"), "Test validation error");
let display = error.to_string();
assert!(display.starts_with("Test validation error"), "Unexpected message: {display}");
}
#[test]
fn test_source() {
let error = UriError::caused_by(ErrorLabel::from_static("test"), "Test validation error");
assert!(error.source().is_none());
}
#[test]
fn test_from_invalid_uri() {
let invalid_uri = "http://[::1:invalid".parse::<http::Uri>().unwrap_err();
let validation_error = UriError::from(invalid_uri);
let display = validation_error.to_string();
assert!(!display.is_empty(), "Error should have a non-empty display");
assert_eq!(validation_error.label(), "uri_invalid");
assert!(validation_error.source().is_some(), "Should have a source error");
}
#[test]
fn test_from_http_error() {
let invalid_uri_result = "http://[::1:bad".parse::<http::Uri>();
assert!(invalid_uri_result.is_err());
let http_error: http::Error = invalid_uri_result.unwrap_err().into();
let validation_error = UriError::from(http_error);
let display = validation_error.to_string();
assert!(!display.is_empty(), "Error should have a non-empty display");
assert!(validation_error.source().is_some(), "Should have a source error");
assert_eq!(validation_error.label(), "uri_http_error");
}
#[test]
fn test_from_invalid_uri_parts() {
let mut parts = http::uri::Parts::default();
parts.scheme = Some(http::uri::Scheme::HTTP);
parts.authority = None;
parts.path_and_query = Some("/path".parse().unwrap());
let uri_result = http::Uri::from_parts(parts);
assert!(uri_result.is_err());
let invalid_uri_parts = uri_result.unwrap_err();
let validation_error = UriError::from(invalid_uri_parts);
let display = validation_error.to_string();
assert!(!display.is_empty(), "Error should have a non-empty display");
assert!(validation_error.source().is_some(), "Should have a source error");
assert_eq!(validation_error.label(), "uri_invalid");
}
}