@thigasdevelopment/luam 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lua/validate.lua CHANGED
@@ -1,239 +1,284 @@
1
- local MAX_DEPTH = 16
2
- local MAX_ENTRIES = 4096
3
- local MAX_STRING = 65536
1
+ local MAX_DEPTH = 16;
2
+ local MAX_ENTRIES = 4096;
3
+ local MAX_STRING = 65536;
4
4
 
5
- local describe
5
+ local describe, check;
6
6
 
7
- local function joinPath(path, segment)
8
- if path == '' then
9
- return segment
10
- end
7
+ ---@param path string
8
+ ---@param segment string
9
+ ---@return string
10
+ local function joinPath (path, segment)
11
+ if (path == '') then
12
+ return segment;
13
+ end
11
14
 
12
- return path .. '.' .. segment
15
+ return path .. '.' .. segment;
13
16
  end
14
17
 
15
- local function describeUnion(descriptor)
16
- local parts = {}
18
+ ---@param descriptor table
19
+ ---@return string
20
+ local function describeUnion (descriptor)
21
+ local parts = { };
17
22
 
18
- for index = 1, #descriptor.options do
19
- parts[index] = describe(descriptor.options[index])
20
- end
23
+ for index = 1, #descriptor.options do
24
+ parts[index] = describe (descriptor.options[index]);
25
+ end
21
26
 
22
- return table.concat(parts, ' | ')
27
+ return table.concat (parts, ' | ');
23
28
  end
24
29
 
25
- describe = function(descriptor)
26
- local kind = descriptor.kind
30
+ ---@param descriptor table
31
+ ---@return string
32
+ describe = function (descriptor)
33
+ local kind = descriptor.kind;
27
34
 
28
- if kind == 'literal' then
29
- if type(descriptor.value) == 'string' then
30
- return "'" .. descriptor.value .. "'"
31
- end
35
+ if (kind == 'literal') then
36
+ if (type (descriptor.value) == 'string') then
37
+ return '\'' .. descriptor.value .. '\'';
38
+ end
32
39
 
33
- return tostring(descriptor.value)
34
- end
40
+ return tostring (descriptor.value);
41
+ end
35
42
 
36
- if kind == 'optional' then
37
- return describe(descriptor.element) .. '?'
38
- end
43
+ if (kind == 'optional') then
44
+ return describe (descriptor.element) .. '?';
45
+ end
39
46
 
40
- if kind == 'array' then
41
- return describe(descriptor.element) .. '[]'
42
- end
47
+ if (kind == 'array') then
48
+ return describe (descriptor.element) .. '[]';
49
+ end
43
50
 
44
- if kind == 'map' then
45
- return 'table<' .. describe(descriptor.key) .. ', ' .. describe(descriptor.value) .. '>'
46
- end
51
+ if (kind == 'map') then
52
+ return 'table<' .. describe (descriptor.key) .. ', ' .. describe (descriptor.value) .. '>';
53
+ end
47
54
 
48
- if kind == 'union' then
49
- return describeUnion(descriptor)
50
- end
55
+ if (kind == 'union') then
56
+ return describeUnion (descriptor);
57
+ end
51
58
 
52
- if kind == 'record' or kind == 'instance' then
53
- return descriptor.name
54
- end
59
+ if (kind == 'record') or (kind == 'instance') then
60
+ return descriptor.name;
61
+ end
55
62
 
56
- return kind
63
+ return kind;
57
64
  end
58
65
 
59
- local function fail(path, descriptor, reason)
60
- local place = path == '' and 'value' or ('"' .. path .. '"')
66
+ ---@param path string
67
+ ---@param descriptor table
68
+ ---@param reason? string
69
+ local function fail (path, descriptor, reason)
70
+ local place = (path == '') and 'value' or ('"' .. path .. '"');
61
71
 
62
- if reason ~= nil then
63
- error('luam-validate: ' .. place .. ' ' .. reason, 0)
64
- end
72
+ if (reason ~= nil) then
73
+ error ('luam-validate: ' .. place .. ' ' .. reason, 0);
74
+ end
65
75
 
66
- error('luam-validate: ' .. place .. ' expected "' .. describe(descriptor) .. '"', 0)
76
+ error ('luam-validate: ' .. place .. ' expected "' .. describe (descriptor) .. '"', 0);
67
77
  end
68
78
 
69
- local function countEntries(value, path, descriptor)
70
- local total = 0
79
+ ---@param value table
80
+ ---@param path string
81
+ ---@param descriptor table
82
+ ---@return number
83
+ local function countEntries (value, path, descriptor)
84
+ local total = 0;
71
85
 
72
- for _ in pairs(value) do
73
- total = total + 1
86
+ for _ in pairs (value) do
87
+ total = total + 1;
74
88
 
75
- if total > MAX_ENTRIES then
76
- fail(path, descriptor, 'has more than ' .. MAX_ENTRIES .. ' entries')
77
- end
78
- end
89
+ if (total > MAX_ENTRIES) then
90
+ fail (path, descriptor, 'has more than ' .. MAX_ENTRIES .. ' entries');
91
+ end
92
+ end
79
93
 
