plugger_core/
lib.rs

1pub type TypeName = &'static str;
2
3#[derive(Clone)]
4pub struct Parameter {
5    pub name: String,
6    pub ty: TypeName,
7}
8
9#[derive(Clone)]
10pub struct Method
11{
12    /// A pointer to the function.
13    pub method_pointer: *mut fn(),
14    /// Marshall functions for every supported language.
15    // NOTE: This is a vec and not a hash map because it's easier to construct
16    // a Vec inside a syntax extension.
17    pub lang_marshalls: Vec<(&'static str, *mut fn())>,
18
19    /// The name of the method.
20    pub name: &'static str,
21    /// The parameter list.
22    pub parameters: Vec<Parameter>,
23    /// The return type (if any).
24    pub ret: Option<TypeName>,
25
26    /// Whether the method has a receiver.
27    pub is_static: bool,
28}
29
30#[derive(Clone)]
31pub struct Field
32{
33    /// The number of bytes from the start of the structure.
34    pub field_offset: usize,
35
36    pub ty: TypeName,
37    pub name: &'static str,
38}
39
40#[derive(Clone)]
41pub struct Class
42{
43    pub name: String,
44    pub fields: Vec<Field>,
45    pub methods: Vec<Method>,
46}
47
48pub trait PluggableFields
49{
50    fn pluggable_fields(&self) -> Vec<Field>;
51}
52
53pub trait PluggableMethods
54{
55    fn pluggable_methods(&self) -> Vec<Method>;
56}
57
58/// An object that can marshall Rust values to an arbitrary value.
59pub trait Marshall
60{
61    type Value;
62
63    fn to_bool(value: Self::Value) -> bool;
64
65    fn to_u8(value: Self::Value) -> u8;
66    fn to_u16(value: Self::Value) -> u16;
67    fn to_u32(value: Self::Value) -> u32;
68    fn to_u64(value: Self::Value) -> u64;
69    fn to_i8(value: Self::Value) -> i8;
70    fn to_i16(value: Self::Value) -> i16;
71    fn to_i32(value: Self::Value) -> i32;
72    fn to_i64(value: Self::Value) -> i64;
73
74    fn to_f32(value: Self::Value) -> f32;
75    fn to_f64(value: Self::Value) -> f64;
76
77    fn to_string(value: Self::Value) -> String;
78}
79
80/// An object that can be plugged into a scripting language.
81///
82/// Can be automatically derived by placing `#[pluggable]` on a struct.
83///
84/// When implementing `Pluggable`, it is necessary to have both a `struct` and an
85/// `impl`, with both having the `#[pluggable]` attribute.
86///
87/// This has been split up into two other traits
88///
89/// * `PluggableFields`
90/// * `PluggableMethods
91///
92/// This is because the syntax extender can not see all of the code -
93/// it can only see the thing it's operating on. This is why we need
94/// an attribute on the `struct` and the `impl`. We can't implement
95/// a trait twice, each time overriding a specific method.
96///
97/// Because of this, it is necessary to mark both the `struct` and the `impl`
98/// with the `pluggable` attribute. It's not the prettiest, but it does work.
99pub trait Pluggable : PluggableFields + PluggableMethods
100{
101    fn name(&self) -> &'static str;
102
103    fn fields(&self) -> Vec<Field> { PluggableFields::pluggable_fields(self) }
104    fn methods(&self) -> Vec<Method> { PluggableMethods::pluggable_methods(self) }
105
106    fn class(&self) -> Class {
107        Class {
108            name: self.name().to_owned(),
109            fields: self.fields(),
110            methods: self.methods(),
111        }
112    }
113}
114
115impl Method {
116    /// Gets the marshall for a language.
117    pub fn marshall(&self, lang_name: &str) -> *mut fn() {
118        self.lang_marshalls.iter().find(|m| m.0 == lang_name).unwrap().1
119    }
120}
121