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