bubbles/runtime/provider.rs
1//! [`LineProvider`] trait for localisation / text substitution.
2
3/// Supplies localised (or otherwise substituted) text for a line.
4///
5/// When a line carries a `#line:<id>` tag, the runner queries the provider with that id.
6/// If the provider returns `Some(text)`, that replaces the original line text in the event.
7/// If it returns `None`, the original source text is used as-is.
8pub trait LineProvider: Send + Sync + 'static {
9 /// Returns localised text for `line_id`, or `None` to use the source text.
10 fn get(&self, line_id: &str) -> Option<String>;
11}
12
13/// A no-op provider that always returns `None` (source text is used unchanged).
14#[derive(Debug, Clone, Default)]
15pub struct PassthroughProvider;
16
17impl LineProvider for PassthroughProvider {
18 fn get(&self, _line_id: &str) -> Option<String> {
19 None
20 }
21}
22
23/// A simple in-memory provider backed by a [`std::collections::HashMap`].
24#[derive(Debug, Clone, Default)]
25pub struct HashMapProvider {
26 map: std::collections::HashMap<String, String>,
27}
28
29impl HashMapProvider {
30 /// Creates an empty provider.
31 #[must_use]
32 pub fn new() -> Self {
33 Self::default()
34 }
35
36 /// Inserts a localised string for the given id.
37 pub fn insert(&mut self, id: impl Into<String>, text: impl Into<String>) {
38 self.map.insert(id.into(), text.into());
39 }
40}
41
42impl LineProvider for HashMapProvider {
43 fn get(&self, line_id: &str) -> Option<String> {
44 self.map.get(line_id).cloned()
45 }
46}