1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/// This module defines the main traits used to dynamically operate and reflect on Rust types using Interact.
use std::sync::Arc;

use crate::deser::Deser;
use crate::{deser, ClimbError, Climber, NodeTree, Reflector};

/// The indirect Reflect allows indirect climber or reflector access, and meant to be used as a
/// trait object for that purpose.
///
/// It is expected that the provided callback would be called at this or some other thread in order
/// to continue traversal of the access expression. For example, if a processes uses internal message
/// passing, the traversal can continue upon message reception.
pub trait ReflectIndirect {
    /// Provides indirection for immutable access.
    fn indirect(&self, fnc: Box<FnMut(&dyn Access) + Send>);

    /// Provides indirection for mutable access.
    fn indirect_mut(&mut self, fnc: Box<FnMut(&mut dyn Access) + Send>);
}

/// The direct Reflect allows direct climber or reflector access, and meant
/// to be used as a trait object for that purpose.
pub trait ReflectDirect {
    /// The specific implementation of the following method will mostly likely call
    /// Reflector::reflect with the specific type.
    fn immut_reflector(&self, _reflector: &Arc<Reflector>) -> NodeTree;

    /// Implement climbing for the specific type. Returns a reflection of the inner value,
    /// depending on the expression remaining to parse.
    fn immut_climber<'a>(&self, _climber: &mut Climber<'a>)
        -> Result<Option<NodeTree>, ClimbError>;

    /// Implement mutable climbing for the specific type, allowing to modifying it.
    /// Returns a reflection of the inner value, depending on the expression remaining to parse.
    fn mut_climber<'a>(
        &mut self,
        _climber: &mut Climber<'a>,
    ) -> Result<Option<NodeTree>, ClimbError>;
}

/// An arbitrar between the two possible way to climb into an immutable value.
pub enum Reflect<'a> {
    Indirect(&'a dyn ReflectIndirect),
    Direct(&'a dyn ReflectDirect),
}

pub struct Function {
    pub name: &'static str,
    pub args: &'static [&'static str],
}

/// MutAccess adds function call information over `ReflectMut`.
pub struct MutAccess<'a> {
    pub reflect: ReflectMut<'a>,
    pub functions: &'static [Function],
}

impl<'a> MutAccess<'a> {
    pub fn no_funcs(reflect: ReflectMut<'a>) -> Self {
        Self {
            reflect,
            functions: &[],
        }
    }
}

/// ImmutAccess adds function call information over `Reflect`.
pub struct ImmutAccess<'a> {
    pub reflect: Reflect<'a>,
    pub functions: &'static [Function],
}

impl<'a> ImmutAccess<'a> {
    pub fn no_funcs(reflect: Reflect<'a>) -> Self {
        Self {
            reflect,
            functions: &[],
        }
    }
}

/// An arbitrar between the two possible way to climb into a mutable value.
pub enum ReflectMut<'a> {
    Indirect(&'a mut dyn ReflectIndirect),
    Direct(&'a mut dyn ReflectDirect),

    /// Internally signals that the value is not really mutable, for example
    /// we cannot change a reference value field from Interact context.
    Immutable,
}

#[derive(Debug, Eq, PartialEq)]
pub enum AssignError {
    Deser(deser::DeserError),

    /// Some types, having ignored fields, will be unbuildable.
    Unbuildable,

    /// Other values are immutable, such as reference values.
    Immutable,
}

#[derive(Debug, Eq, PartialEq)]
pub enum CallError {
    Deser(deser::DeserError),

    /// Signals the Climber stack to retract into a mutable path so that the
    /// field we are attempting to operate on will be recalled in a mutable
    /// state.
    NeedMutable,

    /// The called function does not exist.
    NoSuchFunction,
}

pub type RetValCallback<'a> = Box<FnMut(&dyn Access, &mut Climber<'a>)>;

/// The `Access` trait, meant to be used as a trait object, provides methods that
/// dynamically expose read&write access to the underlying objects.
pub trait Access {
    /// Expose an immmutable accessor, used when `Access` is immutable or mutable.
    fn immut_access(&self) -> ImmutAccess;

    /// Expose a mutable accessor, used when `Access` is mutable.
    fn mut_access(&mut self) -> MutAccess;

    /// Perform an optional method call for a certain function, with the return value provided to
    /// the callback. The arguments are parsed from the Token tracker in the Climber parameter.
    ///
    /// Depending on the state of the Climber, we may just parsing the arguments not not actually
    /// calling the function, in order to provide user feedback.
    fn immut_call<'a>(
        &self,
        _func_name: &'static str,
        _climber: &mut Climber<'a>,
        mut _retcall: RetValCallback<'a>,
    ) -> Result<(), CallError> {
        Err(CallError::NoSuchFunction)
    }

    /// Perform an optional method call for a certain function which may modify the underlying
    /// value, with the return value provided to the callback. The arguments are parsed from the
    /// Token tracker in the Climber parameter.
    ///
    /// Depending on the state of the Climber, we may just parsing the arguments not not actually
    /// calling the function, in order to provide user feedback.
    fn mut_call<'a>(
        &mut self,
        _func_name: &'static str,
        _climber: &mut Climber<'a>,
        mut _retcall: RetValCallback<'a>,
    ) -> Result<(), CallError> {
        Err(CallError::NoSuchFunction)
    }

    /// Assign a new value to this object. `probe_only` determines whether the implementation would
    /// only parse the new value and not actually assign it. This is in order to provide user
    /// feedback for the parsing bits.
    fn mut_assign<'a, 'b>(
        &mut self,
        _tokens: &mut deser::Tracker<'a, 'b>,
        _probe_only: bool,
    ) -> Result<(), AssignError> {
        Err(AssignError::Unbuildable)
    }
}

macro_rules! mut_assign_deser {
    () => {
        fn mut_assign<'x, 'y>(
            &mut self,
            tracker: &mut deser::Tracker<'x, 'y>,
            probe_only: bool,
        ) -> Result<(), AssignError> {
            crate::access::deser_assign(self, tracker, probe_only)
        }
    }
}

/// A helper for the specific implementations of `Access` to use with `mut_assign` methods
pub fn deser_assign<'a, 'b, T: Deser>(
    dest: &mut T,
    tracker: &mut deser::Tracker<'a, 'b>,
    probe_only: bool,
) -> Result<(), AssignError> {
    match T::deser(tracker) {
        Ok(v) => {
            if !probe_only {
                *dest = v;
            }
            Ok(())
        }
        Err(e) => Err(AssignError::Deser(e)),
    }
}

mod basic;
mod btreemap;
mod derefs;
pub mod derive;
mod explicit;
mod hashmap;
mod hashset;
mod instant;
pub mod iter;
mod mutex;
mod refcell;
mod tuple;
pub mod vec;