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}