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}