rpgmxp_types/
event_command.rs

1use crate::EventCommandParameter;
2use ruby_marshal::FromValue;
3use ruby_marshal::FromValueContext;
4use ruby_marshal::FromValueError;
5use ruby_marshal::IntoValue;
6use ruby_marshal::IntoValueError;
7use ruby_marshal::ObjectValue;
8use ruby_marshal::SymbolValue;
9use ruby_marshal::Value;
10use ruby_marshal::ValueArena;
11use ruby_marshal::ValueHandle;
12
13const OBJECT_NAME: &[u8] = b"RPG::EventCommand";
14
15const PARAMETERS_FIELD: &[u8] = b"@parameters";
16const CODE_FIELD: &[u8] = b"@code";
17const INDENT_FIELD: &[u8] = b"@indent";
18
19/// An Event Command
20#[derive(Debug, serde::Serialize, serde::Deserialize)]
21pub struct EventCommand {
22    /// Event Command Parameters
23    pub parameters: Vec<EventCommandParameter>,
24    /// The indent
25    pub indent: i32,
26    /// The command code
27    pub code: i32,
28}
29
30impl<'a> FromValue<'a> for EventCommand {
31    fn from_value(ctx: &FromValueContext<'a>, value: &Value) -> Result<Self, FromValueError> {
32        let object: &ObjectValue = FromValue::from_value(ctx, value)?;
33        let name = object.name();
34        let name: &SymbolValue = ctx.from_value(name.into())?;
35        let name = name.value();
36
37        if name != OBJECT_NAME {
38            return Err(FromValueError::UnexpectedObjectName { name: name.into() });
39        }
40
41        let instance_variables = object.instance_variables();
42
43        let mut parameters_field = None;
44        let mut indent_field = None;
45        let mut code_field = None;
46
47        for (key, value) in instance_variables.iter().copied() {
48            let key: &SymbolValue = ctx.from_value(key.into())?;
49            let key = key.value();
50
51            match key {
52                PARAMETERS_FIELD => {
53                    if parameters_field.is_some() {
54                        return Err(FromValueError::DuplicateInstanceVariable {
55                            name: PARAMETERS_FIELD.into(),
56                        });
57                    }
58
59                    parameters_field = Some(ctx.from_value(value)?);
60                }
61                CODE_FIELD => {
62                    if code_field.is_some() {
63                        return Err(FromValueError::DuplicateInstanceVariable {
64                            name: CODE_FIELD.into(),
65                        });
66                    }
67
68                    code_field = Some(ctx.from_value(value)?);
69                }
70                INDENT_FIELD => {
71                    if indent_field.is_some() {
72                        return Err(FromValueError::DuplicateInstanceVariable {
73                            name: INDENT_FIELD.into(),
74                        });
75                    }
76
77                    indent_field = Some(ctx.from_value(value)?);
78                }
79                _ => {
80                    return Err(FromValueError::UnknownInstanceVariable { name: key.into() });
81                }
82            }
83        }
84
85        let parameters =
86            parameters_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
87                name: PARAMETERS_FIELD.into(),
88            })?;
89        let indent = indent_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
90            name: INDENT_FIELD.into(),
91        })?;
92        let code = code_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
93            name: CODE_FIELD.into(),
94        })?;
95
96        Ok(Self {
97            parameters,
98            indent,
99            code,
100        })
101    }
102}
103
104impl IntoValue for EventCommand {
105    fn into_value(self, arena: &mut ValueArena) -> Result<ValueHandle, IntoValueError> {
106        let object_name = arena.create_symbol(OBJECT_NAME.into());
107
108        let parameters_field_key = arena.create_symbol(PARAMETERS_FIELD.into());
109        let code_field_key = arena.create_symbol(CODE_FIELD.into());
110        let indent_field_key = arena.create_symbol(INDENT_FIELD.into());
111
112        let parameters_field_value = self.parameters.into_value(arena)?;
113        let code_field_value = self.code.into_value(arena)?;
114        let indent_field_value = self.indent.into_value(arena)?;
115
116        let fields = vec![
117            (parameters_field_key, parameters_field_value),
118            (code_field_key, code_field_value),
119            (indent_field_key, indent_field_value),
120        ];
121
122        let object = arena.create_object(object_name, fields);
123
124        Ok(object.into())
125    }
126}