binn_ir/value_enum/impls/
object.rs

1/*
2==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--
3
4Binn-IR
5
6Copyright (C) 2018-2023  Anonymous
7
8There are several releases over multiple years,
9they are listed as ranges, such as: "2018-2023".
10
11This program is free software: you can redistribute it and/or modify
12it under the terms of the GNU Lesser General Public License as published by
13the Free Software Foundation, either version 3 of the License, or
14(at your option) any later version.
15
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19GNU Lesser General Public License for more details.
20
21You should have received a copy of the GNU Lesser General Public License
22along with this program.  If not, see <https://www.gnu.org/licenses/>.
23
24::--::--::--::--::--::--::--::--::--::--::--::--::--::--::--::--
25*/
26
27//! # Shortcuts for `Value::Object`
28
29use {
30    core::iter::FromIterator,
31    crate::{Error, Object, ObjectKey, Result, Value},
32};
33
34/// # Helper macro for Value::*_maybe_by()/*_maybe_mut_by()
35macro_rules! maybe_by_or_mut_by { ($self: ident, $variant: tt, $keys: ident, $code: tt) => {{
36    if $keys.is_empty() {
37        return Err(err!("Keys must not be empty"));
38    }
39
40    let mut value = Some($self);
41    for (nth, key) in $keys.iter().enumerate() {
42        match value {
43            Some(Value::$variant(variant)) => value = variant.$code(*key),
44            Some(_) => return Err(match nth {
45                0 => err!("Value is not {}", stringify!($variant)),
46                _ => err!("Value at {keys:?} is not {variant}", keys=&$keys[..nth], variant=stringify!($variant)),
47            }),
48            None => return Err(err!("There is no value at {:?}", &$keys[..nth])),
49        };
50    }
51
52    Ok(value)
53}}}
54
55/// # Helper macro for Value::*_take_by()
56macro_rules! maybe_take_by { ($self: ident, $variant: tt, $keys: ident) => {{
57    let mut value = Some($self);
58    for (nth, key) in $keys.iter().enumerate() {
59        match value {
60            Some(Value::$variant(variant)) => if nth + 1 == $keys.len() {
61                return Ok(variant.remove(*key));
62            } else {
63                value = variant.get_mut(*key);
64            },
65            Some(_) => return Err(match nth {
66                0 => err!("Value is not {}", stringify!($variant)),
67                _ => err!("Value at {keys:?} is not {variant}", keys=&$keys[..nth], variant=stringify!($variant)),
68            }),
69            None => return Err(err!("There is no value at {:?}", &$keys[..nth])),
70        };
71    }
72
73    Err(err!("Keys must not be empty"))
74}}}
75
76/// # Shortcuts for [`Object`](#variant.Object)
77impl Value {
78
79    /// # If the value is an object, inserts new item into it
80    ///
81    /// On success, returns previous value (if it existed).
82    ///
83    /// Returns an error if the value is not an object.
84    pub fn object_insert<K, V>(&mut self, key: K, value: V) -> Result<Option<Value>> where K: Into<ObjectKey>, V: Into<Self> {
85        match self {
86            Self::Object(object) => Ok(crate::object_insert(object, key, value)),
87            _ => Err(err!("Value is not an object")),
88        }
89    }
90
91    /// # Gets an immutable item from this object and its sub objects
92    ///
93    /// The function returns an error on one of these conditions:
94    ///
95    /// - Keys are empty.
96    /// - The value or any of its sub items is not an object.
97    ///
98    /// ## Examples
99    ///
100    /// ```
101    /// let mut object = binn_ir::object();
102    /// object.object_insert("zero", true)?;
103    /// object.object_insert("one", {
104    ///     let mut object = binn_ir::Object::new();
105    ///     binn_ir::object_insert(&mut object, "two", 99);
106    ///     object
107    /// })?;
108    ///
109    /// assert_eq!(bool::try_from(object.object_by(&["zero"])?)?, true);
110    /// assert_eq!(u8::try_from(object.object_by(&["one", "two"])?)?, 99);
111    ///
112    /// assert!(object.object_by(&["two"]).is_err());
113    /// assert!(object.object_maybe_by(&["two"])?.is_none());
114    ///
115    /// assert!(object.object_by(&[]).is_err());
116    /// assert!(object.object_by(&["zero", "two"]).is_err());
117    /// assert!(object.object_by(&["one", "two", "three"]).is_err());
118    ///
119    /// # Ok::<_, binn_ir::Error>(())
120    /// ```
121    pub fn object_by(&self, keys: &[&str]) -> Result<&Self> {
122        self.object_maybe_by(keys)?.ok_or_else(|| err!("There is no value at: {:?}", keys))
123    }
124
125    /// # Gets an optional immutable item from this object and its sub objects
126    ///
127    /// The function returns an error on one of these conditions:
128    ///
129    /// - Keys are empty.
130    /// - The value or any of its sub items is not an object.
131    pub fn object_maybe_by(&self, keys: &[&str]) -> Result<Option<&Self>> {
132        maybe_by_or_mut_by!(self, Object, keys, get)
133    }
134
135    /// # Gets a mutable item from this object and its sub objects
136    ///
137    /// The function returns an error on one of these conditions:
138    ///
139    /// - Keys are empty.
140    /// - The value or any of its sub items is not an object.
141    pub fn object_mut_by(&mut self, keys: &[&str]) -> Result<&mut Self> {
142        self.object_maybe_mut_by(keys)?.ok_or_else(|| err!("There is no value at: {:?}", keys))
143    }
144
145    /// # Gets an optional mutable item from this object and its sub objects
146    ///
147    /// The function returns an error on one of these conditions:
148    ///
149    /// - Keys are empty.
150    /// - The value or any of its sub items is not an object.
151    pub fn object_maybe_mut_by(&mut self, keys: &[&str]) -> Result<Option<&mut Self>> {
152        maybe_by_or_mut_by!(self, Object, keys, get_mut)
153    }
154
155    /// # Takes an item from this object and its sub objects
156    ///
157    /// The function returns an error on one of these conditions:
158    ///
159    /// - Keys are empty.
160    /// - The value or any of its sub items is not an object.
161    ///
162    /// ## Examples
163    ///
164    /// ```
165    /// let mut object = binn_ir::object();
166    /// object.object_insert("first", "1st")?;
167    /// object.object_insert("second", {
168    ///     let mut object = binn_ir::Object::new();
169    ///     binn_ir::object_insert(&mut object, "third", "3rd");
170    ///     object
171    /// })?;
172    ///
173    /// assert_eq!(object.object_take_by(&["first"])?.as_text()?, "1st");
174    /// assert_eq!(object.object_take_by(&["second", "third"])?.as_text()?, "3rd");
175    ///
176    /// assert!(object.object_take_by(&["zero"]).is_err());
177    /// assert!(object.object_maybe_take_by(&["zero"])?.is_none());
178    /// assert!(object.object_maybe_take_by(&["second", "fourth"])?.is_none());
179    ///
180    /// assert!(object.object_take_by(&[]).is_err());
181    /// assert!(object.object_take_by(&["third", "fourth"]).is_err());
182    ///
183    /// # Ok::<_, binn_ir::Error>(())
184    /// ```
185    pub fn object_take_by(&mut self, keys: &[&str]) -> Result<Self> {
186        self.object_maybe_take_by(keys)?.ok_or_else(|| err!("There is no value at: {:?}", keys))
187    }
188
189    /// # Takes an optional item from this object and its sub objects
190    ///
191    /// The function returns an error on one of these conditions:
192    ///
193    /// - Keys are empty.
194    /// - The value or any of its sub items is not an object.
195    pub fn object_maybe_take_by(&mut self, keys: &[&str]) -> Result<Option<Self>> {
196        maybe_take_by!(self, Object, keys)
197    }
198
199    /// # If the value is an object, returns an immutable reference of it
200    ///
201    /// Returns an error if the value is not an object.
202    pub fn as_object(&self) -> Result<&Object> {
203        match self {
204            Self::Object(object) => Ok(object),
205            _ => Err(err!("Value is not an Object")),
206        }
207    }
208
209    /// # If the value is an object, returns a mutable reference of it
210    ///
211    /// Returns an error if the value is not an object.
212    pub fn as_mut_object(&mut self) -> Result<&mut Object> {
213        match self {
214            Self::Object(object) => Ok(object),
215            _ => Err(err!("Value is not an Object")),
216        }
217    }
218
219}
220
221impl From<Object> for Value {
222
223    fn from(object: Object) -> Self {
224        Self::Object(object)
225    }
226
227}
228
229impl FromIterator<(ObjectKey, Value)> for Value {
230
231    fn from_iter<T>(iter: T) -> Self where T: IntoIterator<Item=(ObjectKey, Self)> {
232        Self::Object(iter.into_iter().collect())
233    }
234
235}
236
237impl TryFrom<Value> for Object {
238
239    type Error = Error;
240
241    fn try_from(v: Value) -> core::result::Result<Self, Self::Error> {
242        match v {
243            Value::Object(object) => Ok(object),
244            _ => Err(err!("Value is not an Object")),
245        }
246    }
247
248}