customasm/expr/
builtin_fn.rs1use crate::*;
2
3
4pub fn resolve_builtin_fn(
5 name: &str)
6 -> Option<fn(&mut expr::EvalFunctionQuery) -> Result<expr::Value, ()>>
7{
8 match name.as_ref()
9 {
10 "assert" => Some(eval_builtin_assert),
11 "sizeof" => Some(eval_builtin_sizeof),
12 "le" => Some(eval_builtin_le),
13 "ascii" => Some(eval_builtin_ascii),
14 "utf8" => Some(eval_builtin_utf8),
15 "utf16be" => Some(eval_builtin_utf16be),
16 "utf16le" => Some(eval_builtin_utf16le),
17 "utf32be" => Some(eval_builtin_utf32be),
18 "utf32le" => Some(eval_builtin_utf32le),
19 "strlen" => Some(eval_builtin_strlen),
20 _ => None,
21 }
22}
23
24
25pub fn get_static_size_builtin_fn(
26 name: &str,
27 provider: &expr::StaticallyKnownProvider,
28 args: &Vec<expr::Expr>)
29 -> Option<usize>
30{
31 let get_static_size_fn = {
32 match name.as_ref()
33 {
34 "sizeof" => get_static_size_builtin_sizeof,
35 "le" => get_static_size_builtin_le,
36 _ => return None,
37 }
38 };
39
40 get_static_size_fn(
41 provider,
42 args)
43}
44
45
46pub fn get_statically_known_value_builtin_fn(
47 name: &str,
48 _args: &Vec<expr::Expr>)
49 -> bool
50{
51 match name.as_ref()
52 {
53 "assert" => false,
54 "sizeof" => true,
55 "le" => true,
56 "ascii" => true,
57 "utf8" => true,
58 "utf16be" => true,
59 "utf16le" => true,
60 "utf32be" => true,
61 "utf32le" => true,
62 "strlen" => true,
63 _ => false,
64 }
65}
66
67
68pub fn eval_builtin_fn(
69 query: &mut expr::EvalFunctionQuery)
70 -> Result<expr::Value, ()>
71{
72 let builtin_name = {
73 match query.func
74 {
75 expr::Value::ExprBuiltInFunction(ref name) => name,
76 _ => unreachable!(),
77 }
78 };
79
80 let builtin_fn = resolve_builtin_fn(builtin_name).unwrap();
81 builtin_fn(query)
82}
83
84
85pub fn eval_builtin_assert(
86 query: &mut expr::EvalFunctionQuery)
87 -> Result<expr::Value, ()>
88{
89 query.ensure_min_max_arg_number(1, 2)?;
90
91 let condition = query.args[0]
92 .value
93 .expect_bool(
94 query.report,
95 query.args[0].span)?;
96
97 if !condition
98 {
99 let msg = {
100 if query.args.len() == 2
101 {
102 diagn::Message::error_span(
103 format!(
104 "assertion failed: {}",
105 query.args[1]
106 .value
107 .expect_string(query.report, query.args[1].span)?
108 .utf8_contents),
109 query.span)
110 }
111 else {
112 diagn::Message::error_span("assertion failed", query.span)
113 }
114 };
115
116 return Ok(expr::Value::FailedConstraint(
117 query.report.wrap_in_parents_capped(msg)));
118 }
119
120 Ok(expr::Value::Void)
121}
122
123
124pub fn eval_builtin_sizeof(
125 query: &mut expr::EvalFunctionQuery)
126 -> Result<expr::Value, ()>
127{
128 query.ensure_arg_number(1)?;
129
130 let (_bigint, size) = query.args[0].value.expect_sized_integerlike(
131 query.report,
132 query.args[0].span)?;
133
134 Ok(expr::Value::make_integer(size))
135}
136
137
138pub fn eval_builtin_le(
139 query: &mut expr::EvalFunctionQuery)
140 -> Result<expr::Value, ()>
141{
142 query.ensure_arg_number(1)?;
143
144 let bigint = query.args[0].value.expect_sized_bigint(
145 query.report,
146 query.args[0].span)?;
147
148 if bigint.size.unwrap() % 8 != 0
149 {
150 query.report.push_parent(
151 "argument to `le` must have a size multiple of 8",
152 query.args[0].span);
153
154 query.report.note(format!(
155 "got size {}",
156 bigint.size.unwrap()));
157
158 query.report.pop_parent();
159
160 return Err(());
161 }
162
163 Ok(expr::Value::make_integer(bigint.convert_le()))
164}
165
166
167pub fn get_static_size_builtin_sizeof(
168 provider: &expr::StaticallyKnownProvider,
169 args: &Vec<expr::Expr>)
170 -> Option<usize>
171{
172 if args.len() == 1
173 {
174 args[0].get_static_size(provider)
175 }
176 else
177 {
178 None
179 }
180}
181
182
183pub fn get_static_size_builtin_le(
184 provider: &expr::StaticallyKnownProvider,
185 args: &Vec<expr::Expr>)
186 -> Option<usize>
187{
188 if args.len() == 1
189 {
190 args[0].get_static_size(provider)
191 }
192 else
193 {
194 None
195 }
196}
197
198
199pub fn eval_builtin_string_encoding(
200 encoding: &str,
201 query: &mut expr::EvalFunctionQuery)
202 -> Result<expr::Value, ()>
203{
204 query.ensure_arg_number(1)?;
205
206 let s = query.args[0].value.expect_string(
207 query.report,
208 query.args[0].span)?;
209
210 Ok(expr::Value::make_string(
211 &s.utf8_contents,
212 encoding))
213}
214
215
216pub fn eval_builtin_ascii(
217 query: &mut expr::EvalFunctionQuery)
218 -> Result<expr::Value, ()>
219{
220 eval_builtin_string_encoding("ascii", query)
221}
222
223
224pub fn eval_builtin_utf8(
225 query: &mut expr::EvalFunctionQuery)
226 -> Result<expr::Value, ()>
227{
228 eval_builtin_string_encoding("utf8", query)
229}
230
231
232pub fn eval_builtin_utf16be(
233 query: &mut expr::EvalFunctionQuery)
234 -> Result<expr::Value, ()>
235{
236 eval_builtin_string_encoding("utf16be", query)
237}
238
239
240pub fn eval_builtin_utf16le(
241 query: &mut expr::EvalFunctionQuery)
242 -> Result<expr::Value, ()>
243{
244 eval_builtin_string_encoding("utf16le", query)
245}
246
247
248pub fn eval_builtin_utf32be(
249 query: &mut expr::EvalFunctionQuery)
250 -> Result<expr::Value, ()>
251{
252 eval_builtin_string_encoding("utf32be", query)
253}
254
255
256pub fn eval_builtin_utf32le(
257 query: &mut expr::EvalFunctionQuery)
258 -> Result<expr::Value, ()>
259{
260 eval_builtin_string_encoding("utf32le", query)
261}
262
263
264pub fn eval_builtin_strlen(
265 query: &mut expr::EvalFunctionQuery)
266 -> Result<expr::Value, ()>
267{
268 query.ensure_arg_number(1)?;
269
270 let s = query.args[0].value.expect_string(
271 query.report,
272 query.args[0].span)?;
273
274 Ok(expr::Value::make_integer(s.utf8_contents.len()))
275
276}