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}