80
- return total
94
+ return total;
81
95
  end
82
96
 
83
- local function isInstanceOf(value, name)
84
- local meta = getmetatable(value)
85
- local definition = meta and meta.__index
86
- local depth = 0
97
+ ---@param value table
98
+ ---@param name string
99
+ ---@return boolean
100
+ local function isInstanceOf (value, name)
101
+ local meta = getmetatable (value);
102
+ local definition = meta and meta.__index;
103
+ local depth = 0;
87
104
 
88
- while type(definition) == 'table' and depth <= MAX_DEPTH do
89
- if definition.__name == name then
90
- return true
91
- end
105
+ while (type (definition) == 'table') and (depth <= MAX_DEPTH) do
106
+ if (definition.__name == name) then
107
+ return true;
108
+ end
92
109
 
93
- definition = definition.__super
94
- depth = depth + 1
95
- end
110
+ definition = definition.__super;
111
+ depth = depth + 1;
112
+ end
96
113
 
97
- return false
114
+ return false;
98
115
  end
99
116
 
100
- local check
117
+ ---@param value table
118
+ ---@param descriptor table
119
+ ---@param path string
120
+ ---@param depth number
121
+ ---@return table
122
+ local function checkRecord (value, descriptor, path, depth)
123
+ countEntries (value, path, descriptor);
101
124
 
102
- local function checkRecord(value, descriptor, path, depth)
103
- countEntries(value, path, descriptor)
125
+ for index = 1, #descriptor.members do
126
+ local member = descriptor.members[index];
104
127
 
105
- for index = 1, #descriptor.members do
106
- local member = descriptor.members[index]
128
+ check (value[member.key], member.value, joinPath (path, member.key), depth + 1);
129
+ end
107
130
 
108
- check(value[member.key], member.value, joinPath(path, member.key), depth + 1)
109
- end
110
-
111
- return value
131
+ return value;
112
132
  end
113
133
 
114
- local function checkArray(value, descriptor, path, depth)
115
- local total = countEntries(value, path, descriptor)
134
+ ---@param value table
135
+ ---@param descriptor table
136
+ ---@param path string
137
+ ---@param depth number
138
+ ---@return table
139
+ local function checkArray (value, descriptor, path, depth)
140
+ local total = countEntries (value, path, descriptor);
116
141
 
117
- for index = 1, total do
118
- check(value[index], descriptor.element, path .. '[' .. index .. ']', depth + 1)
119
- end
142
+ for index = 1, total do
143
+ check (value[index], descriptor.element, path .. '[' .. index .. ']', depth + 1);
144
+ end
120
145
 
121
- return value
146
+ return value;
122
147
  end
123
148
 
124
- local function checkMap(value, descriptor, path, depth)
125
- countEntries(value, path, descriptor)
149
+ ---@param value table
150
+ ---@param descriptor table
151
+ ---@param path string
152
+ ---@param depth number
153
+ ---@return table
154
+ local function checkMap (value, descriptor, path, depth)
155
+ countEntries (value, path, descriptor);
126
156
 
127
- for key, entry in pairs(value) do
128
- check(key, descriptor.key, joinPath(path, tostring(key)) .. ' (key)', depth + 1)
129
- check(entry, descriptor.value, joinPath(path, tostring(key)), depth + 1)
130
- end
157
+ for key, entry in pairs (value) do
158
+ check (key, descriptor.key, joinPath (path, tostring (key)) .. ' (key)', depth + 1);
159
+ check (entry, descriptor.value, joinPath (path, tostring (key)), depth + 1);
160
+ end
131
161
 
132
- return value
162
+ return value;
133
163
  end
134
164
 
135
- local function matches(value, descriptor, depth)
136
- local ok = pcall(check, value, descriptor, '', depth)
165
+ ---@param value any
166
+ ---@param descriptor table
167
+ ---@param depth number
168
+ ---@return boolean
169
+ local function matches (value, descriptor, depth)
170
+ local ok = pcall (check, value, descriptor, '', depth);
137
171
 
138
- return ok
172
+ return ok;
139
173
  end
140
174
 
