uira_core/protocol/primitives/
event.rs1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
4#[serde(rename_all = "PascalCase")]
5pub enum HookEvent {
6 PreToolUse,
7 PostToolUse,
8 UserPromptSubmit,
9 Stop,
10 PreCompact,
11 PreCheck,
12 PostCheck,
13 PreAi,
14 PostAi,
15 PreFix,
16 PostFix,
17}
18
19impl HookEvent {
20 pub fn as_str(&self) -> &'static str {
21 match self {
22 Self::PreToolUse => "PreToolUse",
23 Self::PostToolUse => "PostToolUse",
24 Self::UserPromptSubmit => "UserPromptSubmit",
25 Self::Stop => "Stop",
26 Self::PreCompact => "PreCompact",
27 Self::PreCheck => "pre-check",
28 Self::PostCheck => "post-check",
29 Self::PreAi => "pre-ai",
30 Self::PostAi => "post-ai",
31 Self::PreFix => "pre-fix",
32 Self::PostFix => "post-fix",
33 }
34 }
35
36 pub fn is_claude_event(&self) -> bool {
37 matches!(
38 self,
39 Self::PreToolUse
40 | Self::PostToolUse
41 | Self::UserPromptSubmit
42 | Self::Stop
43 | Self::PreCompact
44 )
45 }
46
47 pub fn is_uira_event(&self) -> bool {
48 matches!(
49 self,
50 Self::PreCheck
51 | Self::PostCheck
52 | Self::PreAi
53 | Self::PostAi
54 | Self::PreFix
55 | Self::PostFix
56 )
57 }
58}
59
60impl std::fmt::Display for HookEvent {
61 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62 write!(f, "{}", self.as_str())
63 }
64}
65
66impl std::str::FromStr for HookEvent {
67 type Err = HookEventParseError;
68
69 fn from_str(s: &str) -> Result<Self, Self::Err> {
70 match s.to_lowercase().as_str() {
71 "pretooluse" | "pre-tool-use" | "pre_tool_use" => Ok(Self::PreToolUse),
72 "posttooluse" | "post-tool-use" | "post_tool_use" => Ok(Self::PostToolUse),
73 "userpromptsubmit" | "user-prompt-submit" | "user_prompt_submit" => {
74 Ok(Self::UserPromptSubmit)
75 }
76 "stop" => Ok(Self::Stop),
77 "precompact" | "pre-compact" | "pre_compact" => Ok(Self::PreCompact),
78 "precheck" | "pre-check" | "pre_check" => Ok(Self::PreCheck),
79 "postcheck" | "post-check" | "post_check" => Ok(Self::PostCheck),
80 "preai" | "pre-ai" | "pre_ai" => Ok(Self::PreAi),
81 "postai" | "post-ai" | "post_ai" => Ok(Self::PostAi),
82 "prefix" | "pre-fix" | "pre_fix" => Ok(Self::PreFix),
83 "postfix" | "post-fix" | "post_fix" => Ok(Self::PostFix),
84 _ => Err(HookEventParseError(s.to_string())),
85 }
86 }
87}
88
89#[derive(Debug, Clone)]
90pub struct HookEventParseError(pub String);
91
92impl std::fmt::Display for HookEventParseError {
93 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
94 write!(f, "unknown hook event: {}", self.0)
95 }
96}
97
98impl std::error::Error for HookEventParseError {}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103
104 #[test]
105 fn test_event_as_str() {
106 assert_eq!(HookEvent::PreToolUse.as_str(), "PreToolUse");
107 assert_eq!(HookEvent::PreCheck.as_str(), "pre-check");
108 }
109
110 #[test]
111 fn test_event_parse() {
112 assert_eq!(
113 "PreToolUse".parse::<HookEvent>().unwrap(),
114 HookEvent::PreToolUse
115 );
116 assert_eq!(
117 "pre-check".parse::<HookEvent>().unwrap(),
118 HookEvent::PreCheck
119 );
120 assert!("invalid".parse::<HookEvent>().is_err());
121 }
122
123 #[test]
124 fn test_is_claude_event() {
125 assert!(HookEvent::PreToolUse.is_claude_event());
126 assert!(!HookEvent::PreCheck.is_claude_event());
127 }
128}