1use async_trait::async_trait;
2use std::fmt::Display;
3
4use crate::{
5 Message, Notification, Request, Response, message::Direction,
6 processed_message::ProcessedMessage,
7};
8
9#[derive(Debug)]
10pub enum HookError {
11 ProcessingFailed(String),
12}
13
14impl Display for HookError {
15 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16 match self {
17 HookError::ProcessingFailed(msg) => write!(f, "Hook processing failed: {}", msg),
18 }
19 }
20}
21
22impl std::error::Error for HookError {}
23
24#[derive(Debug)]
25pub struct HookOutput {
26 pub message: Message,
27 pub generated_messages: Vec<(Direction, Message)>,
28}
29
30impl HookOutput {
31 pub fn new(message: Message) -> Self {
32 Self {
33 message: message,
34 generated_messages: Vec::new(),
35 }
36 }
37
38 pub fn with_message(mut self, direction: Direction, message: Message) -> Self {
39 self.generated_messages.push((direction, message));
40 self
41 }
42
43 pub fn with_messages(mut self, messages: Vec<(Direction, Message)>) -> Self {
44 self.generated_messages.extend(messages);
45 self
46 }
47
48 pub fn as_processed(self) -> ProcessedMessage {
49 ProcessedMessage::WithMessages {
50 message: self.message,
51 generated_messages: self.generated_messages,
52 }
53 }
54}
55
56pub type HookResult = Result<HookOutput, HookError>;
57
58#[async_trait]
59pub trait Hook: Send + Sync {
60 async fn on_request(&self, request: Request) -> HookResult {
61 Ok(HookOutput::new(Message::Request(request)))
62 }
63
64 async fn on_response(&self, response: Response) -> HookResult {
65 Ok(HookOutput::new(Message::Response(response)))
66 }
67
68 async fn on_notification(&self, notification: Notification) -> HookResult {
69 Ok(HookOutput::new(Message::Notification(notification)))
70 }
71}