1use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
6use std::sync::{Arc, RwLock};
7use lazy_static::lazy_static;
8
9lazy_static! {
11 static ref STRING_POOL: Arc<RwLock<HashMap<String, Arc<String>>>> = Arc::new(RwLock::new(HashMap::new()));
12}
13
14#[derive(Debug, Clone, PartialEq, Eq, Hash)]
16pub struct InternedString(Arc<String>);
17
18impl InternedString {
19 pub fn new<S: Into<String>>(s: S) -> Self {
21 let string = s.into();
22 let mut pool = STRING_POOL.write().unwrap();
23
24 if let Some(interned) = pool.get(&string) {
25 InternedString(Arc::clone(interned))
26 } else {
27 let interned = Arc::new(string.clone());
28 pool.insert(string, Arc::clone(&interned));
29 InternedString(interned)
30 }
31 }
32
33 pub fn as_str(&self) -> &str {
35 &self.0
36 }
37
38 pub fn len(&self) -> usize {
40 self.0.len()
41 }
42
43 pub fn is_empty(&self) -> bool {
45 self.0.is_empty()
46 }
47}
48
49impl From<String> for InternedString {
50 fn from(s: String) -> Self {
51 InternedString::new(s)
52 }
53}
54
55impl From<&str> for InternedString {
56 fn from(s: &str) -> Self {
57 InternedString::new(s)
58 }
59}
60
61impl From<&String> for InternedString {
62 fn from(s: &String) -> Self {
63 InternedString::new(s.clone())
64 }
65}
66
67impl std::fmt::Display for InternedString {
68 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69 write!(f, "{}", self.0)
70 }
71}
72
73impl AsRef<str> for InternedString {
74 fn as_ref(&self) -> &str {
75 self.as_str()
76 }
77}
78
79#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
81pub struct Triple {
82 pub subject: String,
83 pub predicate: String,
84 pub object: String,
85}
86
87#[derive(Debug, Clone, PartialEq, Eq, Hash)]
89pub struct InternedTriple {
90 pub subject: InternedString,
91 pub predicate: InternedString,
92 pub object: InternedString,
93}
94
95impl InternedTriple {
96 pub fn new<S: Into<InternedString>, P: Into<InternedString>, O: Into<InternedString>>(
98 subject: S,
99 predicate: P,
100 object: O,
101 ) -> Self {
102 InternedTriple {
103 subject: subject.into(),
104 predicate: predicate.into(),
105 object: object.into(),
106 }
107 }
108
109 pub fn to_triple(&self) -> Triple {
111 Triple {
112 subject: self.subject.as_str().to_string(),
113 predicate: self.predicate.as_str().to_string(),
114 object: self.object.as_str().to_string(),
115 }
116 }
117
118 pub fn from_triple(triple: &Triple) -> Self {
120 InternedTriple::new(
121 InternedString::from(&triple.subject),
122 InternedString::from(&triple.predicate),
123 InternedString::from(&triple.object),
124 )
125 }
126}
127
128#[derive(Debug, Clone, Serialize, Deserialize)]
130pub struct JsonLdDocument {
131 #[serde(rename = "@context")]
132 pub context: serde_json::Value,
133 #[serde(rename = "@graph", skip_serializing_if = "Option::is_none")]
134 pub graph: Option<Vec<serde_json::Value>>,
135 #[serde(flatten)]
136 pub data: HashMap<String, serde_json::Value>,
137}
138
139#[derive(Debug, Clone, Default)]
141pub struct NamedGraph {
142 pub name: String,
143 pub triples: Vec<Triple>,
144}
145
146#[derive(Debug, Clone, Serialize, Deserialize)]
148#[serde(tag = "type", content = "data")]
149pub enum CyberEvent {
150 NetworkConnection {
151 source_ip: String,
152 dest_ip: String,
153 port: u16,
154 protocol: String,
155 timestamp: i64,
156 },
157 ProcessExecution {
158 process_id: u32,
159 parent_process_id: Option<u32>,
160 command_line: String,
161 user: String,
162 timestamp: i64,
163 },
164 FileAccess {
165 file_path: String,
166 access_type: String,
167 user: String,
168 process_id: u32,
169 timestamp: i64,
170 },
171 UserLogin {
172 user: String,
173 source_ip: String,
174 success: bool,
175 timestamp: i64,
176 },
177}
178
179#[derive(Debug, Clone, Serialize, Deserialize)]
181#[serde(tag = "action_type", content = "parameters")]
182pub enum SecurityAction {
183 IsolateHost { host_ip: String, reason: String },
184 BlockConnection { source_ip: String, dest_ip: String, reason: String },
185 TerminateProcess { process_id: u32, reason: String },
186 RevokePrivileges { user: String, privilege: String, reason: String },
187 Alert { severity: String, message: String, details: serde_json::Value },
188}
189
190#[derive(Debug, Clone, Serialize, Deserialize)]
192pub struct InferenceRule {
193 pub name: String,
194 pub description: String,
195 pub conditions: Vec<Triple>,
196 pub actions: Vec<SecurityAction>,
197}