regorus/value.rs
1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4#![allow(
5 clippy::indexing_slicing,
6 clippy::shadow_unrelated,
7 clippy::option_if_let_else,
8 clippy::semicolon_if_nothing_returned,
9 clippy::pattern_type_mismatch,
10 clippy::unused_trait_names,
11 clippy::as_conversions
12)] // value helpers index paths directly for performance
13
14use crate::number::Number;
15
16use alloc::collections::{BTreeMap, BTreeSet};
17use alloc::vec::Vec;
18use core::fmt;
19use core::ops;
20
21use core::convert::AsRef;
22use core::str::FromStr;
23
24use anyhow::{anyhow, bail, Result};
25use serde::de::{self, Deserializer, Error as DeError, MapAccess, SeqAccess, Visitor};
26use serde::ser::{SerializeMap, Serializer};
27use serde::{Deserialize, Serialize};
28
29use crate::*;
30
31/// A value in a Rego document.
32///
33/// Value is similar to a [`serde_json::value::Value`], but has the following additional
34/// capabilities:
35/// - [`Value::Set`] variant to represent sets.
36/// - [`Value::Undefined`] variant to represent absence of value.
37// - [`Value::Object`] keys can be other values, not just strings.
38/// - [`Value::Number`] has at least 100 digits of precision for computations.
39///
40/// Value can be efficiently cloned due to the use of reference counting.
41#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
42pub enum Value {
43 /// JSON null.
44 Null,
45
46 /// JSON boolean.
47 Bool(bool),
48
49 /// JSON number.
50 /// At least 100 digits of precision.
51 Number(Number),
52
53 /// JSON string.
54 String(Rc<str>),
55
56 /// JSON array.
57 Array(Rc<Vec<Value>>),
58
59 /// A set of values.
60 /// No JSON equivalent.
61 /// Sets are serialized as arrays in JSON.
62 Set(Rc<BTreeSet<Value>>),
63
64 /// An object.
65 /// Unlike JSON, keys can be any value, not just string.
66 Object(Rc<BTreeMap<Value, Value>>),
67
68 /// Undefined value.
69 /// Used to indicate the absence of a value.
70 Undefined,
71}
72
73#[inline]
74fn enforce_limit_anyhow() -> Result<()> {
75 crate::utils::limits::check_memory_limit_if_needed().map_err(|err| anyhow!(err))
76}
77
78#[inline]
79fn enforce_limit_for<E: DeError>() -> core::result::Result<(), E> {
80 crate::utils::limits::check_memory_limit_if_needed().map_err(|err| E::custom(err.to_string()))
81}
82
83#[doc(hidden)]
84impl Serialize for Value {
85 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
86 where
87 S: Serializer,
88 {
89 use serde::ser::Error;
90 match self {
91 Value::Null => serializer.serialize_unit(),
92 Value::Bool(b) => serializer.serialize_bool(*b),
93 Value::String(s) => serializer.serialize_str(s.as_ref()),
94 Value::Number(n) => n.serialize(serializer),
95 Value::Array(a) => a.serialize(serializer),
96 Value::Object(fields) => {
97 let mut map = serializer.serialize_map(Some(fields.len()))?;
98 for (k, v) in fields.iter() {
99 match k {
100 Value::String(_) => map.serialize_entry(k, v)?,
101 _ => {
102 let key_str = serde_json::to_string(k).map_err(Error::custom)?;
103 map.serialize_entry(&key_str, v)?
104 }
105 }
106 }
107 map.end()
108 }
109
110 // display set as an array
111 Value::Set(s) => s.serialize(serializer),
112
113 // display undefined as a special string
114 Value::Undefined => serializer.serialize_str("<undefined>"),
115 }
116 }
117}
118
119struct ValueVisitor;
120
121impl<'de> Visitor<'de> for ValueVisitor {
122 type Value = Value;
123
124 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
125 formatter.write_str("a value")
126 }
127
128 fn visit_unit<E>(self) -> Result<Self::Value, E>
129 where
130 E: de::Error,
131 {
132 Ok(Value::Null)
133 }
134
135 fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
136 where
137 E: de::Error,
138 {
139 Ok(Value::Bool(v))
140 }
141
142 fn visit_none<E>(self) -> Result<Self::Value, E>
143 where
144 E: de::Error,
145 {
146 Ok(Value::Null)
147 }
148
149 fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
150 where
151 D: Deserializer<'de>,
152 {
153 Value::deserialize(deserializer)
154 }
155
156 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
157 where
158 E: de::Error,
159 {
160 Ok(Value::from(v))
161 }
162
163 fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
164 where
165 E: de::Error,
166 {
167 Ok(Value::from(v))
168 }
169
170 fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
171 where
172 E: de::Error,
173 {
174 Ok(Value::from(v))
175 }
176
177 fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
178 where
179 E: de::Error,
180 {
181 Ok(Value::from(v))
182 }
183
184 fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
185 where
186 E: de::Error,
187 {
188 Ok(Value::from(Number::from(v)))
189 }
190
191 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
192 where
193 E: de::Error,
194 {
195 Ok(Value::String(s.to_string().into()))
196 }
197
198 fn visit_string<E>(self, s: String) -> Result<Self::Value, E>
199 where
200 E: de::Error,
201 {
202 Ok(Value::String(s.into()))
203 }
204
205 fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
206 where
207 V: SeqAccess<'de>,
208 {
209 let mut arr = vec![];
210 while let Some(v) = visitor.next_element()? {
211 arr.push(v);
212 // Enforce allocator limit while expanding a deserialized array.
213 enforce_limit_for::<V::Error>()?;
214 }
215 Ok(Value::from(arr))
216 }
217
218 fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
219 where
220 V: MapAccess<'de>,
221 {
222 if let Some((key, value)) = visitor.next_entry()? {
223 if let (Value::String(k), Value::String(v)) = (&key, &value) {
224 if k.as_ref() == "$serde_json::private::Number" {
225 match Number::from_str(v) {
226 Ok(n) => return Ok(Value::from(n)),
227 _ => return Err(de::Error::custom("failed to read big number")),
228 }
229 }
230 }
231 let mut map = BTreeMap::new();
232 map.insert(key, value);
233 // Enforce allocator limit while expanding a deserialized object.
234 enforce_limit_for::<V::Error>()?;
235 while let Some((key, value)) = visitor.next_entry()? {
236 map.insert(key, value);
237 // Enforce allocator limit while expanding a deserialized object.
238 enforce_limit_for::<V::Error>()?;
239 }
240 Ok(Value::from(map))
241 } else {
242 Ok(Value::new_object())
243 }
244 }
245}
246
247#[doc(hidden)]
248impl<'de> Deserialize<'de> for Value {
249 fn deserialize<D>(deserializer: D) -> Result<Value, D::Error>
250 where
251 D: Deserializer<'de>,
252 {
253 deserializer.deserialize_any(ValueVisitor)
254 }
255}
256
257impl fmt::Display for Value {
258 /// Display a value.
259 ///
260 /// A value is displayed by serializing it to JSON using serde_json::to_string.
261 ///
262 /// ```
263 /// # use regorus::*;
264 /// # fn main() -> anyhow::Result<()> {
265 /// let v = Value::from("hello");
266 /// assert_eq!(format!("{v}"), "\"hello\"");
267 /// # Ok(())
268 /// # }
269 /// ```
270 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
271 match serde_json::to_string(self) {
272 Ok(s) => write!(f, "{s}"),
273 Err(_e) => Err(fmt::Error),
274 }
275 }
276}
277
278impl Value {
279 /// Create an empty [`Value::Array`]
280 ///
281 /// ```
282 /// # use regorus::*;
283 /// # fn main() -> anyhow::Result<()> {
284 /// let obj = Value::new_array();
285 /// assert_eq!(obj.as_array().expect("not an array").len(), 0);
286 /// # Ok(())
287 /// # }
288 /// ```
289 pub fn new_array() -> Value {
290 Value::from(vec![])
291 }
292
293 /// Create an empty [`Value::Object`]
294 ///
295 /// ```
296 /// # use regorus::*;
297 /// # fn main() -> anyhow::Result<()> {
298 /// let obj = Value::new_object();
299 /// assert_eq!(obj.as_object().expect("not an object").len(), 0);
300 /// # Ok(())
301 /// # }
302 /// ```
303 pub fn new_object() -> Value {
304 Value::from(BTreeMap::new())
305 }
306
307 /// Create an empty [`Value::Set`]
308 ///
309 /// ```
310 /// # use regorus::*;
311 /// # fn main() -> anyhow::Result<()> {
312 /// let obj = Value::new_set();
313 /// assert_eq!(obj.as_set().expect("not a set").len(), 0);
314 /// # Ok(())
315 /// # }
316 /// ```
317 pub fn new_set() -> Value {
318 Value::from(BTreeSet::new())
319 }
320}
321
322impl Value {
323 /// Deserialize a [`Value`] from JSON.
324 /// ```
325 /// # use regorus::*;
326 /// # fn main() -> anyhow::Result<()> {
327 /// let json = r#"
328 /// [
329 /// null, true, false,
330 /// "hello", 12345,
331 /// { "name" : "regorus" }
332 /// ]"#;
333 ///
334 /// // Deserialize json.
335 /// let value = Value::from_json_str(json)?;
336 ///
337 /// // Assert outer array.
338 /// let array = value.as_array().expect("not an array");
339 ///
340 /// // Assert elements.
341 /// assert_eq!(array[0], Value::Null);
342 /// assert_eq!(array[1], Value::from(true));
343 /// assert_eq!(array[2], Value::from(false));
344 /// assert_eq!(array[3], Value::from("hello"));
345 /// assert_eq!(array[4], Value::from(12345u64));
346 /// let obj = array[5].as_object().expect("not an object");
347 /// assert_eq!(obj.len(), 1);
348 /// assert_eq!(obj[&Value::from("name")], Value::from("regorus"));
349 /// # Ok(())
350 /// # }
351 /// ```
352 pub fn from_json_str(json: &str) -> Result<Value> {
353 match serde_json::from_str::<Value>(json) {
354 Ok(value) => Ok(value),
355 Err(err) => {
356 #[cfg(feature = "allocator-memory-limits")]
357 {
358 // Re-validate allocator limits when serde parsing fails to surface LimitError.
359 match crate::utils::limits::check_global_memory_limit() {
360 Err(limit_err) => Err(anyhow!(limit_err)),
361 Ok(_) => Err(anyhow!(err)),
362 }
363 }
364
365 #[cfg(not(feature = "allocator-memory-limits"))]
366 {
367 Err(anyhow!(err))
368 }
369 }
370 }
371 }
372
373 /// Deserialize a [`Value`] from a file containing JSON.
374 ///
375 /// ```
376 /// # use regorus::*;
377 /// # fn main() -> anyhow::Result<()> {
378 /// let value = Value::from_json_file("tests/aci/input.json")?;
379 ///
380 /// // Convert the value back to json.
381 /// let json_str = value.to_json_str()?;
382 ///
383 /// assert_eq!(json_str.trim(),
384 /// std::fs::read_to_string("tests/aci/input.json")?.trim().replace("\r\n", "\n"));
385 /// # Ok(())
386 /// # }
387 /// ```
388 #[cfg(feature = "std")]
389 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
390 pub fn from_json_file<P: AsRef<std::path::Path>>(path: P) -> Result<Value> {
391 match std::fs::read_to_string(&path) {
392 Ok(c) => Self::from_json_str(c.as_str()),
393 Err(e) => bail!("Failed to read {}. {e}", path.as_ref().display()),
394 }
395 }
396
397 /// Serialize a value to JSON.
398 ///
399 /// ```
400 /// # use regorus::*;
401 /// # fn main() -> anyhow::Result<()> {
402 /// let value = Value::from_json_file("tests/aci/input.json")?;
403 ///
404 /// // Convert the value back to json.
405 /// let json_str = value.to_json_str()?;
406 ///
407 /// assert_eq!(json_str.trim(),
408 /// std::fs::read_to_string("tests/aci/input.json")?.trim().replace("\r\n", "\n"));
409 /// # Ok(())
410 /// # }
411 /// ```
412 ///
413 /// Sets are serialized as arrays.
414 /// ```
415 /// # use regorus::*;
416 /// # use std::collections::BTreeSet;
417 /// # fn main() -> anyhow::Result<()> {
418 /// let mut set = BTreeSet::new();
419 /// set.insert(Value::from("Hello"));
420 /// set.insert(Value::from(1u64));
421 ///
422 /// let set_value = Value::from(set);
423 ///
424 /// assert_eq!(
425 /// set_value.to_json_str()?,
426 /// r#"
427 ///[
428 /// 1,
429 /// "Hello"
430 ///]"#.trim());
431 /// # Ok(())
432 /// # }
433 /// ```
434 ///
435 /// Non string keys of objects are serialized to json first and the serialized string representation
436 /// is emitted as the key.
437 /// ```
438 /// # use regorus::*;
439 /// # use std::collections::BTreeMap;
440 /// # fn main() -> anyhow::Result<()> {
441 /// let mut obj = BTreeMap::new();
442 /// obj.insert(Value::from("Hello"), Value::from("World"));
443 /// obj.insert(Value::from([Value::from(1u64)].to_vec()), Value::Null);
444 ///
445 /// let obj_value = Value::from(obj);
446 ///
447 /// assert_eq!(
448 /// obj_value.to_json_str()?,
449 /// r#"
450 ///{
451 /// "Hello": "World",
452 /// "[1]": null
453 ///}"#.trim());
454 /// # Ok(())
455 /// # }
456 /// ```
457 pub fn to_json_str(&self) -> Result<String> {
458 serde_json::to_string_pretty(self).map_err(anyhow::Error::msg)
459 }
460
461 /// Deserialize a value from YAML.
462 /// Note: Deserialization from YAML does not support arbitrary precision numbers.
463 #[cfg(feature = "yaml")]
464 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
465 pub fn from_yaml_str(yaml: &str) -> Result<Value> {
466 let value = serde_yaml::from_str(yaml)
467 .map_err(|err| anyhow::anyhow!("Failed to parse YAML: {}", err))?;
468 Ok(value)
469 }
470
471 /// Deserialize a value from a file containing YAML.
472 /// Note: Deserialization from YAML does not support arbitrary precision numbers.
473 #[cfg(feature = "std")]
474 #[cfg(feature = "yaml")]
475 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
476 #[cfg_attr(docsrs, doc(cfg(feature = "yaml")))]
477 pub fn from_yaml_file(path: &String) -> Result<Value> {
478 match std::fs::read_to_string(path) {
479 Ok(c) => Self::from_yaml_str(c.as_str()),
480 Err(e) => bail!("Failed to read {path}. {e}"),
481 }
482 }
483}
484
485impl From<bool> for Value {
486 /// Create a [`Value::Bool`] from `bool`.
487 /// ```
488 /// # use regorus::*;
489 /// # use std::collections::BTreeSet;
490 /// # fn main() -> anyhow::Result<()> {
491 /// assert_eq!(Value::from(true), Value::Bool(true));
492 /// # Ok(())
493 /// # }
494 fn from(b: bool) -> Self {
495 Value::Bool(b)
496 }
497}
498
499impl From<String> for Value {
500 /// Create a [`Value::String`] from `string`.
501 /// ```
502 /// # use regorus::*;
503 /// # fn main() -> anyhow::Result<()> {
504 /// assert_eq!(Value::from("Hello".to_string()), Value::String("Hello".into()));
505 /// # Ok(())
506 /// # }
507 fn from(s: String) -> Self {
508 Value::String(s.into())
509 }
510}
511
512impl From<&str> for Value {
513 /// Create a [`Value::String`] from `&str`.
514 /// ```
515 /// # use regorus::*;
516 /// # fn main() -> anyhow::Result<()> {
517 /// assert_eq!(Value::from("Hello"), Value::String("Hello".into()));
518 /// # Ok(())
519 /// # }
520 fn from(s: &str) -> Self {
521 Value::String(s.into())
522 }
523}
524
525impl From<u128> for Value {
526 /// Create a [`Value::Number`] from `u128`.
527 /// ```
528 /// # use regorus::*;
529 /// # fn main() -> anyhow::Result<()> {
530 /// assert_eq!(
531 /// Value::from(340_282_366_920_938_463_463_374_607_431_768_211_455u128).as_u128()?,
532 /// 340_282_366_920_938_463_463_374_607_431_768_211_455u128);
533 /// # Ok(())
534 /// # }
535 fn from(n: u128) -> Self {
536 Value::Number(Number::from(n))
537 }
538}
539
540impl From<i128> for Value {
541 /// Create a [`Value::Number`] from `i128`.
542 /// ```
543 /// # use regorus::*;
544 /// # fn main() -> anyhow::Result<()> {
545 /// assert_eq!(
546 /// Value::from(-170141183460469231731687303715884105728i128).as_i128()?,
547 /// -170141183460469231731687303715884105728i128);
548 /// # Ok(())
549 /// # }
550 fn from(n: i128) -> Self {
551 Value::Number(Number::from(n))
552 }
553}
554
555impl From<u64> for Value {
556 /// Create a [`Value::Number`] from `u64`.
557 /// ```
558 /// # use regorus::*;
559 /// # fn main() -> anyhow::Result<()> {
560 /// assert_eq!(
561 /// Value::from(0u64),
562 /// Value::from_json_str("0")?);
563 /// # Ok(())
564 /// # }
565 fn from(n: u64) -> Self {
566 Value::Number(Number::from(n))
567 }
568}
569
570impl From<i64> for Value {
571 /// Create a [`Value::Number`] from `i64`.
572 /// ```
573 /// # use regorus::*;
574 /// # fn main() -> anyhow::Result<()> {
575 /// assert_eq!(
576 /// Value::from(0i64),
577 /// Value::from_json_str("0")?);
578 /// # Ok(())
579 /// # }
580 fn from(n: i64) -> Self {
581 Value::Number(Number::from(n))
582 }
583}
584
585impl From<u32> for Value {
586 /// Create a [`Value::Number`] from `u32`.
587 /// ```
588 /// # use regorus::*;
589 /// # fn main() -> anyhow::Result<()> {
590 /// assert_eq!(
591 /// Value::from(0u32),
592 /// Value::from_json_str("0")?);
593 /// # Ok(())
594 /// # }
595 fn from(n: u32) -> Self {
596 Value::Number(Number::from(n as u64))
597 }
598}
599
600impl From<i32> for Value {
601 /// Create a [`Value::Number`] from `i32`.
602 /// ```
603 /// # use regorus::*;
604 /// # fn main() -> anyhow::Result<()> {
605 /// assert_eq!(
606 /// Value::from(0i32),
607 /// Value::from_json_str("0")?);
608 /// # Ok(())
609 /// # }
610 fn from(n: i32) -> Self {
611 Value::Number(Number::from(n as i64))
612 }
613}
614
615impl From<f64> for Value {
616 /// Create a [`Value::Number`] from `f64`.
617 /// ```
618 /// # use regorus::*;
619 /// # fn main() -> anyhow::Result<()> {
620 /// assert_eq!(
621 /// Value::from(3.5f64),
622 /// Value::from_numeric_string("3.5")?);
623 /// # Ok(())
624 /// # }
625 /// ```
626 ///
627 /// [`Value::Number`] stores floating-point values as `f64`, so it inherits the same
628 /// ~15-digit precision limit. Adding additional digits to either the literal or a parsed
629 /// numeric string causes both to round to the same `f64` value.
630 /// ```
631 /// # use regorus::*;
632 /// # fn main() -> anyhow::Result<()> {
633 /// let from_float = Value::from(3.141592653589793238462f64);
634 /// let from_string = Value::from_numeric_string("3.141592653589793238462")?;
635 /// assert_eq!(from_float, from_string);
636 ///
637 /// // All representations round to approximately 15 digits.
638 /// assert_eq!(
639 /// from_float,
640 /// Value::from_numeric_string("3.141592653589793")?);
641 /// # Ok(())
642 /// # }
643 /// ```
644 ///
645 /// If additional precision is required, keep the raw data as strings or use an external
646 /// arbitrary-precision numeric type before converting it into [`Value`].
647 fn from(n: f64) -> Self {
648 Value::Number(Number::from(n))
649 }
650}
651
652impl From<serde_json::Value> for Value {
653 /// Create a [`Value`] from [`serde_json::Value`].
654 ///
655 /// Returns [`Value::Undefined`] in case of error.
656 /// ```
657 /// # use regorus::*;
658 /// # fn main() -> anyhow::Result<()> {
659 /// let json_v = serde_json::json!({ "x":10, "y": 20 });
660 /// let v = Value::from(json_v);
661 ///
662 /// assert_eq!(v["x"].as_u64()?, 10);
663 /// assert_eq!(v["y"].as_u64()?, 20);
664 /// # Ok(())
665 /// # }
666 fn from(v: serde_json::Value) -> Self {
667 match serde_json::from_value(v) {
668 Ok(v) => v,
669 _ => Value::Undefined,
670 }
671 }
672}
673
674#[cfg(feature = "yaml")]
675#[cfg_attr(docsrs, doc(cfg(feature = "yaml")))]
676impl From<serde_yaml::Value> for Value {
677 /// Create a [`Value`] from [`serde_yaml::Value`].
678 ///
679 /// Returns [`Value::Undefined`] in case of error.
680 /// ```
681 /// # use regorus::*;
682 /// # fn main() -> anyhow::Result<()> {
683 /// let yaml = "
684 /// x: 10
685 /// y: 20
686 /// ";
687 /// let yaml_v : serde_yaml::Value = serde_yaml::from_str(&yaml).unwrap();
688 /// let v = Value::from(yaml_v);
689 ///
690 /// assert_eq!(v["x"].as_u64()?, 10);
691 /// assert_eq!(v["y"].as_u64()?, 20);
692 /// # Ok(())
693 /// # }
694 fn from(v: serde_yaml::Value) -> Self {
695 match serde_yaml::from_value(v) {
696 Ok(v) => v,
697 _ => Value::Undefined,
698 }
699 }
700}
701
702impl Value {
703 /// Create a [`Value::Number`] from a string containing numeric representation of a number.
704 ///
705 /// This is the preferred way for creating arbitrary precision numbers.
706 ///
707 /// ```
708 /// # use regorus::*;
709 /// # fn main() -> anyhow::Result<()> {
710 /// let v = Value::from_numeric_string("3.14159265358979323846264338327950288419716939937510")?;
711 ///
712 /// println!("{}", v.to_json_str()?);
713 /// // Prints 3.1415926535897932384626433832795028841971693993751 if serde_json/arbitrary_precision feature is enabled.
714 /// // Prints 3.141592653589793 if serde_json/arbitrary_precision is not enabled.
715 /// # Ok(())
716 /// # }
717 /// ```
718 pub fn from_numeric_string(s: &str) -> Result<Value> {
719 Ok(Value::Number(
720 Number::from_str(s).map_err(|_| anyhow!("not a valid numeric string"))?,
721 ))
722 }
723}
724
725impl From<usize> for Value {
726 /// Create a [`Value::Number`] from `usize`.
727 /// ```
728 /// # use regorus::*;
729 /// # fn main() -> anyhow::Result<()> {
730 /// assert_eq!(
731 /// Value::from(0usize),
732 /// Value::from_json_str("0")?);
733 /// # Ok(())
734 /// # }
735 fn from(n: usize) -> Self {
736 Value::Number(Number::from(n))
737 }
738}
739
740#[doc(hidden)]
741impl From<Number> for Value {
742 fn from(n: Number) -> Self {
743 Value::Number(n)
744 }
745}
746
747impl From<Vec<Value>> for Value {
748 /// Create a [`Value::Array`] from a [`Vec<Value>`].
749 /// ```
750 /// # use regorus::*;
751 /// # fn main() -> anyhow::Result<()> {
752 /// let strings = [ "Hello", "World" ];
753 ///
754 /// let v = Value::from(strings.iter().map(|s| Value::from(*s)).collect::<Vec<Value>>());
755 /// assert_eq!(v[0], Value::from(strings[0]));
756 /// assert_eq!(v[1], Value::from(strings[1]));
757 /// # Ok(())
758 /// # }
759 fn from(a: Vec<Value>) -> Self {
760 Value::Array(Rc::new(a))
761 }
762}
763
764impl From<BTreeSet<Value>> for Value {
765 /// Create a [`Value::Set`] from a [`BTreeSet<Value>`].
766 /// ```
767 /// # use regorus::*;
768 /// # use std::collections::BTreeSet;
769 /// # fn main() -> anyhow::Result<()> {
770 /// let strings = [ "Hello", "World" ];
771 /// let v = Value::from(strings
772 /// .iter()
773 /// .map(|s| Value::from(*s))
774 /// .collect::<BTreeSet<Value>>());
775 ///
776 /// let mut iter = v.as_set()?.iter();
777 /// assert_eq!(iter.next(), Some(&Value::from(strings[0])));
778 /// assert_eq!(iter.next(), Some(&Value::from(strings[1])));
779 /// # Ok(())
780 /// # }
781 fn from(s: BTreeSet<Value>) -> Self {
782 Value::Set(Rc::new(s))
783 }
784}
785
786impl From<BTreeMap<Value, Value>> for Value {
787 /// Create a [`Value::Object`] from a [`BTreeMap<Value>`].
788 /// ```
789 /// # use regorus::*;
790 /// # use std::collections::BTreeMap;
791 /// # fn main() -> anyhow::Result<()> {
792 /// let strings = [ ("Hello", "World") ];
793 /// let v = Value::from(strings
794 /// .iter()
795 /// .map(|(k,v)| (Value::from(*k), Value::from(*v)))
796 /// .collect::<BTreeMap<Value, Value>>());
797 ///
798 /// let mut iter = v.as_object()?.iter();
799 /// assert_eq!(iter.next(), Some((&Value::from(strings[0].0), &Value::from(strings[0].1))));
800 /// # Ok(())
801 /// # }
802 fn from(s: BTreeMap<Value, Value>) -> Self {
803 Value::Object(Rc::new(s))
804 }
805}
806
807impl Value {
808 pub(crate) fn from_array(a: Vec<Value>) -> Value {
809 Value::from(a)
810 }
811
812 pub(crate) fn from_set(s: BTreeSet<Value>) -> Value {
813 Value::from(s)
814 }
815
816 pub(crate) fn from_map(m: BTreeMap<Value, Value>) -> Value {
817 Value::from(m)
818 }
819
820 pub(crate) fn is_empty_object(&self) -> bool {
821 self == &Value::new_object()
822 }
823}
824
825impl Value {
826 /// Cast value to [`& bool`] if [`Value::Bool`].
827 /// ```
828 /// # use regorus::*;
829 /// # fn main() -> anyhow::Result<()> {
830 /// let v = Value::from(true);
831 /// assert_eq!(v.as_bool()?, &true);
832 /// # Ok(())
833 /// # }
834 pub fn as_bool(&self) -> Result<&bool> {
835 match self {
836 Value::Bool(b) => Ok(b),
837 _ => Err(anyhow!("not a bool")),
838 }
839 }
840
841 /// Cast value to [`&mut bool`] if [`Value::Bool`].
842 /// ```
843 /// # use regorus::*;
844 /// # fn main() -> anyhow::Result<()> {
845 /// let mut v = Value::from(true);
846 /// *v.as_bool_mut()? = false;
847 /// # Ok(())
848 /// # }
849 pub fn as_bool_mut(&mut self) -> Result<&mut bool> {
850 match self {
851 Value::Bool(b) => Ok(b),
852 _ => Err(anyhow!("not a bool")),
853 }
854 }
855
856 /// Cast value to [`& u128`] if [`Value::Number`].
857 ///
858 /// Error is raised if the value is not a number or if the numeric value
859 /// does not fit in a u128.
860 ///
861 /// ```
862 /// # use regorus::*;
863 /// # fn main() -> anyhow::Result<()> {
864 /// let v = Value::from(10);
865 /// assert_eq!(v.as_u128()?, 10u128);
866 ///
867 /// let v = Value::from(-10);
868 /// assert!(v.as_u128().is_err());
869 /// # Ok(())
870 /// # }
871 pub fn as_u128(&self) -> Result<u128> {
872 match self {
873 Value::Number(b) => {
874 if let Some(n) = b.as_u128() {
875 return Ok(n);
876 }
877 bail!("not a u128");
878 }
879 _ => Err(anyhow!("not a u128")),
880 }
881 }
882
883 /// Cast value to [`& i128`] if [`Value::Number`].
884 ///
885 /// Error is raised if the value is not a number or if the numeric value
886 /// does not fit in a i128.
887 ///
888 /// ```
889 /// # use regorus::*;
890 /// # fn main() -> anyhow::Result<()> {
891 /// let v = Value::from(-10);
892 /// assert_eq!(v.as_i128()?, -10i128);
893 ///
894 /// let v = Value::from_numeric_string("11111111111111111111111111111111111111111111111111")?;
895 /// assert!(v.as_i128().is_err());
896 /// # Ok(())
897 /// # }
898 pub fn as_i128(&self) -> Result<i128> {
899 match self {
900 Value::Number(b) => {
901 if let Some(n) = b.as_i128() {
902 return Ok(n);
903 }
904 bail!("not a i128");
905 }
906 _ => Err(anyhow!("not a i128")),
907 }
908 }
909
910 /// Cast value to [`& u64`] if [`Value::Number`].
911 ///
912 /// Error is raised if the value is not a number or if the numeric value
913 /// does not fit in a u64.
914 ///
915 /// ```
916 /// # use regorus::*;
917 /// # fn main() -> anyhow::Result<()> {
918 /// let v = Value::from(10);
919 /// assert_eq!(v.as_u64()?, 10u64);
920 ///
921 /// let v = Value::from(-10);
922 /// assert!(v.as_u64().is_err());
923 /// # Ok(())
924 /// # }
925 pub fn as_u64(&self) -> Result<u64> {
926 match self {
927 Value::Number(b) => {
928 if let Some(n) = b.as_u64() {
929 return Ok(n);
930 }
931 bail!("not a u64");
932 }
933 _ => Err(anyhow!("not a u64")),
934 }
935 }
936
937 /// Cast value to [`& i64`] if [`Value::Number`].
938 ///
939 /// Error is raised if the value is not a number or if the numeric value
940 /// does not fit in a i64.
941 ///
942 /// ```
943 /// # use regorus::*;
944 /// # fn main() -> anyhow::Result<()> {
945 /// let v = Value::from(-10);
946 /// assert_eq!(v.as_i64()?, -10i64);
947 ///
948 /// let v = Value::from(340_282_366_920_938_463_463_374_607_431_768_211_455u128);
949 /// assert!(v.as_i64().is_err());
950 /// # Ok(())
951 /// # }
952 pub fn as_i64(&self) -> Result<i64> {
953 match self {
954 Value::Number(b) => {
955 if let Some(n) = b.as_i64() {
956 return Ok(n);
957 }
958 bail!("not an i64");
959 }
960 _ => Err(anyhow!("not an i64")),
961 }
962 }
963
964 /// Cast value to [`& u32`] if [`Value::Number`].
965 ///
966 /// Error is raised if the value is not a number or if the numeric value
967 /// does not fit in a u32.
968 ///
969 /// ```
970 /// # use regorus::*;
971 /// # fn main() -> anyhow::Result<()> {
972 /// let v = Value::from(10);
973 /// assert_eq!(v.as_u32()?, 10u32);
974 ///
975 /// let v = Value::from(-10);
976 /// assert!(v.as_u32().is_err());
977 /// # Ok(())
978 /// # }
979 pub fn as_u32(&self) -> Result<u32> {
980 match self {
981 Value::Number(b) => {
982 if let Some(n) = b.as_u64() {
983 if let Ok(v) = u32::try_from(n) {
984 return Ok(v);
985 }
986 }
987 bail!("not a u32");
988 }
989 _ => Err(anyhow!("not a u32")),
990 }
991 }
992
993 /// Cast value to [`& i32`] if [`Value::Number`].
994 ///
995 /// Error is raised if the value is not a number or if the numeric value
996 /// does not fit in a i32.
997 ///
998 /// ```
999 /// # use regorus::*;
1000 /// # fn main() -> anyhow::Result<()> {
1001 /// let v = Value::from(-10);
1002 /// assert_eq!(v.as_i32()?, -10i32);
1003 ///
1004 /// let v = Value::from(2_147_483_648i64);
1005 /// assert!(v.as_i32().is_err());
1006 /// # Ok(())
1007 /// # }
1008 pub fn as_i32(&self) -> Result<i32> {
1009 match self {
1010 Value::Number(b) => {
1011 if let Some(n) = b.as_i64() {
1012 if let Ok(v) = i32::try_from(n) {
1013 return Ok(v);
1014 }
1015 }
1016 bail!("not an i32");
1017 }
1018 _ => Err(anyhow!("not an i32")),
1019 }
1020 }
1021
1022 /// Cast value to [`& u16`] if [`Value::Number`].
1023 ///
1024 /// Error is raised if the value is not a number or if the numeric value
1025 /// does not fit in a u16.
1026 ///
1027 /// ```
1028 /// # use regorus::*;
1029 /// # fn main() -> anyhow::Result<()> {
1030 /// let v = Value::from(10);
1031 /// assert_eq!(v.as_u16()?, 10u16);
1032 ///
1033 /// let v = Value::from(-10);
1034 /// assert!(v.as_u16().is_err());
1035 /// # Ok(())
1036 /// # }
1037 pub fn as_u16(&self) -> Result<u16> {
1038 match self {
1039 Value::Number(b) => {
1040 if let Some(n) = b.as_u64() {
1041 if let Ok(v) = u16::try_from(n) {
1042 return Ok(v);
1043 }
1044 }
1045 bail!("not a u16");
1046 }
1047 _ => Err(anyhow!("not a u16")),
1048 }
1049 }
1050
1051 /// Cast value to [`& i16`] if [`Value::Number`].
1052 ///
1053 /// Error is raised if the value is not a number or if the numeric value
1054 /// does not fit in a i16.
1055 ///
1056 /// ```
1057 /// # use regorus::*;
1058 /// # fn main() -> anyhow::Result<()> {
1059 /// let v = Value::from(-10);
1060 /// assert_eq!(v.as_i16()?, -10i16);
1061 ///
1062 /// let v = Value::from(32768i64);
1063 /// assert!(v.as_i16().is_err());
1064 /// # Ok(())
1065 /// # }
1066 pub fn as_i16(&self) -> Result<i16> {
1067 match self {
1068 Value::Number(b) => {
1069 if let Some(n) = b.as_i64() {
1070 if let Ok(v) = i16::try_from(n) {
1071 return Ok(v);
1072 }
1073 }
1074 bail!("not an i16");
1075 }
1076 _ => Err(anyhow!("not an i16")),
1077 }
1078 }
1079
1080 /// Cast value to [`& u8`] if [`Value::Number`].
1081 ///
1082 /// Error is raised if the value is not a number or if the numeric value
1083 /// does not fit in a u8.
1084 ///
1085 /// ```
1086 /// # use regorus::*;
1087 /// # fn main() -> anyhow::Result<()> {
1088 /// let v = Value::from(10);
1089 /// assert_eq!(v.as_u8()?, 10u8);
1090 ///
1091 /// let v = Value::from(-10);
1092 /// assert!(v.as_u8().is_err());
1093 /// # Ok(())
1094 /// # }
1095 pub fn as_u8(&self) -> Result<u8> {
1096 match self {
1097 Value::Number(b) => {
1098 if let Some(n) = b.as_u64() {
1099 if let Ok(v) = u8::try_from(n) {
1100 return Ok(v);
1101 }
1102 }
1103 bail!("not a u8");
1104 }
1105 _ => Err(anyhow!("not a u8")),
1106 }
1107 }
1108
1109 /// Cast value to [`& i8`] if [`Value::Number`].
1110 ///
1111 /// Error is raised if the value is not a number or if the numeric value
1112 /// does not fit in a i8.
1113 ///
1114 /// ```
1115 /// # use regorus::*;
1116 /// # fn main() -> anyhow::Result<()> {
1117 /// let v = Value::from(-10);
1118 /// assert_eq!(v.as_i8()?, -10i8);
1119 ///
1120 /// let v = Value::from(128);
1121 /// assert!(v.as_i8().is_err());
1122 /// # Ok(())
1123 /// # }
1124 pub fn as_i8(&self) -> Result<i8> {
1125 match self {
1126 Value::Number(b) => {
1127 if let Some(n) = b.as_i64() {
1128 if let Ok(v) = i8::try_from(n) {
1129 return Ok(v);
1130 }
1131 }
1132 bail!("not an i8");
1133 }
1134 _ => Err(anyhow!("not an i8")),
1135 }
1136 }
1137
1138 /// Cast value to [`& f64`] if [`Value::Number`].
1139 /// Error is raised if the value is not a number or if the numeric value
1140 /// does not fit in a i64.
1141 ///
1142 /// ```
1143 /// # use regorus::*;
1144 /// # fn main() -> anyhow::Result<()> {
1145 /// let v = Value::from(-10);
1146 /// assert_eq!(v.as_f64()?, -10f64);
1147 ///
1148 /// let v = Value::from(340_282_366_920_938_463_463_374_607_431_768_211_455u128);
1149 /// assert!(v.as_i64().is_err());
1150 /// # Ok(())
1151 /// # }
1152 pub fn as_f64(&self) -> Result<f64> {
1153 match self {
1154 Value::Number(b) => {
1155 if let Some(n) = b.as_f64() {
1156 return Ok(n);
1157 }
1158 bail!("not a f64");
1159 }
1160 _ => Err(anyhow!("not a f64")),
1161 }
1162 }
1163
1164 /// Cast value to [`& Rc<str>`] if [`Value::String`].
1165 /// ```
1166 /// # use regorus::*;
1167 /// # fn main() -> anyhow::Result<()> {
1168 /// let v = Value::from("Hello");
1169 /// assert_eq!(v.as_string()?.as_ref(), "Hello");
1170 /// # Ok(())
1171 /// # }
1172 pub fn as_string(&self) -> Result<&Rc<str>> {
1173 match self {
1174 Value::String(s) => Ok(s),
1175 _ => Err(anyhow!("not a string")),
1176 }
1177 }
1178
1179 /// Cast value to [`&mut Rc<str>`] if [`Value::String`].
1180 /// ```
1181 /// # use regorus::*;
1182 /// # fn main() -> anyhow::Result<()> {
1183 /// let mut v = Value::from("Hello");
1184 /// *v.as_string_mut()? = "World".into();
1185 /// # Ok(())
1186 /// # }
1187 pub fn as_string_mut(&mut self) -> Result<&mut Rc<str>> {
1188 match self {
1189 Value::String(s) => Ok(s),
1190 _ => Err(anyhow!("not a string")),
1191 }
1192 }
1193
1194 #[doc(hidden)]
1195 pub fn as_number(&self) -> Result<&Number> {
1196 match self {
1197 Value::Number(n) => Ok(n),
1198 _ => Err(anyhow!("not a number")),
1199 }
1200 }
1201
1202 #[doc(hidden)]
1203 pub fn as_number_mut(&mut self) -> Result<&mut Number> {
1204 match self {
1205 Value::Number(n) => Ok(n),
1206 _ => Err(anyhow!("not a number")),
1207 }
1208 }
1209
1210 /// Cast value to [`& Vec<Value>`] if [`Value::Array`].
1211 /// ```
1212 /// # use regorus::*;
1213 /// # fn main() -> anyhow::Result<()> {
1214 /// let v = Value::from([Value::from("Hello")].to_vec());
1215 /// assert_eq!(v.as_array()?[0], Value::from("Hello"));
1216 /// # Ok(())
1217 /// # }
1218 pub fn as_array(&self) -> Result<&Vec<Value>> {
1219 match self {
1220 Value::Array(a) => Ok(a),
1221 _ => Err(anyhow!("not an array")),
1222 }
1223 }
1224
1225 /// Cast value to [`&mut Vec<Value>`] if [`Value::Array`].
1226 /// ```
1227 /// # use regorus::*;
1228 /// # fn main() -> anyhow::Result<()> {
1229 /// let mut v = Value::from([Value::from("Hello")].to_vec());
1230 /// v.as_array_mut()?.push(Value::from("World"));
1231 /// # Ok(())
1232 /// # }
1233 pub fn as_array_mut(&mut self) -> Result<&mut Vec<Value>> {
1234 match self {
1235 Value::Array(a) => Ok(Rc::make_mut(a)),
1236 _ => Err(anyhow!("not an array")),
1237 }
1238 }
1239
1240 /// Cast value to [`& BTreeSet<Value>`] if [`Value::Set`].
1241 /// ```
1242 /// # use regorus::*;
1243 /// # use std::collections::BTreeSet;
1244 /// # fn main() -> anyhow::Result<()> {
1245 /// let v = Value::from(
1246 /// [Value::from("Hello")]
1247 /// .iter()
1248 /// .cloned()
1249 /// .collect::<BTreeSet<Value>>(),
1250 /// );
1251 /// assert_eq!(v.as_set()?.first(), Some(&Value::from("Hello")));
1252 /// # Ok(())
1253 /// # }
1254 pub fn as_set(&self) -> Result<&BTreeSet<Value>> {
1255 match self {
1256 Value::Set(s) => Ok(s),
1257 _ => Err(anyhow!("not a set")),
1258 }
1259 }
1260
1261 /// Cast value to [`&mut BTreeSet<Value>`] if [`Value::Set`].
1262 /// ```
1263 /// # use regorus::*;
1264 /// # use std::collections::BTreeSet;
1265 /// # fn main() -> anyhow::Result<()> {
1266 /// let mut v = Value::from(
1267 /// [Value::from("Hello")]
1268 /// .iter()
1269 /// .cloned()
1270 /// .collect::<BTreeSet<Value>>(),
1271 /// );
1272 /// v.as_set_mut()?.insert(Value::from("World"));
1273 /// # Ok(())
1274 /// # }
1275 pub fn as_set_mut(&mut self) -> Result<&mut BTreeSet<Value>> {
1276 match self {
1277 Value::Set(s) => Ok(Rc::make_mut(s)),
1278 _ => Err(anyhow!("not a set")),
1279 }
1280 }
1281
1282 /// Cast value to [`& BTreeMap<Value, Value>`] if [`Value::Object`].
1283 /// ```
1284 /// # use regorus::*;
1285 /// # use std::collections::BTreeMap;
1286 /// # fn main() -> anyhow::Result<()> {
1287 /// let v = Value::from(
1288 /// [(Value::from("Hello"), Value::from("World"))]
1289 /// .iter()
1290 /// .cloned()
1291 /// .collect::<BTreeMap<Value, Value>>(),
1292 /// );
1293 /// assert_eq!(
1294 /// v.as_object()?.iter().next(),
1295 /// Some((&Value::from("Hello"), &Value::from("World"))),
1296 /// );
1297 /// # Ok(())
1298 /// # }
1299 pub fn as_object(&self) -> Result<&BTreeMap<Value, Value>> {
1300 match self {
1301 Value::Object(m) => Ok(m),
1302 _ => Err(anyhow!("not an object")),
1303 }
1304 }
1305
1306 /// Cast value to [`&mut BTreeMap<Value, Value>`] if [`Value::Object`].
1307 /// ```
1308 /// # use regorus::*;
1309 /// # use std::collections::BTreeMap;
1310 /// # fn main() -> anyhow::Result<()> {
1311 /// let mut v = Value::from(
1312 /// [(Value::from("Hello"), Value::from("World"))]
1313 /// .iter()
1314 /// .cloned()
1315 /// .collect::<BTreeMap<Value, Value>>(),
1316 /// );
1317 /// v.as_object_mut()?.insert(Value::from("Good"), Value::from("Bye"));
1318 /// # Ok(())
1319 /// # }
1320 pub fn as_object_mut(&mut self) -> Result<&mut BTreeMap<Value, Value>> {
1321 match self {
1322 Value::Object(m) => Ok(Rc::make_mut(m)),
1323 _ => Err(anyhow!("not an object")),
1324 }
1325 }
1326}
1327
1328impl Value {
1329 pub(crate) fn make_or_get_value_mut<'a>(&'a mut self, paths: &[&str]) -> Result<&'a mut Value> {
1330 if paths.is_empty() {
1331 return Ok(self);
1332 }
1333
1334 let key = Value::String(paths[0].into());
1335 if self == &Value::Undefined {
1336 *self = Value::new_object();
1337 }
1338 if let Value::Object(map) = self {
1339 if map.get(&key).is_none() {
1340 Rc::make_mut(map).insert(key.clone(), Value::Undefined);
1341 // Enforce allocator limit while creating nested object entries.
1342 enforce_limit_anyhow()?;
1343 }
1344 }
1345
1346 match self {
1347 Value::Object(map) => match Rc::make_mut(map).get_mut(&key) {
1348 Some(v) if paths.len() == 1 => Ok(v),
1349 Some(v) => Self::make_or_get_value_mut(v, &paths[1..]),
1350 _ => bail!("internal error: unexpected"),
1351 },
1352 Value::Undefined if paths.len() > 1 => {
1353 *self = Value::new_object();
1354 Self::make_or_get_value_mut(self, paths)
1355 }
1356 Value::Undefined => Ok(self),
1357 _ => bail!("internal error: make: not an selfect {self:?}"),
1358 }
1359 }
1360
1361 pub(crate) fn merge(&mut self, mut new: Value) -> Result<()> {
1362 if self == &new {
1363 return Ok(());
1364 }
1365 match (self, &mut new) {
1366 (v @ Value::Undefined, _) => *v = new,
1367 (Value::Set(ref mut set), Value::Set(new)) => {
1368 Rc::make_mut(set).append(Rc::make_mut(new));
1369 // Enforce allocator limit after merging set entries.
1370 enforce_limit_anyhow()?;
1371 }
1372 (Value::Object(map), Value::Object(new)) => {
1373 for (k, v) in new.iter() {
1374 match map.get(k) {
1375 Some(pv) if *pv != *v => {
1376 bail!(
1377 "value for key `{}` generated multiple times: `{}` and `{}`",
1378 serde_json::to_string_pretty(&k).map_err(anyhow::Error::msg)?,
1379 serde_json::to_string_pretty(&pv).map_err(anyhow::Error::msg)?,
1380 serde_json::to_string_pretty(&v).map_err(anyhow::Error::msg)?,
1381 )
1382 }
1383 _ => {
1384 Rc::make_mut(map).insert(k.clone(), v.clone());
1385 // Enforce allocator limit after merging object entries.
1386 enforce_limit_anyhow()?;
1387 }
1388 };
1389 }
1390 }
1391 _ => bail!("error: could not merge value"),
1392 };
1393 Ok(())
1394 }
1395}
1396
1397impl ops::Index<&Value> for Value {
1398 type Output = Value;
1399
1400 /// Index a [`Value`] using a [`Value`].
1401 ///
1402 /// [`Value::Undefined`] is returned
1403 /// - If the index not valid for the collection.
1404 /// - If the value being indexed is not an array, set or object.
1405 ///
1406 /// Sets can be indexed only by elements within the set.
1407 ///
1408 /// ```
1409 /// # use regorus::*;
1410 /// # use std::collections::BTreeMap;
1411 /// # fn main() -> anyhow::Result<()> {
1412 ///
1413 /// let arr = Value::from([Value::from("Hello")].to_vec());
1414 /// // Index an array.
1415 /// assert_eq!(arr[&Value::from(0)].as_string()?.as_ref(), "Hello");
1416 /// assert_eq!(arr[&Value::from(10)], Value::Undefined);
1417 ///
1418 /// let mut set = Value::new_set();
1419 /// set.as_set_mut()?.insert(Value::from(100));
1420 /// set.as_set_mut()?.insert(Value::from("Hello"));
1421 ///
1422 /// // Index a set.
1423 /// let item = Value::from("Hello");
1424 /// assert_eq!(&set[&item], &item);
1425 /// assert_eq!(&set[&Value::from(10)], &Value::Undefined);
1426 ///
1427 /// let mut obj = Value::new_object();
1428 /// obj.as_object_mut()?.insert(Value::from("Hello"), Value::from("World"));
1429 /// obj.as_object_mut()?.insert(Value::new_array(), Value::from("bye"));
1430 ///
1431 /// // Index an object.
1432 /// assert_eq!(&obj[Value::from("Hello")].as_string()?.as_ref(), &"World");
1433 /// assert_eq!(&obj[Value::from("hllo")], &Value::Undefined);
1434 /// // Index using non-string key.
1435 /// assert_eq!(&obj[&Value::new_array()].as_string()?.as_ref(), &"bye");
1436 ///
1437 /// // Index a non-collection.
1438 /// assert_eq!(&Value::Null[&Value::from(1)], &Value::Undefined);
1439 /// # Ok(())
1440 /// # }
1441 /// ```
1442 ///
1443 /// This is the preferred way of indexing a value.
1444 /// Since constructing a value may be a costly operation (e.g. Value::String),
1445 /// the caller can construct the index value once and use it many times.
1446 ///`
1447 fn index(&self, key: &Value) -> &Self::Output {
1448 match (self, key) {
1449 (Value::Object(o), _) => match &o.get(key) {
1450 Some(v) => v,
1451 _ => &Value::Undefined,
1452 },
1453 (Value::Set(s), _) => match s.get(key) {
1454 Some(v) => v,
1455 _ => &Value::Undefined,
1456 },
1457 (Value::Array(a), Value::Number(n)) => match n.as_u64() {
1458 Some(index) if (index as usize) < a.len() => &a[index as usize],
1459 _ => &Value::Undefined,
1460 },
1461 _ => &Value::Undefined,
1462 }
1463 }
1464}
1465
1466impl<T> ops::Index<T> for Value
1467where
1468 Value: From<T>,
1469{
1470 type Output = Value;
1471
1472 /// Index a [`Value`].
1473 ///
1474 ///
1475 /// A [`Value`] is constructed from the index which is then used for indexing.
1476 ///
1477 /// ```
1478 /// # use regorus::*;
1479 /// # use std::collections::BTreeMap;
1480 /// # fn main() -> anyhow::Result<()> {
1481 /// let v = Value::from(
1482 /// [(Value::from("Hello"), Value::from("World")),
1483 /// (Value::from(1), Value::from(2))]
1484 /// .iter()
1485 /// .cloned()
1486 /// .collect::<BTreeMap<Value, Value>>(),
1487 /// );
1488 ///
1489 /// assert_eq!(&v["Hello"].as_string()?.as_ref(), &"World");
1490 /// assert_eq!(&v[1].as_u64()?, &2u64);
1491 /// # Ok(())
1492 /// # }
1493 fn index(&self, key: T) -> &Self::Output {
1494 &self[&Value::from(key)]
1495 }
1496}