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
//! Define and store module specs on an interpreter.

use core::any::Any;

/// Define and store module specs on an interpreter.
///
/// A module spec is a static set of information the interpreter requires to
/// define a Ruby `Module` object.
pub trait ModuleRegistry {
    /// Concrete value type for boxed Ruby values.
    type Value;

    /// Concrete error type for errors encountered when manipulating the module registry.
    type Error;

    /// Type representing a module specification.
    type Spec: 'static;

    /// Create a module definition bound to a Rust type `T`.
    ///
    /// Module definitions have the same lifetime as the interpreter.
    ///
    /// # Errors
    ///
    /// If the module registry state is inaccessible, an error is returned.
    fn def_module<T>(&mut self, spec: Self::Spec) -> Result<(), Self::Error>
    where
        T: Any;

    /// Retrieve a module definition from the interpreter bound to Rust type `T`.
    ///
    /// This function returns `None` if type `T` has not had a module spec
    /// registered for it using [`ModuleRegistry::def_module`].
    ///
    /// # Errors
    ///
    /// If the module registry state is inaccessible, an error is returned.
    fn module_spec<T>(&self) -> Result<Option<&Self::Spec>, Self::Error>
    where
        T: Any;

    /// Retrieve whether a module definition exists from the interpreter bound
    /// to Rust type `T`
    ///
    /// If the interpreter cannot find or load a module associated with `T`,
    /// `Ok(None)` is returned.
    ///
    /// # Errors
    ///
    /// If the module registry state is inaccessible, an error is returned.
    fn is_module_defined<T>(&self) -> bool
    where
        T: Any,
    {
        matches!(self.module_spec::<T>(), Ok(Some(_)))
    }

    /// Retrieve a boxed Ruby value containing a `Module` object for the
    /// `Module` bound to Rust type `T`.
    ///
    /// If the interpreter cannot find or load a module associated with `T`,
    /// `Ok(None)` is returned.
    ///
    /// # Errors
    ///
    /// If the module registry state is inaccessible, an error is returned.
    fn module_of<T>(&mut self) -> Result<Option<Self::Value>, Self::Error>
    where
        T: Any;
}