1use core::processors::{PluginBridge, ScopedRegistry, WorldInfoRegistry};
2use std::{collections::{HashMap, HashSet}, fmt::Debug};
3
4use log::{debug, error, trace};
5use parser::{evaluate_nodes, parse_activation_condition, parse_entry_content, AstNode};
6
7pub mod core;
8pub mod errors;
9pub mod id;
10mod parser;
11mod tests;
12
13pub use errors::{ParserError, WorldInfoError};
14
15pub enum ContextNode {
16 TextChunk(String),
17 InsertionPoint(String),
18}
19
20pub struct Context(Vec<ContextNode>);
21
22impl Context {
23 pub fn new() -> Self {
24 Self(Vec::new())
25 }
26
27 pub fn push(&mut self, node: ContextNode) {
28 self.0.push(node);
29 }
30
31 pub fn text(&self) -> String {
32 let mut result = String::new();
33 for node in &self.0 {
34 if let ContextNode::TextChunk(text) = node {
35 result.push_str(text);
36 }
37 }
38 result
39 }
40}
41
42pub struct WorldInfoSettings {
43 pub permitted_processors: Vec<String>,
45 pub recursion_limit: u32,
46 pub id_length: usize,
47 pub seperate_context_nodes: bool
48}
49
50impl Default for WorldInfoSettings {
51 fn default() -> Self {
52 Self {
53 permitted_processors: vec!["*".to_string()],
54 recursion_limit: 10,
55 id_length: 6,
56 seperate_context_nodes: true
57 }
58 }
59}
60
61pub struct WorldInfo<P: PluginBridge + 'static> {
62 name: String,
63 entries: Vec<WorldInfoEntry>,
64 processor_registry: Box<WorldInfoRegistry<P>>,
65 error_stack: Vec<WorldInfoError>,
66 id_generator: id::IdGenerator,
67 settings: WorldInfoSettings,
68
69 trigger_stack: HashSet<String>,
71 evaluated_entries: HashMap<String, String>
72}
73
74impl<P: PluginBridge> WorldInfo<P>{
75 pub fn evaluate(&mut self, context: Context) -> Result<String, &Vec<WorldInfoError>> {
76 self.reset();
77
78 self.parse_entries();
80
81 if self.error_stack.len() > 0 {
82 return Err(&self.error_stack);
83 }
84
85 let mut failed = self.error_stack.len() > 0;
86 let activated_entries = self.filter_activated_entries(&context.text());
87
88 for entry in self.entries.iter_mut().filter(|e| activated_entries.contains(&e.id())) {
89 debug!("-- Evaluating entry {} --", entry.id());
90 let scopes = &entry.scopes.clone();
91 let id = entry.id();
92 let mut scoped_registry = self.processor_registry.scoped_registry(scopes, id.clone());
93
94
95 match entry.evaluate(&mut scoped_registry) {
96 Ok(content) => {
97 if !self.evaluated_entries.contains_key(&id) {
98 self.evaluated_entries.insert(id, content);
99 }
100 },
101 Err(e) => {
102 failed = true;
103 self.error_stack.push(e);
104 },
105 }
106 }
107
108 if failed {
109 Err(&self.error_stack)
110 } else {
111 self.trigger_stack = self.processor_registry.activation_stack();
112 self.evaluate_activation_stack(&mut 0);
113 Ok(self.format_output(context))
114 }
115 }
116
117 fn format_output(&self, context: Context) -> String {
118 let mut result = String::new();
119 for chunk in context.0 {
120 match chunk {
121 ContextNode::TextChunk(text) => result.push_str(&text),
122 ContextNode::InsertionPoint(id) => {
123 for entry in self.entries_from_insertion(id).iter().map(|e| self.evaluated_entries.get(&e.id()).unwrap()) {
124 if self.settings.seperate_context_nodes {
125 result.push_str("\n");
126 }
127 result.push_str(&entry);
128 }
129 }
130 }
131 }
132 result
133 }
134
135 fn entries_from_insertion(&self, insertion_id: String) -> Vec<&WorldInfoEntry> {
136 let mut result = self.entries
137 .iter()
138 .filter(|e| self.evaluated_entries.contains_key(&e.id()))
139 .filter(|e| e.insertion_point == Some(insertion_id.clone()))
140 .into_iter()
141 .collect::<Vec<_>>();
142
143 result.sort_by(|a, b| a.order.cmp(&b.order));
144
145 result
146 }
147
148 fn evaluate_activation_stack(&mut self, depth: &mut u32) {
149 debug!("Evaluating activation stack (depth: {})", depth);
150 let mut failed = false;
151 let mut activated = self.filter_activated_entries(&self.get_evaluated_context());
152 activated.retain(|id| !self.trigger_stack.contains(id) && !self.evaluated_entries.contains_key(id));
153
154 let mut recurse_stack: HashSet<String> = self.trigger_stack.clone();
155 recurse_stack.extend(activated);
156
157 if recurse_stack.len() == 0 {
158 return;
159 }
160
161 trace!("Recursively evaluating {} entries", recurse_stack.len());
162
163 for entry in self.entries.iter_mut().filter(|e| recurse_stack.contains(&e.id()))
164 {
165 let scopes = &entry.scopes.clone();
166 let id = entry.id();
167 let mut scoped_registry = self.processor_registry.scoped_registry(scopes, id.clone());
168
169 if failed {
170 break;
171 }
172
173 match entry.evaluate(&mut scoped_registry) {
174 Ok(content) => {
175 trace!("Evaluated entry {} (depth: {}) -> {}", id, depth, content);
176 if !self.evaluated_entries.contains_key(&id) {
177 self.evaluated_entries.insert(id, content);
178 }
179 },
180 Err(e) => {
181 failed = true;
182 error!("Failed to evaluate entry {} (depth: {}): {}", id, depth, e);
183 self.error_stack.push(e);
184 },
185 }
186 }
187
188 self.trigger_stack = self.processor_registry.activation_stack();
189
190 if failed {
191 return;
192 }
193 *depth += 1;
194
195 if *depth < self.settings.recursion_limit && self.trigger_stack.len() > 0 {
196 self.evaluate_activation_stack(depth);
197 }
198 }
199
200 fn parse_entries(&mut self) {
201 debug!("-- Parsing entries --");
202 for entry in &mut self.entries {
203 trace!("-- Parsing entry {} --", entry.id());
204 match entry.parse::<P>() {
205 Ok(_) => (),
206 Err(e) => {
207 self.error_stack.push(e);
208 break;
209 },
210 }
211 }
212 }
213
214 fn filter_activated_entries(&mut self, context: &String) -> Vec<String> {
215 let mut activated_entries: Vec<String> = Vec::new();
216 for entry in &mut self.entries {
217 let scopes = &entry.scopes.clone();
218 let mut scoped_registry = self.processor_registry.scoped_registry(scopes, entry.id());
219
220 match entry.determine_activation_status(&mut scoped_registry, context) {
221 Ok(active) => {
222 if active {
223 activated_entries.push(entry.id());
224 }
225 },
226 Err(e) => self.error_stack.push(e),
227 }
228 }
229 activated_entries
230 }
231
232 fn get_evaluated_context(&self) -> String {
233 let mut result = String::new();
234 for entry in &self.entries {
235 if self.evaluated_entries.contains_key(&entry.id()) {
236 result.push_str(&(self.evaluated_entries[&entry.id()].clone() + "\n"));
237 }
238 }
239 result
240 }
241
242 fn reset(&mut self) {
243 self.error_stack.clear();
244 self.trigger_stack.clear();
245 self.evaluated_entries.clear();
246 }
247}
248
249pub trait WorldInfoFactory<P: PluginBridge> {
250 fn new(registry: Box<WorldInfoRegistry<P>>) -> Self;
252 fn set_name(&mut self, name: &str) -> &mut Self;
254 fn new_entry(&mut self, name: &str, order: u32) -> &mut WorldInfoEntry;
256 fn insert_entry(&mut self, entry: WorldInfoEntry) -> &mut Self;
258 fn set_permitted_processors(&mut self, processors: Vec<String>) -> &mut Self;
260 fn build(&self) -> &Self;
262
263 fn insert_entries(&mut self, entries: Vec<WorldInfoEntry>) -> &mut Self {
265 for entry in entries {
266 self.insert_entry(entry);
267 }
268 self
269 }
270}
271
272impl<P: PluginBridge> WorldInfoFactory<P> for WorldInfo<P> {
273 fn new(registry: Box<WorldInfoRegistry<P>>) -> Self {
274 WorldInfo {
275 name: String::new(),
276 entries: Vec::new(),
277 settings: Default::default(),
278 processor_registry: registry,
279 error_stack: Vec::new(),
280 id_generator: id::IdGenerator::new(6),
281 trigger_stack: HashSet::new(),
282 evaluated_entries: HashMap::new()
283 }
284 }
285 fn set_name(&mut self, name: &str) -> &mut Self {
286 self.name = name.to_string();
287 self
288 }
289 fn insert_entry(&mut self, entry: WorldInfoEntry) -> &mut Self {
290 self.entries.push(entry);
291 self
292 }
293 fn set_permitted_processors(&mut self, processors: Vec<String>) -> &mut Self {
294 self.settings.permitted_processors = processors;
295 self
296 }
297 fn build(&self) -> &WorldInfo::<P> {
298 self
299 }
300
301 fn new_entry(&mut self, name: &str, order: u32) -> &mut WorldInfoEntry {
302 let id = self.id_generator.generate_unique(&self.entries.iter().map(|e| e.id()).collect());
303 let entry = WorldInfoEntry::create(name, id.clone(), order);
304 self.insert_entry(entry);
305
306 self.entries.last_mut().unwrap()
307 }
308}
309
310pub struct WorldInfoEntry {
311 name: String,
312 id: String,
313 order: u32,
314 scopes: Vec<String>,
315 activation_conditions: Vec<String>,
316 text: String,
317 enabled: bool,
318 constant: bool,
319 insertion_point: Option<String>,
320
321 raw_nodes: Vec<AstNode>,
323 nodes: Vec<Box<dyn WorldInfoNode>>,
324 content_updated: bool
325}
326
327impl WorldInfoEntry {
328 pub fn new(name: String, id: String, order: u32) -> Self {
329 Self
330 {
331 name,
332 id: id.clone(),
333 order,
334 nodes: Vec::new(),
335 text: String::new(),
336 enabled: true,
337 constant: false,
338 insertion_point: None,
339 scopes: vec!["global".to_string(), id],
340 activation_conditions: Vec::new(),
341 content_updated: true,
342 raw_nodes: Vec::new()
343 }
344 }
345
346 pub fn name(&self) -> String {
347 self.name.clone()
348 }
349
350 pub fn id(&self) -> String {
351 self.id.clone()
352 }
353
354 pub fn order(&self) -> u32 {
355 self.order
356 }
357}
358
359pub trait EntryFactory {
360 fn create(name: &str, id: String, order: u32) -> WorldInfoEntry;
361 fn set_text(&mut self, text: &str) -> &mut WorldInfoEntry;
362 fn set_conditions(&mut self, conditions: Vec<String>) -> &mut WorldInfoEntry;
363 fn parse<P: PluginBridge>(&mut self) -> Result<&mut WorldInfoEntry, WorldInfoError>;
364 fn evaluate<P: PluginBridge>(&mut self, registry: &mut ScopedRegistry<P>) -> Result<String, WorldInfoError>;
365 fn determine_activation_status<P: PluginBridge>(&mut self, registry: &mut ScopedRegistry<P>, context: &String) -> Result<bool, WorldInfoError>;
366 fn set_enabled(&mut self, enabled: bool) -> &mut WorldInfoEntry;
367 fn set_constant(&mut self, constant: bool) -> &mut WorldInfoEntry;
368 fn set_insertion_point(&mut self, insertion_point: String) -> &mut WorldInfoEntry;
369}
370
371impl EntryFactory for WorldInfoEntry {
372 fn create(name: &str, id: String, order: u32) -> WorldInfoEntry {
373 WorldInfoEntry::new(name.to_string(), id, order)
374 }
375 fn parse<P: PluginBridge>(&mut self) -> Result<&mut WorldInfoEntry, WorldInfoError> {
376 log::debug!("Parsing node: {:?}", self.text);
377 if self.content_updated {
379 match parse_entry_content::<P>(&self.text) {
380 Ok(ast_nodes) => self.raw_nodes = ast_nodes,
381 Err(e) => return Err(WorldInfoError::ParserError(e)),
382 }
383 }
384
385 self.content_updated = false;
386
387 Ok(self)
388 }
389
390 fn set_text(&mut self, text: &str) -> &mut WorldInfoEntry {
391 self.text = text.to_string();
392 self.content_updated = true;
393 self
394 }
395
396 fn evaluate<P: PluginBridge>(&mut self, registry: &mut ScopedRegistry<P>) -> Result<String, WorldInfoError> {
397 match evaluate_nodes(&self.raw_nodes, registry, &self.id, None) {
398 Ok(eval_nodes) => self.nodes = eval_nodes,
399 Err(e) => return Err(WorldInfoError::ParserError(e)),
400 };
401
402 let mut result = String::new();
403 for node in &self.nodes {
404 result.push_str(&node.content()?);
405 }
406 Ok(result)
407 }
408
409 fn determine_activation_status<P: PluginBridge>(&mut self, registry: &mut ScopedRegistry<P>, context: &String) -> Result<bool, WorldInfoError> {
410 trace!("Activation conditions: {:?}, constant: {}", self.activation_conditions, self.constant);
411 match (self.enabled, self.constant, self.activation_conditions.len() > 0) {
412 (true, true, false) => return Ok(true), (true, false, false) => return Ok(false), (false, ..) => return Ok(false), _ => (),
416 }
417
418 let mut results: Vec<bool> = Vec::new();
419 for condition in &self.activation_conditions {
420 if parse_activation_condition(condition, &context, registry, &self.id)
421 .map_err(|e| WorldInfoError::ParserError(e))?
422 {
423 results.push(true);
424 }
425 else {
426 results.push(false);
427 }
428 }
429
430 Ok(results.iter().all(|b| *b) && self.enabled)
431 }
432
433 fn set_conditions(&mut self, conditions: Vec<String>) -> &mut WorldInfoEntry {
434 self.activation_conditions = conditions;
435 self
436 }
437
438 fn set_enabled(&mut self, enabled: bool) -> &mut WorldInfoEntry {
439 self.enabled = enabled;
440 self
441 }
442
443 fn set_constant(&mut self, constant: bool) -> &mut WorldInfoEntry {
444 self.constant = constant;
445 self
446 }
447
448 fn set_insertion_point(&mut self, insertion_point: String) -> &mut WorldInfoEntry {
449 self.insertion_point = Some(insertion_point);
450 self
451 }
452}
453
454pub trait WorldInfoNode: Debug {
455 fn content(&self) -> Result<String, crate::WorldInfoError>;
456 fn name(&self) -> String;
457 fn cloned(&self) -> Box<dyn WorldInfoNode + '_>;
458}
459
460pub trait WorldInfoProcessor: WorldInfoNode {
461 fn process(&self) -> Result<String, crate::WorldInfoError>;
462}