rpgmxp_types/
move_route.rs1use crate::MoveCommand;
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::MoveRoute";
14
15const LIST_FIELD: &[u8] = b"@list";
16const SKIPPABLE_FIELD: &[u8] = b"@skippable";
17const REPEAT_FIELD: &[u8] = b"@repeat";
18
19#[derive(Debug, serde::Serialize, serde::Deserialize)]
20pub struct MoveRoute {
21 pub list: Vec<MoveCommand>,
22 pub skippable: bool,
23 pub repeat: bool,
24}
25
26impl<'a> FromValue<'a> for MoveRoute {
27 fn from_value(ctx: &FromValueContext<'a>, value: &Value) -> Result<Self, FromValueError> {
28 let object: &ObjectValue = FromValue::from_value(ctx, value)?;
29
30 let name = object.name();
31 let name: &SymbolValue = ctx.from_value(name.into())?;
32 let name = name.value();
33 if name != OBJECT_NAME {
34 return Err(FromValueError::UnexpectedObjectName { name: name.into() });
35 }
36
37 let instance_variables = object.instance_variables();
38
39 let mut list_field = None;
40 let mut skippable_field = None;
41 let mut repeat_field = None;
42
43 for (key, value) in instance_variables.iter().copied() {
44 let key: &SymbolValue = ctx.from_value(key.into())?;
45 let key = key.value();
46
47 match key {
48 LIST_FIELD => {
49 if list_field.is_some() {
50 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
51 }
52
53 list_field = Some(ctx.from_value(value)?);
54 }
55 SKIPPABLE_FIELD => {
56 if skippable_field.is_some() {
57 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
58 }
59
60 skippable_field = Some(ctx.from_value(value)?);
61 }
62 REPEAT_FIELD => {
63 if repeat_field.is_some() {
64 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
65 }
66
67 repeat_field = Some(ctx.from_value(value)?);
68 }
69 _ => {
70 return Err(FromValueError::UnknownInstanceVariable { name: key.into() });
71 }
72 }
73 }
74
75 let list = list_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
76 name: LIST_FIELD.into(),
77 })?;
78 let skippable = skippable_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
79 name: SKIPPABLE_FIELD.into(),
80 })?;
81 let repeat = repeat_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
82 name: REPEAT_FIELD.into(),
83 })?;
84
85 Ok(Self {
86 list,
87 skippable,
88 repeat,
89 })
90 }
91}
92
93impl IntoValue for MoveRoute {
94 fn into_value(self, arena: &mut ValueArena) -> Result<ValueHandle, IntoValueError> {
95 let object_name = arena.create_symbol(OBJECT_NAME.into());
96
97 let list_field_key = arena.create_symbol(LIST_FIELD.into());
98 let skippable_field_key = arena.create_symbol(SKIPPABLE_FIELD.into());
99 let repeat_field_key = arena.create_symbol(REPEAT_FIELD.into());
100
101 let list_field_value = self.list.into_value(arena)?;
102 let skippable_field_value = arena.create_bool(self.skippable);
103 let repeat_field_value = arena.create_bool(self.repeat);
104
105 let fields = vec![
106 (list_field_key, list_field_value),
107 (skippable_field_key, skippable_field_value.into()),
108 (repeat_field_key, repeat_field_value.into()),
109 ];
110
111 let object = arena.create_object(object_name, fields);
112
113 Ok(object.into())
114 }
115}