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

use core::any::Any;

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

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

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

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

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

    /// Retrieve whether a class definition exists from the state bound to Rust type `T`.
    ///
    /// # Errors
    ///
    /// If the class registry state is inaccessible, an error is returned.
    fn is_class_defined<T>(&self) -> bool
    where
        T: Any,
    {
        matches!(self.class_spec::<T>(), Ok(Some(_)))
    }

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

    /// Create a new instance of the class bound to the Rust type `T`.
    ///
    /// This method resolves the class referenced by the type `T` and calls
    /// `new` on this Ruby class with the given arguments.
    ///
    /// If the interpreter cannot find or load a class associated with `T`,
    /// `Ok(None)` is returned.
    ///
    /// # Errors
    ///
    /// If the class registry state is inaccessible, an error is returned.
    ///
    /// If an exception is raised on the interpreter, then an error is returned.
    fn new_instance<T>(&mut self, args: &[Self::Value]) -> Result<Option<Self::Value>, Self::Error>
    where
        T: Any;
}