rpgmxp_types/
event.rs

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