systemprompt_models/notifications/
kind.rs1use std::fmt;
7use std::str::FromStr;
8
9#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
12pub struct NotificationKind(String);
13
14#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
16#[error("invalid notification kind {value:?}: {reason}")]
17pub struct NotificationKindError {
18 pub value: String,
19 pub reason: &'static str,
20}
21
22impl NotificationKind {
23 pub const MENTIONED: &'static str = "document.comment.mentioned";
24 pub const SHARED: &'static str = "document.shared";
25 pub const STREAM_PUBLISHED: &'static str = "stream.published";
26 pub const ISSUE_REPORTED: &'static str = "issue.reported";
27 pub const ISSUE_STATUS_CHANGED: &'static str = "issue.status_changed";
28
29 pub fn new(value: impl Into<String>) -> Result<Self, NotificationKindError> {
30 let value = value.into();
31 if let Some(reason) = kind_violation(&value) {
32 return Err(NotificationKindError { value, reason });
33 }
34 Ok(Self(value))
35 }
36
37 #[must_use]
38 pub const fn as_str(&self) -> &str {
39 self.0.as_str()
40 }
41}
42
43fn kind_violation(value: &str) -> Option<&'static str> {
44 if value.is_empty() {
45 return Some("must not be empty");
46 }
47 if value.split('.').any(str::is_empty) {
48 return Some("segments must not be empty");
49 }
50 if !value
51 .bytes()
52 .all(|b| b == b'.' || b == b'_' || b.is_ascii_lowercase() || b.is_ascii_digit())
53 {
54 return Some("must contain only lowercase letters, digits, '_' and '.'");
55 }
56 None
57}
58
59impl fmt::Display for NotificationKind {
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 f.write_str(&self.0)
62 }
63}
64
65impl FromStr for NotificationKind {
66 type Err = NotificationKindError;
67
68 fn from_str(s: &str) -> Result<Self, Self::Err> {
69 Self::new(s)
70 }
71}
72
73crate::notifications::string_form::string_serde!(NotificationKind, "NotificationKind");