1use std::borrow::Cow;
2
3use bitflags::bitflags;
4use bumpalo::boxed::Box;
5use bumpalo::collections::String as BumpString;
6use bumpalo::collections::Vec as BumpVec;
7use bumpalo::Bump;
8use hashbrown::DefaultHashBuilder;
9use hashbrown::HashMap;
10
11use super::frame::Frame;
12use super::functions::FunctionContext;
13use crate::parser::ast::{Ast, AstKind, RegexLiteral};
14use crate::{Error, Result};
15
16pub mod impls;
17pub mod iterator;
18mod range;
19pub mod serialize;
20
21use self::range::Range;
22use self::serialize::{DumpFormatter, PrettyFormatter, Serializer};
23pub use iterator::MemberIterator;
24
25bitflags! {
26 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
27 pub struct ArrayFlags: u8 {
28 const SEQUENCE = 0b00000001;
29 const SINGLETON = 0b00000010;
30 const CONS = 0b00000100;
31 const WRAPPED = 0b00001000;
32 const TUPLE_STREAM = 0b00010000;
33 }
34}
35
36pub const UNDEFINED: Value = Value::Undefined;
37pub const TRUE: Value = Value::Bool(true);
38pub const FALSE: Value = Value::Bool(false);
39
40pub enum Value<'a> {
49 Undefined,
50 Null,
51 Number(f64),
52 Bool(bool),
53 String(BumpString<'a>),
54 Regex(std::boxed::Box<RegexLiteral>),
55 Array(BumpVec<'a, &'a Value<'a>>, ArrayFlags),
56 Object(HashMap<BumpString<'a>, &'a Value<'a>, DefaultHashBuilder, &'a Bump>),
57 Range(Range<'a>),
58 Lambda {
59 ast: Box<'a, Ast>,
60 input: &'a Value<'a>,
61 frame: Frame<'a>,
62 },
63 NativeFn {
64 name: String,
65 arity: usize,
66 func: fn(FunctionContext<'a, '_>, &[&'a Value<'a>]) -> Result<&'a Value<'a>>,
67 },
68 Transformer {
69 pattern: std::boxed::Box<Ast>,
70 update: std::boxed::Box<Ast>,
71 delete: Option<std::boxed::Box<Ast>>,
72 },
73}
74
75#[allow(clippy::mut_from_ref)]
76impl<'a> Value<'a> {
77 pub fn undefined() -> &'a Value<'a> {
78 unsafe { std::mem::transmute::<&Value<'static>, &'a Value<'a>>(&UNDEFINED) }
81 }
82
83 pub fn null(arena: &Bump) -> &mut Value {
84 arena.alloc(Value::Null)
85 }
86
87 pub fn bool(value: bool) -> &'a Value<'a> {
88 if value {
89 unsafe { std::mem::transmute::<&Value<'static>, &'a Value<'a>>(&TRUE) }
90 } else {
91 unsafe { std::mem::transmute::<&Value<'static>, &'a Value<'a>>(&FALSE) }
92 }
93 }
94
95 pub fn number(arena: &Bump, value: impl Into<f64>) -> &mut Value {
96 arena.alloc(Value::Number(value.into()))
97 }
98
99 pub fn number_from_u128(arena: &Bump, value: u128) -> Result<&mut Value> {
100 let value_f64 = value as f64;
101 if value_f64 as u128 != value {
102 return Err(Error::D1001NumberOfOutRange(value_f64));
104 };
105 Ok(arena.alloc(Value::Number(value_f64)))
106 }
107
108 pub fn string(arena: &'a Bump, value: &str) -> &'a mut Value<'a> {
109 arena.alloc(Value::String(BumpString::from_str_in(value, arena)))
110 }
111
112 pub fn array(arena: &Bump, flags: ArrayFlags) -> &mut Value {
113 let v = BumpVec::new_in(arena);
114 arena.alloc(Value::Array(v, flags))
115 }
116
117 pub fn array_from(
118 arena: &'a Bump,
119 arr: BumpVec<'a, &'a Value<'a>>,
120 flags: ArrayFlags,
121 ) -> &'a mut Value<'a> {
122 arena.alloc(Value::Array(arr, flags))
123 }
124
125 pub fn array_with_capacity(arena: &Bump, capacity: usize, flags: ArrayFlags) -> &mut Value {
126 arena.alloc(Value::Array(
127 BumpVec::with_capacity_in(capacity, arena),
128 flags,
129 ))
130 }
131
132 pub fn object(arena: &Bump) -> &mut Value {
133 arena.alloc(Value::Object(HashMap::new_in(arena)))
134 }
135
136 pub fn object_from<H>(
137 hash: &HashMap<BumpString<'a>, &'a Value<'a>, H, &'a Bump>,
138 arena: &'a Bump,
139 ) -> &'a mut Value<'a> {
140 let result = Value::object_with_capacity(arena, hash.len());
141 if let Value::Object(o) = result {
142 o.extend(hash.iter().map(|(k, v)| (k.clone(), *v)));
143 }
144 result
145 }
146
147 pub fn object_with_capacity(arena: &Bump, capacity: usize) -> &mut Value {
148 arena.alloc(Value::Object(HashMap::with_capacity_in(capacity, arena)))
149 }
150
151 pub fn lambda(
152 arena: &'a Bump,
153 node: &Ast,
154 input: &'a Value<'a>,
155 frame: Frame<'a>,
156 ) -> &'a mut Value<'a> {
157 arena.alloc(Value::Lambda {
158 ast: Box::new_in(node.clone(), arena),
159 input,
160 frame,
161 })
162 }
163
164 pub fn nativefn(
165 arena: &'a Bump,
166 name: &str,
167 arity: usize,
168 func: fn(FunctionContext<'a, '_>, &[&'a Value<'a>]) -> Result<&'a Value<'a>>,
169 ) -> &'a mut Value<'a> {
170 arena.alloc(Value::NativeFn {
171 name: name.to_string(),
172 arity,
173 func,
174 })
175 }
176
177 pub fn transformer(
178 arena: &'a Bump,
179 pattern: &std::boxed::Box<Ast>,
180 update: &std::boxed::Box<Ast>,
181 delete: &Option<std::boxed::Box<Ast>>,
182 ) -> &'a mut Value<'a> {
183 arena.alloc(Value::Transformer {
184 pattern: pattern.clone(),
185 update: update.clone(),
186 delete: delete.clone(),
187 })
188 }
189
190 pub fn range(arena: &'a Bump, start: isize, end: isize) -> &'a mut Value<'a> {
191 arena.alloc(Value::Range(Range::new(arena, start, end)))
192 }
193
194 pub fn range_from(arena: &'a Bump, range: &'a Range) -> &'a mut Value<'a> {
195 arena.alloc(Value::Range(range.clone()))
196 }
197
198 pub fn is_undefined(&self) -> bool {
199 matches!(*self, Value::Undefined)
200 }
201
202 pub fn is_null(&self) -> bool {
203 matches!(*self, Value::Null)
204 }
205
206 pub fn is_bool(&self) -> bool {
207 matches!(&self, Value::Bool(..))
208 }
209
210 pub fn is_number(&self) -> bool {
211 matches!(&self, Value::Number(..))
212 }
213
214 pub fn is_integer(&self) -> bool {
215 match self {
216 Value::Number(n) => match n.classify() {
217 std::num::FpCategory::Nan
218 | std::num::FpCategory::Infinite
219 | std::num::FpCategory::Subnormal => false,
220 _ => {
221 let mantissa = n.trunc();
222 n - mantissa == 0.0
223 }
224 },
225 _ => false,
226 }
227 }
228
229 pub fn is_array_of_valid_numbers(&self) -> Result<bool> {
230 match self {
231 Value::Array(ref a, _) => {
232 for member in a.iter() {
233 if !member.is_valid_number()? {
234 return Ok(false);
235 }
236 }
237 Ok(true)
238 }
239 _ => Ok(false),
240 }
241 }
242
243 pub fn is_array_of_strings(&self) -> bool {
244 match self {
245 Value::Array(ref a, _) => {
246 for member in a.iter() {
247 if !member.is_string() {
248 return false;
249 }
250 }
251 true
252 }
253 _ => false,
254 }
255 }
256
257 pub fn is_valid_number(&self) -> Result<bool> {
258 match self {
259 Value::Number(n) => {
260 if n.is_nan() {
261 Ok(false)
262 } else if n.is_infinite() {
263 Err(Error::D1001NumberOfOutRange(*n))
264 } else {
265 Ok(true)
266 }
267 }
268 _ => Ok(false),
269 }
270 }
271
272 pub fn is_nan(&self) -> bool {
273 matches!(*self, Value::Number(n) if n.is_nan())
274 }
275
276 pub fn is_finite(&self) -> bool {
277 match self {
278 Value::Number(n) => n.is_finite(),
279 _ => false,
280 }
281 }
282
283 pub fn is_string(&self) -> bool {
284 matches!(*self, Value::String(..))
285 }
286
287 pub fn is_array(&self) -> bool {
288 matches!(*self, Value::Array(..) | Value::Range(..))
289 }
290
291 pub fn is_object(&self) -> bool {
292 matches!(*self, Value::Object(..))
293 }
294
295 pub fn is_function(&self) -> bool {
296 matches!(
297 *self,
298 Value::Lambda { .. } | Value::NativeFn { .. } | Value::Transformer { .. }
299 )
300 }
301
302 pub fn is_truthy(&'a self) -> bool {
303 match *self {
304 Value::Undefined => false,
305 Value::Null => false,
306 Value::Number(n) => n != 0.0,
307 Value::Bool(ref b) => *b,
308 Value::String(ref s) => !s.is_empty(),
309 Value::Array(ref a, _) => match a.len() {
310 0 => false,
311 1 => self.get_member(0).is_truthy(),
312 _ => {
313 for item in self.members() {
314 if item.is_truthy() {
315 return true;
316 }
317 }
318 false
319 }
320 },
321 Value::Object(ref o) => !o.is_empty(),
322 Value::Regex(_) => true, Value::Lambda { .. } | Value::NativeFn { .. } | Value::Transformer { .. } => false,
324 Value::Range(ref r) => !r.is_empty(),
325 }
326 }
327
328 pub fn get_member(&self, index: usize) -> &'a Value<'a> {
329 match *self {
330 Value::Array(ref array, _) => {
331 array.get(index).copied().unwrap_or_else(Value::undefined)
332 }
333 Value::Range(ref range) => range.nth(index).unwrap_or_else(Value::undefined),
334 _ => panic!("Not an array"),
335 }
336 }
337
338 pub fn members(&'a self) -> MemberIterator<'a> {
339 match self {
340 Value::Array(..) | Value::Range(..) => MemberIterator::new(self),
341 _ => panic!("Not an array"),
342 }
343 }
344
345 pub fn entries(&self) -> hashbrown::hash_map::Iter<'_, BumpString<'a>, &'a Value> {
346 match self {
347 Value::Object(map) => map.iter(),
348 _ => panic!("Not an object"),
349 }
350 }
351
352 pub fn arity(&self) -> usize {
353 match *self {
354 Value::Lambda { ref ast, .. } => {
355 if let AstKind::Lambda { ref args, .. } = ast.kind {
356 args.len()
357 } else {
358 panic!("Not a lambda function")
359 }
360 }
361 Value::NativeFn { arity, .. } => arity,
362 Value::Transformer { .. } => 1,
363 _ => panic!("Not a function"),
364 }
365 }
366
367 pub fn as_bool(&self) -> bool {
368 match *self {
369 Value::Bool(ref b) => *b,
370 _ => panic!("Not a bool"),
371 }
372 }
373
374 pub fn as_f64(&self) -> f64 {
375 match *self {
376 Value::Number(n) => n,
377 _ => panic!("Not a number"),
378 }
379 }
380
381 pub fn as_usize(&self) -> usize {
383 match *self {
384 Value::Number(n) => n as usize,
385 _ => panic!("Not a number"),
386 }
387 }
388
389 pub fn as_isize(&self) -> isize {
391 match *self {
392 Value::Number(n) => n as isize,
393 _ => panic!("Not a number"),
394 }
395 }
396
397 pub fn as_str(&self) -> Cow<'_, str> {
398 match *self {
399 Value::String(ref s) => Cow::from(s.as_str()),
400 _ => panic!("Not a string"),
401 }
402 }
403
404 pub fn len(&self) -> usize {
405 match *self {
406 Value::Array(ref array, _) => array.len(),
407 Value::Range(ref range) => range.len(),
408 _ => panic!("Not an array"),
409 }
410 }
411
412 pub fn is_empty(&self) -> bool {
413 match *self {
414 Value::Array(ref array, _) => array.is_empty(),
415 Value::Range(ref range) => range.is_empty(),
416 _ => panic!("Not an array"),
417 }
418 }
419
420 pub fn get_entry(&self, key: &str) -> &'a Value<'a> {
421 match *self {
422 Value::Object(ref map) => match map.get(key) {
423 Some(value) => value,
424 None => Value::undefined(),
425 },
426 _ => panic!("Not an object"),
427 }
428 }
429
430 pub fn remove_entry(&mut self, key: &str) {
431 match *self {
432 Value::Object(ref mut map) => map.remove(key),
433 _ => panic!("Not an object"),
434 };
435 }
436
437 pub fn push(&mut self, value: &'a Value<'a>) {
438 match *self {
439 Value::Array(ref mut array, _) => array.push(value),
440 _ => panic!("Not an array"),
441 }
442 }
443
444 pub fn insert(&mut self, key: &str, value: &'a Value<'a>) {
445 match *self {
446 Value::Object(ref mut map) => {
447 map.insert(BumpString::from_str_in(key, map.allocator()), value);
448 }
449 _ => panic!("Not an object"),
450 }
451 }
452
453 pub fn remove(&mut self, key: &str) {
454 match *self {
455 Value::Object(ref mut map) => map.remove(key),
456 _ => panic!("Not an object"),
457 };
458 }
459
460 pub fn flatten(&'a self, arena: &'a Bump) -> &'a mut Value<'a> {
461 let flattened = Self::array(arena, ArrayFlags::empty());
462 self._flatten(flattened)
463 }
464
465 fn _flatten(&'a self, flattened: &'a mut Value<'a>) -> &'a mut Value<'a> {
466 let mut flattened = flattened;
467
468 if self.is_array() {
469 for member in self.members() {
470 flattened = member._flatten(flattened);
471 }
472 } else {
473 flattened.push(self)
474 }
475
476 flattened
477 }
478
479 pub fn wrap_in_array(
480 arena: &'a Bump,
481 value: &'a Value<'a>,
482 flags: ArrayFlags,
483 ) -> &'a mut Value<'a> {
484 arena.alloc(Value::Array(bumpalo::vec![in arena; value], flags))
485 }
486
487 pub fn wrap_in_array_if_needed(
488 arena: &'a Bump,
489 value: &'a Value<'a>,
490 flags: ArrayFlags,
491 ) -> &'a Value<'a> {
492 if value.is_array() {
493 value
494 } else {
495 Value::wrap_in_array(arena, value, flags)
496 }
497 }
498
499 pub fn get_flags(&self) -> ArrayFlags {
500 match self {
501 Value::Array(_, flags) => *flags,
502 _ => panic!("Not an array"),
503 }
504 }
505
506 pub fn has_flags(&self, check_flags: ArrayFlags) -> bool {
507 match self {
508 Value::Array(_, flags) => flags.contains(check_flags),
509 _ => false,
510 }
511 }
512
513 pub fn clone(&'a self, arena: &'a Bump) -> &'a mut Value<'a> {
514 match self {
515 Self::Undefined => arena.alloc(Value::Undefined),
516 Self::Null => Value::null(arena),
517 Self::Number(n) => Value::number(arena, *n),
518 Self::Bool(b) => arena.alloc(Value::Bool(*b)),
519 Self::String(s) => arena.alloc(Value::String(s.clone())),
520 Self::Array(a, f) => Value::array_from(arena, a.clone(), *f),
521 Self::Object(o) => Value::object_from(o, arena),
522 Self::Lambda { ast, input, frame } => Value::lambda(arena, ast, input, frame.clone()),
523 Self::NativeFn { name, arity, func } => Value::nativefn(arena, name, *arity, *func),
524 Self::Transformer {
525 pattern,
526 update,
527 delete,
528 } => Value::transformer(arena, pattern, update, delete),
529 Self::Range(range) => Value::range_from(arena, range),
530 Self::Regex(regex) => arena.alloc(Value::Regex(regex.clone())),
531 }
532 }
533
534 pub fn clone_array_with_flags(&self, arena: &'a Bump, flags: ArrayFlags) -> &'a mut Value<'a> {
535 match *self {
536 Value::Array(ref array, _) => arena.alloc(Value::Array(array.clone(), flags)),
537 _ => panic!("Not an array"),
538 }
539 }
540
541 pub fn serialize(&'a self, pretty: bool) -> String {
542 if pretty {
543 let serializer = Serializer::new(PrettyFormatter::default(), false);
544 serializer.serialize(self).expect("Shouldn't fail")
545 } else {
546 let serializer = Serializer::new(DumpFormatter, false);
547 serializer.serialize(self).expect("Shouldn't fail")
548 }
549 }
550
551 #[allow(invalid_reference_casting)]
560 pub fn __very_unsafe_make_mut(&'a self) -> &'a mut Value<'a> {
561 unsafe {
562 let const_ptr = self as *const Value<'a>;
563 let mut_ptr = const_ptr as *mut Value<'a>;
564 &mut *mut_ptr
565 }
566 }
567}