use std::any::Any;
use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct EventType(String);
impl EventType {
#[must_use]
pub fn new(name: impl Into<String>) -> Self {
Self(name.into())
}
#[must_use]
pub fn as_str(&self) -> &str {
&self.0
}
}
impl fmt::Display for EventType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.0)
}
}
pub trait Event: Any + Send + Sync + 'static {
fn event_type(&self) -> EventType;
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HookError {
message: String,
fatal: bool,
}
impl HookError {
#[must_use]
pub fn new(message: impl Into<String>) -> Self {
Self {
message: message.into(),
fatal: false,
}
}
#[must_use]
pub fn fatal(message: impl Into<String>) -> Self {
Self {
message: message.into(),
fatal: true,
}
}
#[must_use]
pub const fn is_fatal(&self) -> bool {
self.fatal
}
#[must_use]
pub fn message(&self) -> &str {
&self.message
}
}
impl fmt::Display for HookError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.message)
}
}
impl std::error::Error for HookError {}
pub type HookResult = Result<(), HookError>;
#[cfg(test)]
mod tests {
use super::{Event, EventType, HookError, HookResult};
struct Ping {
count: u32,
}
impl Event for Ping {
fn event_type(&self) -> EventType {
EventType::new("ping")
}
}
#[test]
fn event_type_equality() {
assert_eq!(EventType::new("ping"), EventType::new("ping"));
assert_ne!(EventType::new("ping"), EventType::new("pong"));
}
#[test]
fn event_type_is_static_metadata() {
let ping = Ping { count: 42 };
assert_eq!(ping.event_type(), EventType::new("ping"));
assert_eq!(ping.count, 42);
}
#[test]
fn hook_result_success() {
let result: HookResult = Ok(());
assert!(result.is_ok());
}
#[test]
fn hook_error_fatal_flag() {
let err = HookError::fatal("budget exceeded");
assert!(err.is_fatal());
assert_eq!(err.message(), "budget exceeded");
}
}