ayaka_bindings_types/
plugin.rs

1use crate::*;
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4
5/// The bit flags to describe plugin type.
6///
7/// Every plugin should provide a function `plugin_type`,
8/// which returns [`PluginType`].
9///
10/// ```ignore
11/// use ayaka_bindings::*;
12///
13/// #[export]
14/// fn plugin_type() -> PluginType {
15///     PluginType::default()
16/// }
17/// ```
18#[derive(Debug, Default, Clone, Serialize, Deserialize)]
19pub struct PluginType {
20    /// The action plugin.
21    /// This plugin processes the action after they are parsed.
22    pub action: bool,
23    /// The text plugin.
24    /// The custom text commands are dealt with this type of plugin.
25    pub text: Vec<String>,
26    /// The line plugin.
27    /// The custom line types are dealt with this type of plugin.
28    pub line: Vec<String>,
29    /// The game plugin.
30    /// This plugin processes the game properties after it is loaded.
31    pub game: bool,
32}
33
34impl PluginType {
35    /// Creates a [`PluginTypeBuilder`] instance to build a [`PluginType`].
36    pub fn builder() -> PluginTypeBuilder {
37        PluginTypeBuilder {
38            data: Self::default(),
39        }
40    }
41}
42
43/// The builder of [`PluginType`].
44pub struct PluginTypeBuilder {
45    data: PluginType,
46}
47
48impl PluginTypeBuilder {
49    /// An action plugin.
50    pub fn action(mut self) -> Self {
51        self.data.action = true;
52        self
53    }
54
55    /// A text plugin, which provides commands.
56    pub fn text(mut self, cmds: impl IntoIterator<Item = impl Into<String>>) -> Self {
57        self.data.text = cmds.into_iter().map(|s| s.into()).collect();
58        self
59    }
60
61    /// A line plugins, which provides custom line types.
62    pub fn line(mut self, cmds: impl IntoIterator<Item = impl Into<String>>) -> Self {
63        self.data.line = cmds.into_iter().map(|s| s.into()).collect();
64        self
65    }
66
67    /// A game plugin.
68    pub fn game(mut self) -> Self {
69        self.data.game = true;
70        self
71    }
72
73    /// Build a [`PluginType`].
74    pub fn build(self) -> PluginType {
75        self.data
76    }
77}
78
79/// The type of current frontend.
80#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
81pub enum FrontendType {
82    /// The frontend only accepts raw texts.
83    Text,
84    /// The frontend renders HTML.
85    Html,
86    /// The frontend renders LaTeX.
87    Latex,
88}
89
90/// The argument to action plugin.
91///
92/// Every action plugin should implement `process_action`:
93/// ```ignore
94/// use ayaka_bindings::*;
95///
96/// #[export]
97/// fn process_action(mut ctx: ActionProcessContext) -> ActionProcessResult {
98///     // Process the action...
99///     ActionProcessResult { action: ctx.action }
100/// }
101/// ```
102#[derive(Debug, Serialize, Deserialize)]
103pub struct ActionProcessContext {
104    /// The global properties of the game profile.
105    pub game_props: HashMap<String, String>,
106    /// The frontend type.
107    pub frontend: FrontendType,
108    /// The current context.
109    pub ctx: RawContext,
110    /// The current action.
111    pub action: ActionText,
112}
113
114#[derive(Debug, Serialize)]
115#[doc(hidden)]
116pub struct ActionProcessContextRef<'a> {
117    pub game_props: &'a HashMap<String, String>,
118    pub frontend: FrontendType,
119    pub ctx: &'a RawContext,
120    pub action: &'a ActionText,
121}
122
123/// The result of action plugins.
124/// See examples at [`ActionProcessContext`].
125#[derive(Debug, Default, Serialize, Deserialize)]
126pub struct ActionProcessResult {
127    /// The processed action text.
128    pub action: ActionText,
129}
130
131/// The argument to text plugin.
132///
133/// ```ignore
134/// use ayaka_bindings::*;
135///
136/// #[export]
137/// fn plugin_type() -> PluginType {
138///     PluginType::builder().text(&["hello"]).build()
139/// }
140///
141/// #[export]
142/// fn hello(_args: Vec<String>, _ctx: TextProcessContext) -> TextProcessResult {
143///     let mut res = TextProcessResult::default();
144///     res.line.push_back_chars("hello");
145///     res
146/// }
147/// ```
148#[derive(Debug, Serialize, Deserialize)]
149pub struct TextProcessContext {
150    /// The global properties of the game profile.
151    pub game_props: HashMap<String, String>,
152    /// The frontend type.
153    pub frontend: FrontendType,
154}
155
156#[derive(Debug, Serialize)]
157#[doc(hidden)]
158pub struct TextProcessContextRef<'a> {
159    pub game_props: &'a HashMap<String, String>,
160    pub frontend: FrontendType,
161}
162
163/// The result of commands in text plugins.
164/// See examples at [`TextProcessContext`].
165#[derive(Debug, Default, Serialize, Deserialize)]
166pub struct TextProcessResult {
167    /// The lines to append.
168    pub text: ActionText,
169}
170
171/// The argument to game plugin.
172///
173/// Every game plugin should implement `process_game`:
174/// ```ignore
175/// use ayaka_bindings::*;
176///
177/// #[export]
178/// fn process_game(mut ctx: GameProcessContext) -> GameProcessResult {
179///     // Process the game...
180///     GameProcessResult { props: ctx.props }
181/// }
182/// ```
183#[derive(Debug, Serialize, Deserialize)]
184pub struct GameProcessContext {
185    /// The title of the game.
186    pub title: String,
187    /// The author of the game.
188    pub author: String,
189    /// The global properties of the game.
190    pub props: HashMap<String, String>,
191}
192
193#[derive(Debug, Serialize)]
194#[doc(hidden)]
195pub struct GameProcessContextRef<'a> {
196    pub title: &'a str,
197    pub author: &'a str,
198    pub props: &'a HashMap<String, String>,
199}
200
201/// The result of game plugins.
202/// See examples at [`GameProcessContext`].
203#[derive(Debug, Serialize, Deserialize)]
204pub struct GameProcessResult {
205    /// The updated properties.
206    pub props: HashMap<String, String>,
207}
208
209/// The argument to line plugin.
210///
211/// ```ignore
212/// use ayaka_bindings::*;
213///
214/// #[export]
215/// fn plugin_type() -> PluginType {
216///     PluginType::builder().line(&["hello"]).build()
217/// }
218///
219/// #[export]
220/// fn hello(_ctx: LineProcessContext) -> LineProcessResult {
221///     let mut res = LineProcessResult::default();
222///     res.locals.insert("hello".to_string(), RawValue::Str("world".to_string()));
223///     res
224/// }
225/// ```
226#[derive(Debug, Serialize, Deserialize)]
227pub struct LineProcessContext {
228    /// The global properties of the game profile.
229    pub game_props: HashMap<String, String>,
230    /// The frontend type.
231    pub frontend: FrontendType,
232    /// The current context.
233    pub ctx: RawContext,
234    /// The full properties of the custom command.
235    pub props: VarMap,
236}
237
238#[derive(Debug, Serialize)]
239#[doc(hidden)]
240pub struct LineProcessContextRef<'a> {
241    pub game_props: &'a HashMap<String, String>,
242    pub frontend: FrontendType,
243    pub ctx: &'a RawContext,
244    pub props: &'a VarMap,
245}
246
247/// The result of commands in line plugins.
248/// See examples at [`LineProcessContext`].
249#[derive(Debug, Default, Serialize, Deserialize)]
250pub struct LineProcessResult {
251    /// The updated variables.
252    pub locals: VarMap,
253    /// The temp variables.
254    pub vars: VarMap,
255}