1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
//! # The Lua Userscript API
//!
//! One of the core features of sscan is its incredible flexibility
//! thanks to the integration of a Lua 5.4 virtual machine and the
//! userscript environment. Through this environment, scripts can
//! customize, configure, and control almost everything about sscan.
//! Furthermore, userscripts can define custom scan engines that
//! extend sscan beyond its baked-in capabilities.
//!
//! ## Module Structure
//!
//! The root of this module defines the traits necessary to expose
//! an API to the userscript environment, as well as the traits
//! necessary to register help topics with the userscript help system.
//!
//! The submodules of this module contain implementations of these
//! traits for each userscript API, along with both the Rust and Lua
//! documentation for those APIs.
//!
//! ## Developing Custom Userscript APIs
//!
//! To learn how to add custom APIs to the userscript environment, see
//! the [`ApiObject`] trait.
//!
use ;
/// # A userscript API object.
///
/// Any type implementing this trait is eligible to be registered with
/// [`LuaVM`] as a userscript API. A userscript API consists of one or more
/// data fields, functions, or methods, with which a userscript can
/// utilize to interact with a component of sscan.
///
/// Every API object must implement the [`LuaUserData`] trait, and must
/// be [`Send`] and [`'static`].
///
/// # Example
///
/// ```
/// # use sscan::userscript_api::{ApiObject, include::*};
/// // Let's define a userscript API.
/// struct XkcdApi;
///
/// // We define our methods and fields here.
/// impl LuaUserData for XkcdApi {
/// fn add_methods<M: LuaUserDataMethods<Self>>(methods: &mut M) {
/// methods.add_method("get_random_number", |_, _this: &XkcdApi, ()| {
/// Ok(4)
/// });
/// }
///
/// fn add_fields<F: LuaUserDataFields<Self>>(fields: &mut F) {
/// fields.add_field_method_get("source", |_, _this: &XkcdApi| {
/// Ok("https://xkcd.com/221/")
/// });
/// }
/// }
///
/// // Finally, add the required metadata for an API object.
/// impl ApiObject for XkcdApi {
/// fn name(&self) -> &'static str {
/// "xkcd"
/// }
/// }
/// ```
///
/// Once we register our API, we can call it from Lua:
///
/// ```lua
/// random_number = xkcd:get_random_number()
/// assert(random_number == 4)
/// assert(xkcd.source == "https://xkcd.com/221/")
/// ```
///
/// [`LuaVM`]: crate::actors::lua_vm::LuaVM
/// [`'static`]: https://doc.rust-lang.org/std/keyword.static.html