rusteval/
interactive.rs

1use core::any::type_name;
2use core::fmt::Debug;
3
4use auto_impl::auto_impl;
5
6use crate::specialization::{AsDebug, AsMethods, AsMethodsMut};
7use crate::{InteractiveError, Result};
8
9/// A trait that gives interactive access to its fields as `dyn Interactive` or `dyn Debug`.
10///
11/// This trait gets implemented automatically when you derive it with [`Interactive`].
12/// See the macros documentation for more information.
13///
14/// [`Interactive`]: macro@crate::Interactive
15#[cfg_attr(feature = "std", auto_impl(&, &mut, Box, Rc, Arc))]
16#[cfg_attr(not(feature = "std"), auto_impl(&, &mut))]
17pub trait Interactive: AsDebug + AsMethods + AsMethodsMut {
18    /// Looks for a field with the given name and on success return a shared reference to it.
19    fn get_field<'a>(&'a self, field_name: &'a str) -> crate::Result<'a, &dyn crate::Interactive> {
20        Err(InteractiveError::FieldNotFound {
21            type_name: type_name::<Self>(),
22            field_name,
23        })
24    }
25
26    /// Looks for a field with the given name and on success return a mutable reference to it.
27    #[auto_impl(keep_default_for(&, Rc, Arc))]
28    fn get_field_mut<'a>(
29        &'a mut self,
30        field_name: &'a str,
31    ) -> crate::Result<'a, &mut dyn crate::Interactive> {
32        Err(InteractiveError::FieldNotFound {
33            type_name: type_name::<Self>(),
34            field_name,
35        })
36    }
37
38    /// Looks for a field with the given name,
39    /// and passes it as a `Ok(&dyn Debug)` to the given closure.
40    ///
41    /// On error the `Err(InteractiveError)` is passed to the closure instead.
42    fn eval_field(&self, field_name: &str, f: &mut dyn FnMut(Result<'_, &dyn Debug>)) {
43        f(Err(InteractiveError::FieldNotFound {
44            type_name: type_name::<Self>(),
45            field_name,
46        }))
47    }
48
49    /// Returns all interactive field names of this type.
50    ///
51    /// Can be used to drive auto-completion in a CLI.
52    fn get_all_field_names(&self) -> &'static [&'static str] {
53        &[]
54    }
55}
56
57/// A trait that allows to interactively evaluate a structs methods and pass their result to the given closure.
58///
59/// This trait gets implemented automatically when you use the [`Methods`] attribute.
60/// See its documentation for more information.
61///
62/// [`Interactive`]: macro@crate::Interactive
63/// [`Methods`]: macro@crate::Methods
64#[cfg_attr(feature = "std", auto_impl(&, &mut, Box, Rc, Arc))]
65#[cfg_attr(not(feature = "std"), auto_impl(&, &mut))]
66pub trait Methods {
67    /// Looks for a method with the given name,
68    /// parses the args string into the expected arguments of the method,
69    /// executes the method and
70    /// passes the result as a `Ok(&dyn Debug)` to the given closure.
71    ///
72    /// On error the `Err(InteractiveError)` is passed to the closure instead.
73    ///
74    /// This method does not have access to methods that take `&mut self` as their receiver,
75    /// use [`eval_method_mut`] instead.
76    ///
77    /// [`eval_method_mut`]: #method.eval_method_mut
78    fn eval_method(
79        &self,
80        method_name: &str,
81        args: &str,
82        f: &mut dyn FnMut(Result<'_, &dyn Debug>),
83    ) {
84        {
85            let _ = args;
86            f(Err(InteractiveError::MethodNotFound {
87                type_name: type_name::<Self>(),
88                method_name,
89            }));
90        }
91    }
92
93    /// Looks for a method with the given name,
94    /// parses the args string into the expected arguments of the method,
95    /// executes the method and
96    /// passes the result as a `Ok(&dyn Debug)` to the given closure.
97    ///
98    /// On error the `Err(InteractiveError)` is passed to the closure instead.
99    #[auto_impl(keep_default_for(&, Rc, Arc))]
100    fn eval_method_mut(
101        &mut self,
102        method_name: &str,
103        args: &str,
104        f: &mut dyn FnMut(Result<'_, &dyn Debug>),
105    ) {
106        let _ = args;
107        f(Err(InteractiveError::MethodNotFound {
108            type_name: type_name::<Self>(),
109            method_name,
110        }));
111    }
112
113    /// Returns all interactive method names of this type.
114    ///
115    /// Can be used to drive auto-completion in a CLI.
116    fn get_all_method_names(&self) -> &'static [&'static str] {
117        &[]
118    }
119}