141
- check = function(value, descriptor, path, depth)
142
- if depth > MAX_DEPTH then
143
- fail(path, descriptor, 'is nested deeper than ' .. MAX_DEPTH .. ' levels')
144
- end
145
-
146
- local kind = descriptor.kind
147
-
148
- if kind == 'any' then
149
- return value
150
- end
151
-
152
- if kind == 'optional' then
153
- if value == nil then
154
- return value
155
- end
156
-
157
- return check(value, descriptor.element, path, depth)
158
- end
159
-
160
- if kind == 'nil' then
161
- if value ~= nil then
162
- fail(path, descriptor)
163
- end
164
-
165
- return value
166
- end
167
-
168
- if kind == 'literal' then
169
- if value ~= descriptor.value then
170
- fail(path, descriptor)
171
- end
172
-
173
- return value
174
- end
175
-
176
- if kind == 'string' or kind == 'number' or kind == 'boolean' or kind == 'userdata' or kind == 'thread' or kind == 'function' then
177
- if type(value) ~= kind then
178
- fail(path, descriptor)
179
- end
180
-
181
- if kind == 'string' and #value > MAX_STRING then
182
- fail(path, descriptor, 'is longer than ' .. MAX_STRING .. ' characters')
183
- end
184
-
185
- return value
186
- end
187
-
188
- if kind == 'table' then
189
- if type(value) ~= 'table' then
190
- fail(path, descriptor)
191
- end
192
-
193
- return value
194
- end
195
-
196
- if kind == 'union' then
197
- for index = 1, #descriptor.options do
198
- if matches(value, descriptor.options[index], depth) then
199
- return value
200
- end
201
- end
202
-
203
- fail(path, descriptor)
204
- end
205
-
206
- if type(value) ~= 'table' then
207
- fail(path, descriptor)
208
- end
209
-
210
- if kind == 'record' then
211
- return checkRecord(value, descriptor, path, depth)
212
- end
213
-
214
- if kind == 'array' then
215
- return checkArray(value, descriptor, path, depth)
216
- end
217
-
218
- if kind == 'map' then
219
- return checkMap(value, descriptor, path, depth)
220
- end
221
-
222
- if kind == 'instance' then
223
- if not isInstanceOf(value, descriptor.name) then
224
- fail(path, descriptor)
225
- end
226
-
227
- return value
228
- end
229
-
230
- return value
175
+ ---@param value any
176
+ ---@param descriptor table
177
+ ---@param path string
178
+ ---@param depth number
179
+ ---@return any
180
+ check = function (value, descriptor, path, depth)
181
+ if (depth > MAX_DEPTH) then
182
+ fail (path, descriptor, 'is nested deeper than ' .. MAX_DEPTH .. ' levels');
183
+ end
184
+
185
+ local kind = descriptor.kind;
186
+
187
+ if (kind == 'any') then
188
+ return value;
189
+ end
190
+
191
+ if (kind == 'optional') then
192
+ if (value == nil) then
193
+ return value;
194
+ end
195
+
196
+ return check (value, descriptor.element, path, depth);
197
+ end
198
+
199
+ if (kind == 'nil') then
200
+ if (value ~= nil) then
201
+ fail (path, descriptor);
202
+ end
203
+
204
+ return value;
205
+ end
206
+
207
+ if (kind == 'literal') then
208
+ if (value ~= descriptor.value) then
209
+ fail (path, descriptor);
210
+ end
211
+
212
+ return value;
213
+ end
214
+
215
+ if (kind == 'string') or (kind == 'number') or (kind == 'boolean') or (kind == 'userdata') or (kind == 'thread') or (kind == 'function') then
216
+ if (type (value) ~= kind) then
217
+ fail (path, descriptor);
218
+ end
219
+
220
+ if (kind == 'string') and (#value > MAX_STRING) then
221
+ fail (path, descriptor, 'is longer than ' .. MAX_STRING .. ' characters');
222
+ end
223
+
224
+ return value;
225
+ end
226
+
227
+ if (kind == 'table') then
228
+ if (type (value) ~= 'table') then
229
+ fail (path, descriptor);
230
+ end
231
+
232
+ return value;
233
+ end
234
+
235
+ if (kind == 'union') then
236
+ for index = 1, #descriptor.options do
237
+ if (matches (value, descriptor.options[index], depth)) then
238
+ return value;
239
+ end
240
+ end
241
+
242
+ fail (path, descriptor);
243
+ end
244
+
245
+ if (type (value) ~= 'table') then
246
+ fail (path, descriptor);
247
+ end
248
+
249
+ if (kind == 'record') then
250
+ return checkRecord (value, descriptor, path, depth);
251
+ end
252
+
253
+ if (kind == 'array') then
254
+ return checkArray (value, descriptor, path, depth);
255
+ end
256
+
257
+ if (kind == 'map') then
258
+ return checkMap (value, descriptor, path, depth);
259
+ end
260
+
261
+ if (kind == 'instance') then
262
+ if (not isInstanceOf (value, descriptor.name)) then
263
+ fail (path, descriptor);
264
+ end
265
+
266
+ return value;
267
+ end
268
+
269
+ return value;
231
270
  end
232
271
 
233
- function __luam_validate(value, descriptor)
234
- return check(value, descriptor, '', 1)
272
+ ---@param value any
273
+ ---@param descriptor table
274
+ ---@return any
275
+ function __luam_validate (value, descriptor)
276
+ return check (value, descriptor, '', 1);
235
277
  end
236
278
 
237
- function __luam_matches(value, descriptor)
238
- return matches(value, descriptor, 1)
279
+ ---@param value any
280
+ ---@param descriptor table
281
+ ---@return boolean
282
+ function __luam_matches (value, descriptor)
283
+ return matches (value, descriptor, 1);
239
284
  end