uniffi_pipeline/
node.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5use std::{any::Any, fmt, hash::Hash};
6
7use anyhow::{anyhow, bail, Result};
8use indexmap::{IndexMap, IndexSet};
9
10use super::Value;
11
12/// Node trait, this is implemented on all nodes in the Ir (structs, enums and their fields)
13///
14/// Note: All node types must implement `Clone`, `Default`, and `PartialEq`, and the derive macro ensures that.
15/// However, these are not bounds on the node trait, since they're not `dyn-compatible`.
16pub trait Node: fmt::Debug + Any {
17    /// Call a visitor function for all child nodes
18    ///
19    /// Calls the visitor with a path string that represents the field name, vec index, etc. along
20    /// with the child node.
21    ///
22    /// If the visitor returns an error, then the error is returned from `visit_children` without
23    /// any more visits.
24    fn visit_children(
25        &self,
26        _visitor: &mut dyn FnMut(&str, &dyn Node) -> Result<()>,
27    ) -> Result<()> {
28        Ok(())
29    }
30
31    /// Like visit_children, but use &mut.
32    ///
33    /// Note: this will not visit `IndexMap` keys, since they can't be mutated.
34    fn visit_children_mut(
35        &mut self,
36        _visitor: &mut dyn FnMut(&str, &mut dyn Node) -> Result<()>,
37    ) -> Result<()> {
38        Ok(())
39    }
40
41    /// Type name for structs / enums
42    ///
43    /// This is used to implement the type name filter in the CLI
44    fn type_name(&self) -> Option<&'static str> {
45        None
46    }
47
48    /// Create a value from this node's data
49    ///
50    /// Logically, this consumes `self`.  However, it inputs `&mut self` because it works better
51    /// with dyn traits.  It leaves behind an empty node.
52    fn take_into_value(&mut self) -> Value;
53
54    /// Convert a value into this node.
55    fn try_from_value(value: Value) -> Result<Self, FromValueError>
56    where
57        Self: Sized;
58
59    /// Convert `&Node` into `&dyn Any`.
60    ///
61    /// This is used to implement `visit_children`.
62    fn as_any(&self) -> &dyn Any;
63
64    /// Convert `&Node` into `&mut dyn Any`.
65    fn as_any_mut(&mut self) -> &mut dyn Any;
66
67    fn to_box_any(self: Box<Self>) -> Box<dyn Any>;
68
69    fn visit<T: Node>(&self, mut visitor: impl FnMut(&T))
70    where
71        Self: Sized,
72    {
73        // unwrap() should never panic, since the visitor doesn't return an error
74        (self as &dyn Node)
75            .try_visit_descendents_recurse(&mut |node| {
76                visitor(node);
77                Ok(())
78            })
79            .unwrap()
80    }
81
82    fn visit_mut<T: Node>(&mut self, mut visitor: impl FnMut(&mut T))
83    where
84        Self: Sized,
85    {
86        // unwrap() should never panic, since the visitor doesn't return an error
87        (self as &mut dyn Node)
88            .try_visit_descendents_recurse_mut(&mut |node| {
89                visitor(node);
90                Ok(())
91            })
92            .unwrap()
93    }
94
95    fn try_visit<T: Node>(&self, mut visitor: impl FnMut(&T) -> Result<()>) -> Result<()>
96    where
97        Self: Sized,
98    {
99        (self as &dyn Node).try_visit_descendents_recurse(&mut visitor)
100    }
101
102    fn try_visit_mut<T: Node>(
103        &mut self,
104        mut visitor: impl FnMut(&mut T) -> Result<()>,
105    ) -> Result<()>
106    where
107        Self: Sized,
108    {
109        (self as &mut dyn Node).try_visit_descendents_recurse_mut(&mut visitor)
110    }
111
112    /// Does this node has any descendant where the closure returns `true`?
113    fn has_descendant<T: Node>(&self, mut matcher: impl FnMut(&T) -> bool) -> bool
114    where
115        Self: Sized,
116    {
117        self.try_visit(|node: &T| {
118            if matcher(node) {
119                // `matcher` returned true, so we want to short-circuit the `try_visit`.  To do
120                // that, return an error, then check the error after `try_visit` completes.  It's
121                // weird, but it works
122                bail!("");
123            } else {
124                Ok(())
125            }
126        })
127        .is_err()
128    }
129
130    /// Does this node have any descendant of a given type?
131    fn has_descendant_with_type<T: Node>(&self) -> bool
132    where
133        Self: Sized,
134    {
135        self.has_descendant(|_: &T| true)
136    }
137
138    /// Take the current value from `self` leaving behind an empty value
139    fn take(&mut self) -> Self
140    where
141        Self: Default,
142    {
143        std::mem::take(self)
144    }
145
146    /// Convert from one node to another
147    fn try_from_node(mut other: impl Node) -> Result<Self>
148    where
149        Self: Sized,
150    {
151        Self::try_from_value(other.take_into_value()).map_err(|mut e| {
152            e.path.reverse();
153            let path = e.path.join("");
154            anyhow!("Node conversion error: {} (path: <root>{path})", e.message)
155        })
156    }
157}
158
159impl dyn Node {
160    pub(crate) fn try_visit_descendents_recurse<T: Node>(
161        &self,
162        visitor: &mut dyn FnMut(&T) -> Result<()>,
163    ) -> Result<()> {
164        if let Some(node) = self.as_any().downcast_ref::<T>() {
165            visitor(node)?;
166        }
167        self.visit_children(&mut |_, child| {
168            child.try_visit_descendents_recurse(visitor)?;
169            Ok(())
170        })
171    }
172
173    pub(crate) fn try_visit_descendents_recurse_mut<T: Node>(
174        &mut self,
175        visitor: &mut dyn FnMut(&mut T) -> Result<()>,
176    ) -> Result<()> {
177        if let Some(node) = self.as_any_mut().downcast_mut::<T>() {
178            visitor(node)?;
179        }
180        self.visit_children_mut(&mut |_, child| {
181            child.try_visit_descendents_recurse_mut(visitor)?;
182            Ok(())
183        })
184    }
185}
186
187/// Error struct for `Node::try_from_value`
188pub struct FromValueError {
189    /// Field path to the node that couldn't be converted.
190    ///
191    /// To make the generated code simpler, this is in reverse order, the first items in the vec
192    /// are the deepest items in the node tree.
193    path: Vec<String>,
194    message: String,
195}
196
197impl FromValueError {
198    pub fn new(message: String) -> Self {
199        Self {
200            message,
201            path: vec![],
202        }
203    }
204
205    pub fn add_field_to_path(mut self, field: impl Into<String>) -> Self {
206        self.path.push(field.into());
207        self
208    }
209
210    pub fn into_anyhow(mut self) -> anyhow::Error {
211        self.path.reverse();
212        let path = self.path.join("");
213        anyhow!(
214            "Node conversion error: {} (path: <root>{path})",
215            self.message
216        )
217    }
218}
219
220macro_rules! simple_nodes {
221    ($($value_variant:ident($ty:ty)),* $(,)?) => {
222        $(
223            impl Node for $ty {
224                fn as_any(&self) -> &dyn Any {
225                    self
226                }
227
228                fn as_any_mut(&mut self) -> &mut dyn Any {
229                    self
230                }
231
232                fn to_box_any(self: Box<Self>) -> Box<dyn Any>{
233                    self
234                }
235
236                fn take_into_value(&mut self) -> Value {
237                    Value::$value_variant(self.take())
238                }
239
240                fn try_from_value(value: Value) -> Result<Self, FromValueError> {
241                    match value {
242                        Value::$value_variant(v) => Ok(v),
243                        v => Err(FromValueError::new(format!(
244                            "Node type error (expected {}, actual {v:?})",
245                            std::stringify!($value_variant)
246                        ))),
247                    }
248                }
249            }
250        )*
251    };
252}
253
254simple_nodes!(
255    UInt8(u8),
256    Int8(i8),
257    UInt16(u16),
258    Int16(i16),
259    UInt32(u32),
260    Int32(i32),
261    UInt64(u64),
262    Int64(i64),
263    Float32(f32),
264    Float64(f64),
265    String(String),
266    Bool(bool),
267);
268
269impl<T: Node> Node for Box<T> {
270    fn visit_children(&self, visitor: &mut dyn FnMut(&str, &dyn Node) -> Result<()>) -> Result<()> {
271        visitor("", &**self)
272    }
273
274    fn visit_children_mut(
275        &mut self,
276        visitor: &mut dyn FnMut(&str, &mut dyn Node) -> Result<()>,
277    ) -> Result<()> {
278        visitor("", &mut **self)
279    }
280
281    fn as_any(&self) -> &dyn Any {
282        self
283    }
284
285    fn as_any_mut(&mut self) -> &mut dyn Any {
286        self
287    }
288
289    fn to_box_any(self: Box<Self>) -> Box<dyn Any> {
290        self
291    }
292
293    fn take_into_value(&mut self) -> Value {
294        (**self).take_into_value()
295    }
296
297    fn try_from_value(value: Value) -> Result<Self, FromValueError> {
298        T::try_from_value(value).map(Box::new)
299    }
300}
301
302impl<T: Node> Node for Option<T> {
303    fn visit_children(&self, visitor: &mut dyn FnMut(&str, &dyn Node) -> Result<()>) -> Result<()> {
304        if let Some(node) = self {
305            visitor("", node)?;
306        }
307        Ok(())
308    }
309
310    fn visit_children_mut(
311        &mut self,
312        visitor: &mut dyn FnMut(&str, &mut dyn Node) -> Result<()>,
313    ) -> Result<()> {
314        if let Some(node) = self {
315            visitor("", node)?;
316        }
317        Ok(())
318    }
319
320    fn as_any(&self) -> &dyn Any {
321        self
322    }
323
324    fn as_any_mut(&mut self) -> &mut dyn Any {
325        self
326    }
327
328    fn to_box_any(self: Box<Self>) -> Box<dyn Any> {
329        self
330    }
331
332    fn take_into_value(&mut self) -> Value {
333        Value::Option(
334            self.take()
335                .map(|mut node| node.take_into_value())
336                .map(Box::new),
337        )
338    }
339
340    fn try_from_value(value: Value) -> Result<Self, FromValueError> {
341        match value {
342            Value::Option(v) => v.map(|v| v.try_into_node()).transpose(),
343            v => Err(FromValueError::new(format!(
344                "Node type error (expected Option, actual {v:?})"
345            ))),
346        }
347    }
348}
349
350impl<T: Node> Node for Vec<T> {
351    fn visit_children(&self, visitor: &mut dyn FnMut(&str, &dyn Node) -> Result<()>) -> Result<()> {
352        for (i, child) in self.iter().enumerate() {
353            visitor(&format!(".{i}"), child)?;
354        }
355        Ok(())
356    }
357
358    fn visit_children_mut(
359        &mut self,
360        visitor: &mut dyn FnMut(&str, &mut dyn Node) -> Result<()>,
361    ) -> Result<()> {
362        for (i, child) in self.iter_mut().enumerate() {
363            visitor(&format!(".{i}"), child)?;
364        }
365        Ok(())
366    }
367
368    fn as_any(&self) -> &dyn Any {
369        self
370    }
371
372    fn as_any_mut(&mut self) -> &mut dyn Any {
373        self
374    }
375
376    fn to_box_any(self: Box<Self>) -> Box<dyn Any> {
377        self
378    }
379
380    fn take_into_value(&mut self) -> Value {
381        Value::Vec(
382            self.take()
383                .into_iter()
384                .map(|mut node| node.take_into_value())
385                .collect(),
386        )
387    }
388
389    fn try_from_value(value: Value) -> Result<Self, FromValueError> {
390        match value {
391            Value::Vec(values) => values
392                .into_iter()
393                .enumerate()
394                .map(|(i, v)| {
395                    v.try_into_node()
396                        .map_err(|e| e.add_field_to_path(format!("[{i}]")))
397                })
398                .collect(),
399            v => Err(FromValueError::new(format!(
400                "Node type error (expected Vec, actual {v:?})",
401            ))),
402        }
403    }
404}
405
406impl<T> Node for IndexSet<T>
407where
408    T: Node + Hash + Eq,
409{
410    fn visit_children(&self, visitor: &mut dyn FnMut(&str, &dyn Node) -> Result<()>) -> Result<()> {
411        for v in self.iter() {
412            visitor(&format!("{{{v:?}}}"), v)?;
413        }
414        Ok(())
415    }
416
417    fn visit_children_mut(
418        &mut self,
419        visitor: &mut dyn FnMut(&str, &mut dyn Node) -> Result<()>,
420    ) -> Result<()> {
421        // We can't directly mutate IndexSet items, since that would change their hash value.
422        // Instead, use deconstruct the set using into_iter() and collect everything at the end.
423        *self = Node::take(self)
424            .into_iter()
425            .map(|mut v| {
426                visitor(&format!("{{{v:?}}}"), &mut v)?;
427                Ok(v)
428            })
429            .collect::<Result<IndexSet<_>>>()?;
430        Ok(())
431    }
432
433    fn as_any(&self) -> &dyn Any {
434        self
435    }
436
437    fn as_any_mut(&mut self) -> &mut dyn Any {
438        self
439    }
440
441    fn to_box_any(self: Box<Self>) -> Box<dyn Any> {
442        self
443    }
444
445    fn take_into_value(&mut self) -> Value {
446        Value::Set(
447            Node::take(self)
448                .into_iter()
449                .map(|mut node| node.take_into_value())
450                .collect(),
451        )
452    }
453
454    fn try_from_value(value: Value) -> Result<Self, FromValueError> {
455        match value {
456            Value::Set(values) => values
457                .into_iter()
458                .map(|k| {
459                    let key_name = format!("{k:?}");
460                    k.try_into_node()
461                        .map_err(|e| e.add_field_to_path(format!("{{{key_name:?}}}")))
462                })
463                .collect(),
464            v => Err(FromValueError::new(format!(
465                "Node type error (expected Map, actual {v:?})",
466            ))),
467        }
468    }
469}
470
471impl<K, V> Node for IndexMap<K, V>
472where
473    K: Node + Hash + Eq,
474    V: Node,
475{
476    fn visit_children(&self, visitor: &mut dyn FnMut(&str, &dyn Node) -> Result<()>) -> Result<()> {
477        for (k, v) in self.iter() {
478            visitor(&format!("[{k:?}]"), v)?;
479            visitor(&format!(".key[{k:?}]"), k)?;
480        }
481        Ok(())
482    }
483
484    fn visit_children_mut(
485        &mut self,
486        visitor: &mut dyn FnMut(&str, &mut dyn Node) -> Result<()>,
487    ) -> Result<()> {
488        // We can't directly mutate Map key, since that would change their hash value.
489        // Instead, use deconstruct the set using into_iter() and collect everything at the end.
490        *self = self
491            .take()
492            .into_iter()
493            .map(|(mut k, mut v)| {
494                let key_name = format!("{k:?}");
495                visitor(&format!("{{{key_name:?}}}"), &mut k)?;
496                visitor(&format!("[{key_name:?}]"), &mut v)?;
497                Ok((k, v))
498            })
499            .collect::<Result<IndexMap<_, _>>>()?;
500        Ok(())
501    }
502
503    fn as_any(&self) -> &dyn Any {
504        self
505    }
506
507    fn as_any_mut(&mut self) -> &mut dyn Any {
508        self
509    }
510
511    fn to_box_any(self: Box<Self>) -> Box<dyn Any> {
512        self
513    }
514
515    fn take_into_value(&mut self) -> Value {
516        Value::Map(
517            self.take()
518                .into_iter()
519                .map(|(mut k, mut v)| (k.take_into_value(), v.take_into_value()))
520                .collect(),
521        )
522    }
523
524    fn try_from_value(value: Value) -> Result<Self, FromValueError> {
525        match value {
526            Value::Map(values) => values
527                .into_iter()
528                .map(|(k, v)| {
529                    let v = v
530                        .try_into_node()
531                        .map_err(|e| e.add_field_to_path(format!("[{k:?}]")))?;
532                    let k = k
533                        .try_into_node()
534                        .map_err(|e| e.add_field_to_path("[<key>]".to_string()))?;
535                    Ok((k, v))
536                })
537                .collect(),
538            v => Err(FromValueError::new(format!(
539                "Node type error (expected Map, actual {v:?})",
540            ))),
541        }
542    }
543}