rpgmxp_types/
move_command.rs1use 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
13pub(crate) const OBJECT_NAME: &[u8] = b"RPG::MoveCommand";
14
15const PARAMETERS_FIELD: &[u8] = b"@parameters";
16const CODE_FIELD: &[u8] = b"@code";
17
18#[derive(Debug, serde::Serialize, serde::Deserialize)]
19pub struct MoveCommand {
20 pub parameters: Vec<EventCommandParameter>,
21 pub code: i32,
22}
23
24impl<'a> FromValue<'a> for MoveCommand {
25 fn from_value(ctx: &FromValueContext<'a>, value: &Value) -> Result<Self, FromValueError> {
26 let object: &ObjectValue = FromValue::from_value(ctx, value)?;
27
28 let name = object.name();
29 let name: &SymbolValue = ctx.from_value(name.into())?;
30 let name = name.value();
31
32 if name != OBJECT_NAME {
33 return Err(FromValueError::UnexpectedObjectName { name: name.into() });
34 }
35
36 let instance_variables = object.instance_variables();
37
38 let mut parameters_field = None;
39 let mut code_field = None;
40
41 for (key, value) in instance_variables.iter().copied() {
42 let key: &SymbolValue = ctx.from_value(key.into())?;
43 let key = key.value();
44
45 match key {
46 PARAMETERS_FIELD => {
47 if parameters_field.is_some() {
48 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
49 }
50
51 parameters_field = Some(ctx.from_value(value)?);
52 }
53 CODE_FIELD => {
54 if code_field.is_some() {
55 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
56 }
57
58 code_field = Some(ctx.from_value(value)?);
59 }
60 _ => {
61 return Err(FromValueError::UnknownInstanceVariable { name: key.into() });
62 }
63 }
64 }
65
66 let parameters =
67 parameters_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
68 name: PARAMETERS_FIELD.into(),
69 })?;
70 let code = code_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
71 name: CODE_FIELD.into(),
72 })?;
73
74 Ok(Self { parameters, code })
75 }
76}
77
78impl IntoValue for MoveCommand {
79 fn into_value(self, arena: &mut ValueArena) -> Result<ValueHandle, IntoValueError> {
80 let object_name = arena.create_symbol(OBJECT_NAME.into());
81
82 let parameters_field_key = arena.create_symbol(PARAMETERS_FIELD.into());
83 let code_field_key = arena.create_symbol(CODE_FIELD.into());
84
85 let parameters_field_value = self.parameters.into_value(arena)?;
86 let code_field_value = self.code.into_value(arena)?;
87
88 let fields = vec![
89 (parameters_field_key, parameters_field_value),
90 (code_field_key, code_field_value),
91 ];
92
93 let object = arena.create_object(object_name, fields);
94
95 Ok(object.into())
96 }
97}