rpgmxp_types/
common_event.rs

1use crate::EventCommand;
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::StringValue;
9use ruby_marshal::SymbolValue;
10use ruby_marshal::Value;
11use ruby_marshal::ValueArena;
12use ruby_marshal::ValueHandle;
13
14const OBJECT_NAME: &[u8] = b"RPG::CommonEvent";
15
16const NAME_FIELD: &[u8] = b"@name";
17const LIST_FIELD: &[u8] = b"@list";
18const TRIGGER_FIELD: &[u8] = b"@trigger";
19const SWITCH_ID_FIELD: &[u8] = b"@switch_id";
20const ID_FIELD: &[u8] = b"@id";
21
22#[derive(Debug, serde::Serialize, serde::Deserialize)]
23pub struct CommonEvent {
24    pub name: String,
25    pub list: Vec<EventCommand>,
26    pub trigger: i32,
27    pub switch_id: i32,
28    pub id: i32,
29}
30
31impl<'a> FromValue<'a> for CommonEvent {
32    fn from_value(ctx: &FromValueContext<'a>, value: &Value) -> Result<Self, FromValueError> {
33        let object: &ObjectValue = FromValue::from_value(ctx, value)?;
34        let name = object.name();
35        let name: &SymbolValue = ctx.from_value(name.into())?;
36        let name = name.value();
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 name_field = None;
44        let mut list_field = None;
45        let mut trigger_field = None;
46        let mut switch_id_field = None;
47        let mut id_field = None;
48
49        for (key, value) in instance_variables.iter().copied() {
50            let key: &SymbolValue = ctx.from_value(key.into())?;
51            let key = key.value();
52
53            match key {
54                NAME_FIELD => {
55                    if name_field.is_some() {
56                        return Err(FromValueError::DuplicateInstanceVariable {
57                            name: NAME_FIELD.into(),
58                        });
59                    }
60
61                    let name: &StringValue = ctx.from_value(value)?;
62                    let name =
63                        std::str::from_utf8(name.value()).map_err(FromValueError::new_other)?;
64
65                    name_field = Some(name.into());
66                }
67                LIST_FIELD => {
68                    if list_field.is_some() {
69                        return Err(FromValueError::DuplicateInstanceVariable {
70                            name: LIST_FIELD.into(),
71                        });
72                    }
73
74                    list_field = Some(ctx.from_value(value)?);
75                }
76                TRIGGER_FIELD => {
77                    if trigger_field.is_some() {
78                        return Err(FromValueError::DuplicateInstanceVariable {
79                            name: TRIGGER_FIELD.into(),
80                        });
81                    }
82
83                    trigger_field = Some(ctx.from_value(value)?);
84                }
85                SWITCH_ID_FIELD => {
86                    if switch_id_field.is_some() {
87                        return Err(FromValueError::DuplicateInstanceVariable {
88                            name: SWITCH_ID_FIELD.into(),
89                        });
90                    }
91
92                    switch_id_field = Some(ctx.from_value(value)?);
93                }
94                ID_FIELD => {
95                    if id_field.is_some() {
96                        return Err(FromValueError::DuplicateInstanceVariable {
97                            name: ID_FIELD.into(),
98                        });
99                    }
100
101                    id_field = Some(ctx.from_value(value)?);
102                }
103                _ => {
104                    return Err(FromValueError::UnknownInstanceVariable { name: key.into() });
105                }
106            }
107        }
108
109        let name = name_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
110            name: NAME_FIELD.into(),
111        })?;
112        let list = list_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
113            name: LIST_FIELD.into(),
114        })?;
115        let trigger = trigger_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
116            name: TRIGGER_FIELD.into(),
117        })?;
118        let switch_id = switch_id_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
119            name: SWITCH_ID_FIELD.into(),
120        })?;
121        let id = id_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
122            name: ID_FIELD.into(),
123        })?;
124
125        Ok(Self {
126            name,
127            list,
128            trigger,
129            switch_id,
130            id,
131        })
132    }
133}
134
135impl IntoValue for CommonEvent {
136    fn into_value(self, arena: &mut ValueArena) -> Result<ValueHandle, IntoValueError> {
137        let object_name = arena.create_symbol(OBJECT_NAME.into());
138
139        let name_field_key = arena.create_symbol(NAME_FIELD.into());
140        let list_field_key = arena.create_symbol(LIST_FIELD.into());
141        let trigger_field_key = arena.create_symbol(TRIGGER_FIELD.into());
142        let switch_id_field_key = arena.create_symbol(SWITCH_ID_FIELD.into());
143        let id_field_key = arena.create_symbol(ID_FIELD.into());
144
145        let name_field_value = arena.create_string(self.name.into()).into();
146        let list_field_value = self.list.into_value(arena)?;
147        let trigger_field_value = self.trigger.into_value(arena)?;
148        let switch_id_field_value = self.switch_id.into_value(arena)?;
149        let id_field_value = self.id.into_value(arena)?;
150
151        let fields = vec![
152            (name_field_key, name_field_value),
153            (list_field_key, list_field_value),
154            (trigger_field_key, trigger_field_value),
155            (switch_id_field_key, switch_id_field_value),
156            (id_field_key, id_field_value),
157        ];
158
159        let object = arena.create_object(object_name, fields);
160
161        Ok(object.into())
162    }
163}