1use std::{
5 collections::{BTreeMap, HashMap},
6 fmt,
7};
8
9use serde::{
10 de::{self, Deserializer, Visitor},
11 ser::{SerializeMap, SerializeSeq, Serializer},
12 Deserialize, Serialize,
13};
14
15lazy_static::lazy_static! {
16 static ref ANY_TABLE: BTreeMap<String, Field> = {
17 let mut map = BTreeMap::new();
18 map.insert("*".to_owned(), Field::Any);
19 map
20 };
21}
22
23#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
24pub struct StandardLibrary {
25 #[serde(rename = "selene")]
26 pub meta: Option<StandardLibraryMeta>,
27 #[serde(flatten)]
28 pub globals: BTreeMap<String, Field>,
29 #[serde(skip)]
30 pub structs: BTreeMap<String, Field>,
31}
32
33#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
34pub struct StandardLibraryMeta {
35 #[serde(default)]
36 pub base: Option<String>,
37 #[serde(default)]
38 pub name: Option<String>,
39 #[serde(default)]
40 pub structs: Option<BTreeMap<String, BTreeMap<String, Field>>>,
41}
42
43#[derive(Clone, Debug, PartialEq, Eq)]
44pub struct FunctionBehavior {
45 pub arguments: Vec<Argument>,
46 pub method: bool,
47}
48
49#[derive(Clone, Debug, PartialEq, Eq)]
50pub enum Field {
51 Any,
52 Complex {
53 function: Option<FunctionBehavior>,
54 table: BTreeMap<String, Field>,
55 },
56 Property {
57 writable: Option<Writable>,
58 },
59 Struct(String),
60 Removed,
61}
62
63impl From<BTreeMap<String, Field>> for Field {
64 fn from(table: BTreeMap<String, Field>) -> Self {
65 Field::Complex {
66 function: None,
67 table,
68 }
69 }
70}
71
72impl From<FunctionBehavior> for Field {
73 fn from(function: FunctionBehavior) -> Self {
74 Field::Complex {
75 function: Some(function),
76 table: BTreeMap::new(),
77 }
78 }
79}
80
81impl<'de> Deserialize<'de> for Field {
82 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
83 let field_raw = FieldSerde::deserialize(deserializer)?;
84
85 if field_raw.any {
86 return Ok(Field::Any);
87 }
88
89 if field_raw.removed {
90 return Ok(Field::Removed);
91 }
92
93 let is_function = field_raw.args.is_some() || field_raw.method;
94
95 if !field_raw.property
96 && !is_function
97 && field_raw.children.is_empty()
98 && field_raw.strukt.is_none()
99 {
100 return Err(de::Error::custom(
101 "can't determine what kind of field this is",
102 ));
103 }
104
105 if field_raw.property && is_function {
106 return Err(de::Error::custom("field is both a property and a function"));
107 }
108
109 if field_raw.property {
110 return Ok(Field::Property {
111 writable: field_raw.writable,
112 });
113 }
114
115 if let Some(name) = field_raw.strukt {
116 return Ok(Field::Struct(name));
117 }
118
119 let function_behavior = if is_function {
120 Some(FunctionBehavior {
121 arguments: field_raw.args.unwrap_or_default(),
122 method: field_raw.method,
123 })
124 } else {
125 None
126 };
127
128 Ok(Field::Complex {
129 function: function_behavior,
130 table: field_raw.children,
131 })
132 }
133}
134
135impl Serialize for Field {
136 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
137 match self {
138 Field::Any => {
139 let mut map = serializer.serialize_map(Some(1))?;
140 map.serialize_entry("any", &true)?;
141 map.end()
142 }
143
144 Field::Complex { function, table } => {
145 let mut map = serializer.serialize_map(None)?;
146
147 if let Some(function) = function {
148 if function.method {
149 map.serialize_entry("method", &true)?;
150 }
151 map.serialize_entry("args", &function.arguments)?;
152 }
153
154 for (key, value) in table.iter() {
155 map.serialize_entry(key, value)?;
156 }
157
158 map.end()
159 }
160
161 Field::Property { writable } => {
162 let mut map = serializer.serialize_map(None)?;
163 map.serialize_entry("property", &true)?;
164 if let Some(writable) = writable {
165 map.serialize_entry("writable", writable)?;
166 }
167 map.end()
168 }
169
170 Field::Struct(name) => {
171 let mut map = serializer.serialize_map(Some(1))?;
172 map.serialize_entry("struct", name)?;
173 map.end()
174 }
175
176 Field::Removed => {
177 let mut map = serializer.serialize_map(Some(1))?;
178 map.serialize_entry("removed", &true)?;
179 map.end()
180 }
181 }
182 }
183}
184
185#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)]
186#[serde(rename_all = "kebab-case")]
187pub enum Writable {
188 NewFields,
190 Overridden,
192 Full,
194}
195
196#[derive(Debug, Deserialize)]
197struct FieldSerde {
198 #[serde(default)]
199 property: bool,
200 #[serde(default)]
201 method: bool,
202 #[serde(default)]
203 removed: bool,
204 #[serde(default)]
205 writable: Option<Writable>,
206 #[serde(default)]
207 args: Option<Vec<Argument>>,
208 #[serde(default)]
209 #[serde(rename = "struct")]
210 strukt: Option<String>,
211 #[serde(default)]
212 any: bool,
213 #[serde(flatten)]
214 children: BTreeMap<String, Field>,
215}
216
217#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
218pub struct Argument {
219 #[serde(default)]
220 #[serde(skip_serializing_if = "Required::required_no_message")]
221 pub required: Required,
222 #[serde(rename = "type")]
223 pub argument_type: ArgumentType,
224}
225
226#[derive(Clone, Debug, PartialEq, Eq)]
227pub enum ArgumentType {
228 Any,
229 Bool,
230 Constant(Vec<String>),
231 Display(String),
232 Function,
233 Nil,
234 Number,
235 String,
236 Table,
237 Vararg,
238}
239
240impl Serialize for ArgumentType {
241 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
242 match self {
243 &ArgumentType::Any
244 | &ArgumentType::Bool
245 | &ArgumentType::Function
246 | &ArgumentType::Nil
247 | &ArgumentType::Number
248 | &ArgumentType::String
249 | &ArgumentType::Table
250 | &ArgumentType::Vararg => serializer.serialize_str(&self.to_string()),
251
252 ArgumentType::Constant(constants) => {
253 let mut seq = serializer.serialize_seq(Some(constants.len()))?;
254 for constant in constants {
255 seq.serialize_element(constant)?;
256 }
257 seq.end()
258 }
259
260 ArgumentType::Display(display) => {
261 let mut map = serializer.serialize_map(Some(1))?;
262 map.serialize_entry("display", display)?;
263 map.end()
264 }
265 }
266 }
267}
268
269impl<'de> Deserialize<'de> for ArgumentType {
270 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
271 deserializer.deserialize_any(ArgumentTypeVisitor)
272 }
273}
274
275struct ArgumentTypeVisitor;
276
277impl<'de> Visitor<'de> for ArgumentTypeVisitor {
278 type Value = ArgumentType;
279
280 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
281 formatter.write_str("an argument type or an array of constant strings")
282 }
283
284 fn visit_map<A: de::MapAccess<'de>>(self, mut access: A) -> Result<Self::Value, A::Error> {
285 let mut map: HashMap<String, String> = HashMap::new();
286
287 while let Some((key, value)) = access.next_entry()? {
288 map.insert(key, value);
289 }
290
291 if let Some(display) = map.remove("display") {
292 Ok(ArgumentType::Display(display))
293 } else {
294 Err(de::Error::custom(
295 "map value must have a `display` property",
296 ))
297 }
298 }
299
300 fn visit_seq<A: de::SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
301 let mut constants = Vec::new();
302
303 while let Some(value) = seq.next_element()? {
304 constants.push(value);
305 }
306
307 Ok(ArgumentType::Constant(constants))
308 }
309
310 fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
311 match value {
312 "any" => Ok(ArgumentType::Any),
313 "bool" => Ok(ArgumentType::Bool),
314 "function" => Ok(ArgumentType::Function),
315 "nil" => Ok(ArgumentType::Nil),
316 "number" => Ok(ArgumentType::Number),
317 "string" => Ok(ArgumentType::String),
318 "table" => Ok(ArgumentType::Table),
319 "..." => Ok(ArgumentType::Vararg),
320 other => Err(de::Error::custom(format!("unknown type {other}"))),
321 }
322 }
323}
324
325impl fmt::Display for ArgumentType {
326 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
327 match self {
328 ArgumentType::Any => write!(formatter, "any"),
329 ArgumentType::Bool => write!(formatter, "bool"),
330 ArgumentType::Constant(options) => write!(
331 formatter,
332 "{}",
333 options
335 .iter()
336 .map(|string| format!("\"{string}\""))
337 .collect::<Vec<_>>()
338 .join(", ")
339 ),
340 ArgumentType::Display(display) => write!(formatter, "{display}"),
341 ArgumentType::Function => write!(formatter, "function"),
342 ArgumentType::Nil => write!(formatter, "nil"),
343 ArgumentType::Number => write!(formatter, "number"),
344 ArgumentType::String => write!(formatter, "string"),
345 ArgumentType::Table => write!(formatter, "table"),
346 ArgumentType::Vararg => write!(formatter, "..."),
347 }
348 }
349}
350
351#[derive(Clone, Debug, PartialEq, Eq)]
352pub enum Required {
353 NotRequired,
354 Required(Option<String>),
355}
356
357impl Required {
358 fn required_no_message(&self) -> bool {
359 self == &Required::Required(None)
360 }
361}
362
363impl Default for Required {
364 fn default() -> Self {
365 Required::Required(None)
366 }
367}
368
369impl<'de> Deserialize<'de> for Required {
370 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
371 deserializer.deserialize_any(RequiredVisitor)
372 }
373}
374
375impl Serialize for Required {
376 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
377 match self {
378 Required::NotRequired => serializer.serialize_bool(false),
379 Required::Required(None) => serializer.serialize_bool(true),
380 Required::Required(Some(message)) => serializer.serialize_str(message),
381 }
382 }
383}
384
385struct RequiredVisitor;
386
387impl Visitor<'_> for RequiredVisitor {
388 type Value = Required;
389
390 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
391 formatter.write_str("a boolean or a string message (when required)")
392 }
393
394 fn visit_bool<E: de::Error>(self, value: bool) -> Result<Self::Value, E> {
395 if value {
396 Ok(Required::Required(None))
397 } else {
398 Ok(Required::NotRequired)
399 }
400 }
401
402 fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
403 Ok(Required::Required(Some(value.to_owned())))
404 }
405}