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}