1#[derive(Debug, Clone, Copy)]
11pub struct Arity {
12 pub required: usize,
13 pub max: usize,
14}
15
16pub fn function_arity(name: &str) -> Option<Arity> {
19 BUILTIN_FUNCTIONS
20 .binary_search_by_key(&name, |&(n, _, _)| n)
21 .ok()
22 .map(|i| {
23 let (_, req, max) = BUILTIN_FUNCTIONS[i];
24 Arity { required: req, max }
25 })
26}
27
28pub fn is_builtin_class(name: &str) -> bool {
30 BUILTIN_CLASSES
31 .binary_search_by_key(&name, |&n| n)
32 .is_ok()
33}
34
35pub static BUILTIN_FUNCTIONS: &[(&str, usize, usize)] = &[
38 ("abs", 1, 1),
39 ("array_chunk", 2, 3),
40 ("array_column", 2, 3),
41 ("array_combine", 2, 2),
42 ("array_diff", 1, usize::MAX),
43 ("array_diff_assoc", 1, usize::MAX),
44 ("array_diff_key", 1, usize::MAX),
45 ("array_fill", 3, 3),
46 ("array_filter", 1, 3),
47 ("array_flip", 1, 1),
48 ("array_intersect", 1, usize::MAX),
49 ("array_intersect_key", 1, usize::MAX),
50 ("array_key_exists", 2, 2),
51 ("array_key_first", 1, 1),
52 ("array_key_last", 1, 1),
53 ("array_keys", 1, 3),
54 ("array_map", 2, usize::MAX),
55 ("array_merge", 0, usize::MAX),
56 ("array_merge_recursive", 0, usize::MAX),
57 ("array_pad", 3, 3),
58 ("array_pop", 1, 1),
59 ("array_push", 1, usize::MAX),
60 ("array_replace", 1, usize::MAX),
61 ("array_reverse", 1, 2),
62 ("array_search", 2, 3),
63 ("array_shift", 1, 1),
64 ("array_slice", 2, 4),
65 ("array_splice", 2, 4),
66 ("array_sum", 1, 1),
67 ("array_unique", 1, 2),
68 ("array_unshift", 1, usize::MAX),
69 ("array_values", 1, 1),
70 ("arsort", 1, 2),
71 ("asort", 1, 2),
72 ("base64_decode", 1, 2),
73 ("base64_encode", 1, 1),
74 ("base_convert", 3, 3),
75 ("basename", 1, 2),
76 ("ceil", 1, 1),
77 ("chr", 1, 1),
78 ("chunk_split", 1, 3),
79 ("class_alias", 2, 3),
80 ("class_exists", 1, 2),
81 ("class_implements", 1, 2),
82 ("class_parents", 1, 2),
83 ("compact", 1, usize::MAX),
84 ("copy", 2, 3),
85 ("count", 1, 2),
86 ("ctype_alpha", 1, 1),
87 ("ctype_digit", 1, 1),
88 ("ctype_lower", 1, 1),
89 ("ctype_upper", 1, 1),
90 ("curl_close", 1, 1),
91 ("curl_error", 1, 1),
92 ("curl_exec", 1, 1),
93 ("curl_getinfo", 1, 2),
94 ("curl_init", 0, 1),
95 ("curl_setopt", 3, 3),
96 ("curl_setopt_array", 2, 2),
97 ("date", 1, 2),
98 ("date_create", 0, 2),
99 ("date_diff", 2, 3),
100 ("date_format", 2, 2),
101 ("defined", 1, 1),
102 ("dirname", 1, 2),
103 ("empty", 1, 1),
104 ("end", 1, 1),
105 ("error_log", 1, 4),
106 ("error_reporting", 0, 1),
107 ("exec", 1, 3),
108 ("explode", 2, 3),
109 ("extension_loaded", 1, 1),
110 ("extract", 1, 3),
111 ("fclose", 1, 1),
112 ("feof", 1, 1),
113 ("fgets", 1, 2),
114 ("file", 1, 3),
115 ("file_exists", 1, 1),
116 ("file_get_contents", 1, 5),
117 ("file_put_contents", 2, 4),
118 ("filemtime", 1, 1),
119 ("filesize", 1, 1),
120 ("floor", 1, 1),
121 ("fopen", 2, 4),
122 ("fread", 2, 2),
123 ("fseek", 2, 3),
124 ("function_exists", 1, 2),
125 ("fwrite", 2, 3),
126 ("get_class", 0, 1),
127 ("get_class_methods", 1, 1),
128 ("get_declared_classes", 0, 0),
129 ("get_object_vars", 1, 1),
130 ("getenv", 0, 2),
131 ("gettype", 1, 1),
132 ("glob", 1, 2),
133 ("gmdate", 1, 2),
134 ("header", 1, 3),
135 ("htmlentities", 1, 4),
136 ("htmlspecialchars", 1, 4),
137 ("htmlspecialchars_decode", 1, 2),
138 ("http_response_code", 0, 1),
139 ("implode", 1, 2),
140 ("in_array", 2, 3),
141 ("ini_get", 1, 1),
142 ("ini_set", 2, 2),
143 ("interface_exists", 1, 2),
144 ("intval", 1, 2),
145 ("is_a", 2, 3),
146 ("is_array", 1, 1),
147 ("is_bool", 1, 1),
148 ("is_callable", 1, 3),
149 ("is_dir", 1, 1),
150 ("is_file", 1, 1),
151 ("is_float", 1, 1),
152 ("is_int", 1, 1),
153 ("is_null", 1, 1),
154 ("is_numeric", 1, 1),
155 ("is_object", 1, 1),
156 ("is_readable", 1, 1),
157 ("is_string", 1, 1),
158 ("is_subclass_of", 2, 3),
159 ("is_writable", 1, 1),
160 ("json_decode", 1, 4),
161 ("json_encode", 1, 3),
162 ("json_last_error", 0, 0),
163 ("json_last_error_msg", 0, 0),
164 ("krsort", 1, 2),
165 ("ksort", 1, 2),
166 ("lcfirst", 1, 1),
167 ("ltrim", 1, 2),
168 ("max", 1, usize::MAX),
169 ("mb_convert_encoding", 2, 3),
170 ("mb_detect_encoding", 1, 3),
171 ("mb_internal_encoding", 0, 1),
172 ("mb_strlen", 1, 2),
173 ("mb_strpos", 2, 4),
174 ("mb_strrpos", 2, 4),
175 ("mb_strtolower", 1, 2),
176 ("mb_strtoupper", 1, 2),
177 ("mb_substr", 2, 4),
178 ("md5", 1, 2),
179 ("method_exists", 2, 2),
180 ("microtime", 0, 1),
181 ("min", 1, usize::MAX),
182 ("mkdir", 1, 4),
183 ("mktime", 0, 6),
184 ("number_format", 1, 4),
185 ("ob_end_clean", 0, 0),
186 ("ob_end_flush", 0, 0),
187 ("ob_get_clean", 0, 0),
188 ("ob_get_contents", 0, 0),
189 ("ob_start", 0, 3),
190 ("ord", 1, 1),
191 ("pack", 1, usize::MAX),
192 ("parse_url", 1, 2),
193 ("pathinfo", 1, 2),
194 ("phpversion", 0, 1),
195 ("preg_match", 2, 5),
196 ("preg_match_all", 2, 5),
197 ("preg_quote", 1, 2),
198 ("preg_replace", 3, 5),
199 ("preg_replace_callback", 3, 5),
200 ("preg_split", 2, 4),
201 ("print_r", 1, 2),
202 ("property_exists", 2, 2),
203 ("range", 2, 3),
204 ("rawurldecode", 1, 1),
205 ("rawurlencode", 1, 1),
206 ("realpath", 1, 1),
207 ("rename", 2, 3),
208 ("reset", 1, 1),
209 ("rmdir", 1, 2),
210 ("round", 1, 3),
211 ("rtrim", 1, 2),
212 ("serialize", 1, 1),
213 ("session_destroy", 0, 0),
214 ("session_id", 0, 1),
215 ("session_name", 0, 1),
216 ("session_start", 0, 1),
217 ("setcookie", 1, 7),
218 ("sha1", 1, 2),
219 ("sleep", 1, 1),
220 ("sort", 1, 2),
221 ("sprintf", 1, usize::MAX),
222 ("sqrt", 1, 1),
223 ("srand", 0, 2),
224 ("str_contains", 2, 2),
225 ("str_ends_with", 2, 2),
226 ("str_pad", 2, 4),
227 ("str_repeat", 2, 2),
228 ("str_replace", 3, 4),
229 ("str_split", 1, 2),
230 ("str_starts_with", 2, 2),
231 ("str_word_count", 1, 3),
232 ("strcasecmp", 2, 2),
233 ("strcmp", 2, 2),
234 ("strip_tags", 1, 2),
235 ("stripslashes", 1, 1),
236 ("strlen", 1, 1),
237 ("strncmp", 3, 3),
238 ("strpos", 2, 3),
239 ("strrchr", 2, 2),
240 ("strrev", 1, 1),
241 ("strrpos", 2, 3),
242 ("strstr", 2, 3),
243 ("strtok", 1, 2),
244 ("strtolower", 1, 1),
245 ("strtotime", 1, 2),
246 ("strtoupper", 1, 1),
247 ("strval", 1, 1),
248 ("substr", 2, 3),
249 ("substr_count", 2, 4),
250 ("substr_replace", 3, 4),
251 ("sys_get_temp_dir", 0, 0),
252 ("time", 0, 0),
253 ("touch", 1, 3),
254 ("trigger_error", 1, 2),
255 ("trim", 1, 2),
256 ("uasort", 2, 2),
257 ("ucfirst", 1, 1),
258 ("ucwords", 1, 2),
259 ("uksort", 2, 2),
260 ("unlink", 1, 2),
261 ("unserialize", 1, 2),
262 ("urldecode", 1, 1),
263 ("urlencode", 1, 1),
264 ("usort", 2, 2),
265 ("var_dump", 1, usize::MAX),
266 ("var_export", 1, 2),
267 ("wordwrap", 1, 4),
268];
269
270static BUILTIN_CLASSES: &[&str] = &[
272 "ArrayAccess",
273 "ArrayIterator",
274 "ArrayObject",
275 "BadFunctionCallException",
276 "BadMethodCallException",
277 "Closure",
278 "Countable",
279 "DateInterval",
280 "DateTime",
281 "DateTimeImmutable",
282 "DateTimeInterface",
283 "DateTimeZone",
284 "DirectoryIterator",
285 "DomainException",
286 "Error",
287 "Exception",
288 "FilesystemIterator",
289 "Generator",
290 "GlobIterator",
291 "InfiniteIterator",
292 "InvalidArgumentException",
293 "Iterator",
294 "IteratorAggregate",
295 "JsonSerializable",
296 "LengthException",
297 "LogicException",
298 "OutOfBoundsException",
299 "OutOfRangeException",
300 "OverflowException",
301 "PDO",
302 "PDOException",
303 "PDOStatement",
304 "RangeException",
305 "RecursiveArrayIterator",
306 "RecursiveDirectoryIterator",
307 "RecursiveIterator",
308 "RecursiveIteratorIterator",
309 "ReflectionClass",
310 "ReflectionException",
311 "ReflectionFunction",
312 "ReflectionMethod",
313 "ReflectionProperty",
314 "RuntimeException",
315 "Serializable",
316 "SplDoublyLinkedList",
317 "SplFileInfo",
318 "SplFileObject",
319 "SplFixedArray",
320 "SplMaxHeap",
321 "SplMinHeap",
322 "SplPriorityQueue",
323 "SplQueue",
324 "SplStack",
325 "Stringable",
326 "Throwable",
327 "TypeError",
328 "UnderflowException",
329 "UnexpectedValueException",
330 "ValueError",
331 "WeakMap",
332 "WeakReference",
333 "stdClass",
334];
335
336#[cfg(test)]
337mod tests {
338 use super::*;
339
340 #[test]
341 fn builtin_functions_are_sorted() {
342 for pair in BUILTIN_FUNCTIONS.windows(2) {
343 assert!(
344 pair[0].0 <= pair[1].0,
345 "out of order: '{}' before '{}'",
346 pair[0].0,
347 pair[1].0
348 );
349 }
350 }
351
352 #[test]
353 fn builtin_classes_are_sorted() {
354 for pair in BUILTIN_CLASSES.windows(2) {
355 assert!(pair[0] <= pair[1], "out of order: '{}' before '{}'", pair[0], pair[1]);
356 }
357 }
358
359 #[test]
360 fn strlen_is_known() {
361 assert!(function_arity("strlen").is_some());
362 }
363
364 #[test]
365 fn pdo_is_builtin_class() {
366 assert!(is_builtin_class("PDO"));
367 }
368
369 #[test]
370 fn unknown_function_is_none() {
371 assert!(function_arity("totally_unknown_fn_xyz").is_none());
372 }
373}