1use crate::Table;
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::Actor";
15
16const INITIAL_LEVEL_FIELD: &[u8] = b"@initial_level";
17const ARMOR4_ID_FIELD: &[u8] = b"@armor4_id";
18const WEAPON_ID_FIELD: &[u8] = b"@weapon_id";
19const CHARACTER_NAME_FIELD: &[u8] = b"@character_name";
20const NAME_FIELD: &[u8] = b"@name";
21const EXP_INFLATION_FIELD: &[u8] = b"@exp_inflation";
22const PARAMETERS_FIELD: &[u8] = b"@parameters";
23const ARMOR2_FIX_FIELD: &[u8] = b"@armor2_fix";
24const CLASS_ID_FIELD: &[u8] = b"@class_id";
25const ARMOR3_ID_FIELD: &[u8] = b"@armor3_id";
26const ARMOR1_FIX_FIELD: &[u8] = b"@armor1_fix";
27const EXP_BASIS_FIELD: &[u8] = b"@exp_basis";
28const ARMOR2_ID_FIELD: &[u8] = b"@armor2_id";
29const BATTLER_HUE_FIELD: &[u8] = b"@battler_hue";
30const ARMOR4_FIX_FIELD: &[u8] = b"@armor4_fix";
31const FINAL_LEVEL_FIELD: &[u8] = b"@final_level";
32const WEAPON_FIX_FIELD: &[u8] = b"@weapon_fix";
33const ARMOR1_ID_FIELD: &[u8] = b"@armor1_id";
34const ID_FIELD: &[u8] = b"@id";
35const CHARACTER_HUE_FIELD: &[u8] = b"@character_hue";
36const BATTLER_NAME_FIELD: &[u8] = b"@battler_name";
37const ARMOR3_FIX_FIELD: &[u8] = b"@armor3_fix";
38
39#[derive(Debug, serde::Serialize, serde::Deserialize)]
40pub struct Actor {
41 pub initial_level: i32,
42 pub armor4_id: i32,
43 pub weapon_id: i32,
44 pub character_name: String,
45 pub name: String,
46 pub exp_inflation: i32,
47 pub parameters: Table,
48 pub armor2_fix: bool,
49 pub class_id: i32,
50 pub armor3_id: i32,
51 pub armor1_fix: bool,
52 pub exp_basis: i32,
53 pub armor2_id: i32,
54 pub battler_hue: i32,
55 pub armor4_fix: bool,
56 pub final_level: i32,
57 pub weapon_fix: bool,
58 pub armor1_id: i32,
59 pub id: i32,
60 pub character_hue: i32,
61 pub battler_name: String,
62 pub armor3_fix: bool,
63}
64
65impl<'a> FromValue<'a> for Actor {
66 fn from_value(ctx: &FromValueContext<'a>, value: &Value) -> Result<Self, FromValueError> {
67 let object: &ObjectValue = FromValue::from_value(ctx, value)?;
68 let name = object.name();
69 let name: &SymbolValue = ctx.from_value(name.into())?;
70 let name = name.value();
71
72 if name != OBJECT_NAME {
73 return Err(FromValueError::UnexpectedObjectName { name: name.into() });
74 }
75
76 let instance_variables = object.instance_variables();
77
78 let mut initial_level_field = None;
79 let mut armor4_id_field = None;
80 let mut weapon_id_field = None;
81 let mut character_name_field = None;
82 let mut name_field = None;
83 let mut exp_inflation_field = None;
84 let mut parameters_field = None;
85 let mut armor2_fix_field = None;
86 let mut class_id_field = None;
87 let mut armor3_id_field = None;
88 let mut armor1_fix_field = None;
89 let mut exp_basis_field = None;
90 let mut armor2_id_field = None;
91 let mut battler_hue_field = None;
92 let mut armor4_fix_field = None;
93 let mut final_level_field = None;
94 let mut weapon_fix_field = None;
95 let mut armor1_id_field = None;
96 let mut id_field = None;
97 let mut character_hue_field = None;
98 let mut battler_name_field = None;
99 let mut armor3_fix_field = None;
100
101 for (key, value) in instance_variables.iter().copied() {
102 let key: &SymbolValue = ctx.from_value(key.into())?;
103 let key = key.value();
104
105 match key {
106 INITIAL_LEVEL_FIELD => {
107 if initial_level_field.is_some() {
108 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
109 }
110
111 let value: i32 = ctx.from_value(value)?;
112 initial_level_field = Some(value);
113 }
114 ARMOR4_ID_FIELD => {
115 if armor4_id_field.is_some() {
116 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
117 }
118 let value: i32 = ctx.from_value(value)?;
119 armor4_id_field = Some(value);
120 }
121 WEAPON_ID_FIELD => {
122 if weapon_id_field.is_some() {
123 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
124 }
125 let value: i32 = ctx.from_value(value)?;
126 weapon_id_field = Some(value);
127 }
128 CHARACTER_NAME_FIELD => {
129 if character_name_field.is_some() {
130 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
131 }
132 let value: &StringValue = ctx.from_value(value)?;
133 let value = std::str::from_utf8(value.value())
134 .map_err(FromValueError::new_other)?
135 .to_string();
136 character_name_field = Some(value);
137 }
138 NAME_FIELD => {
139 if name_field.is_some() {
140 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
141 }
142 let value: &StringValue = ctx.from_value(value)?;
143 let value = std::str::from_utf8(value.value())
144 .map_err(FromValueError::new_other)?
145 .to_string();
146 name_field = Some(value);
147 }
148 EXP_INFLATION_FIELD => {
149 if exp_inflation_field.is_some() {
150 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
151 }
152 let value: i32 = ctx.from_value(value)?;
153 exp_inflation_field = Some(value);
154 }
155 PARAMETERS_FIELD => {
156 if parameters_field.is_some() {
157 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
158 }
159 let value: Table = ctx.from_value(value)?;
160 parameters_field = Some(value);
161 }
162 ARMOR2_FIX_FIELD => {
163 if armor2_fix_field.is_some() {
164 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
165 }
166 let value: bool = ctx.from_value(value)?;
167 armor2_fix_field = Some(value);
168 }
169 CLASS_ID_FIELD => {
170 if class_id_field.is_some() {
171 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
172 }
173 let value: i32 = ctx.from_value(value)?;
174 class_id_field = Some(value);
175 }
176 ARMOR3_ID_FIELD => {
177 if armor3_id_field.is_some() {
178 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
179 }
180 let value: i32 = ctx.from_value(value)?;
181 armor3_id_field = Some(value);
182 }
183 ARMOR1_FIX_FIELD => {
184 if armor1_fix_field.is_some() {
185 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
186 }
187 let value: bool = ctx.from_value(value)?;
188 armor1_fix_field = Some(value);
189 }
190 EXP_BASIS_FIELD => {
191 if exp_basis_field.is_some() {
192 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
193 }
194 let value: i32 = ctx.from_value(value)?;
195 exp_basis_field = Some(value);
196 }
197 ARMOR2_ID_FIELD => {
198 if armor2_id_field.is_some() {
199 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
200 }
201 let value: i32 = ctx.from_value(value)?;
202 armor2_id_field = Some(value);
203 }
204 BATTLER_HUE_FIELD => {
205 if battler_hue_field.is_some() {
206 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
207 }
208 let value: i32 = ctx.from_value(value)?;
209 battler_hue_field = Some(value);
210 }
211 ARMOR4_FIX_FIELD => {
212 if armor4_fix_field.is_some() {
213 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
214 }
215 let value: bool = ctx.from_value(value)?;
216 armor4_fix_field = Some(value);
217 }
218 FINAL_LEVEL_FIELD => {
219 if final_level_field.is_some() {
220 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
221 }
222 let value: i32 = ctx.from_value(value)?;
223 final_level_field = Some(value);
224 }
225 WEAPON_FIX_FIELD => {
226 if weapon_fix_field.is_some() {
227 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
228 }
229 let value: bool = ctx.from_value(value)?;
230 weapon_fix_field = Some(value);
231 }
232 ARMOR1_ID_FIELD => {
233 if armor1_id_field.is_some() {
234 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
235 }
236 let value: i32 = ctx.from_value(value)?;
237 armor1_id_field = Some(value);
238 }
239 ID_FIELD => {
240 if id_field.is_some() {
241 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
242 }
243 let value: i32 = ctx.from_value(value)?;
244 id_field = Some(value);
245 }
246 CHARACTER_HUE_FIELD => {
247 if character_hue_field.is_some() {
248 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
249 }
250 let value: i32 = ctx.from_value(value)?;
251 character_hue_field = Some(value);
252 }
253 BATTLER_NAME_FIELD => {
254 if battler_name_field.is_some() {
255 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
256 }
257 let value: &StringValue = ctx.from_value(value)?;
258 let value = std::str::from_utf8(value.value())
259 .map_err(FromValueError::new_other)?
260 .to_string();
261 battler_name_field = Some(value);
262 }
263 ARMOR3_FIX_FIELD => {
264 if armor3_fix_field.is_some() {
265 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
266 }
267 let value: bool = ctx.from_value(value)?;
268 armor3_fix_field = Some(value);
269 }
270 _ => {
271 return Err(FromValueError::UnknownInstanceVariable { name: key.into() });
272 }
273 }
274 }
275
276 let initial_level =
277 initial_level_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
278 name: INITIAL_LEVEL_FIELD.into(),
279 })?;
280 let armor4_id = armor4_id_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
281 name: ARMOR4_ID_FIELD.into(),
282 })?;
283 let weapon_id = weapon_id_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
284 name: WEAPON_ID_FIELD.into(),
285 })?;
286 let character_name =
287 character_name_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
288 name: CHARACTER_NAME_FIELD.into(),
289 })?;
290 let name = name_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
291 name: NAME_FIELD.into(),
292 })?;
293 let exp_inflation =
294 exp_inflation_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
295 name: EXP_INFLATION_FIELD.into(),
296 })?;
297 let parameters =
298 parameters_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
299 name: PARAMETERS_FIELD.into(),
300 })?;
301 let armor2_fix =
302 armor2_fix_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
303 name: ARMOR2_FIX_FIELD.into(),
304 })?;
305 let class_id = class_id_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
306 name: CLASS_ID_FIELD.into(),
307 })?;
308 let armor3_id = armor3_id_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
309 name: ARMOR3_ID_FIELD.into(),
310 })?;
311 let armor1_fix =
312 armor1_fix_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
313 name: ARMOR1_FIX_FIELD.into(),
314 })?;
315 let exp_basis = exp_basis_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
316 name: EXP_BASIS_FIELD.into(),
317 })?;
318 let armor2_id = armor2_id_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
319 name: ARMOR2_ID_FIELD.into(),
320 })?;
321 let battler_hue =
322 battler_hue_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
323 name: BATTLER_HUE_FIELD.into(),
324 })?;
325 let armor4_fix =
326 armor4_fix_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
327 name: ARMOR4_FIX_FIELD.into(),
328 })?;
329 let final_level =
330 final_level_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
331 name: FINAL_LEVEL_FIELD.into(),
332 })?;
333 let weapon_fix =
334 weapon_fix_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
335 name: WEAPON_FIX_FIELD.into(),
336 })?;
337 let armor1_id = armor1_id_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
338 name: ARMOR1_ID_FIELD.into(),
339 })?;
340 let id = id_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
341 name: ID_FIELD.into(),
342 })?;
343 let character_hue =
344 character_hue_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
345 name: CHARACTER_HUE_FIELD.into(),
346 })?;
347 let battler_name =
348 battler_name_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
349 name: BATTLER_NAME_FIELD.into(),
350 })?;
351 let armor3_fix =
352 armor3_fix_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
353 name: ARMOR3_FIX_FIELD.into(),
354 })?;
355
356 Ok(Self {
357 initial_level,
358 armor4_id,
359 weapon_id,
360 character_name,
361 name,
362 exp_inflation,
363 parameters,
364 armor2_fix,
365 class_id,
366 armor3_id,
367 armor1_fix,
368 exp_basis,
369 armor2_id,
370 battler_hue,
371 armor4_fix,
372 final_level,
373 weapon_fix,
374 armor1_id,
375 id,
376 character_hue,
377 battler_name,
378 armor3_fix,
379 })
380 }
381}
382
383impl IntoValue for Actor {
384 fn into_value(self, arena: &mut ValueArena) -> Result<ValueHandle, IntoValueError> {
385 let object_name = arena.create_symbol(OBJECT_NAME.into());
386
387 let initial_level_field_key = arena.create_symbol(INITIAL_LEVEL_FIELD.into());
388 let armor4_id_field_key = arena.create_symbol(ARMOR4_ID_FIELD.into());
389 let weapon_id_field_key = arena.create_symbol(WEAPON_ID_FIELD.into());
390 let character_name_field_key = arena.create_symbol(CHARACTER_NAME_FIELD.into());
391 let name_field_key = arena.create_symbol(NAME_FIELD.into());
392 let exp_inflation_field_key = arena.create_symbol(EXP_INFLATION_FIELD.into());
393 let parameters_field_key = arena.create_symbol(PARAMETERS_FIELD.into());
394 let armor2_fix_field_key = arena.create_symbol(ARMOR2_FIX_FIELD.into());
395 let class_id_field_key = arena.create_symbol(CLASS_ID_FIELD.into());
396 let armor3_id_field_key = arena.create_symbol(ARMOR3_ID_FIELD.into());
397 let armor1_fix_field_key = arena.create_symbol(ARMOR1_FIX_FIELD.into());
398 let exp_basis_field_key = arena.create_symbol(EXP_BASIS_FIELD.into());
399 let armor2_id_field_key = arena.create_symbol(ARMOR2_ID_FIELD.into());
400 let battler_hue_field_key = arena.create_symbol(BATTLER_HUE_FIELD.into());
401 let armor4_fix_field_key = arena.create_symbol(ARMOR4_FIX_FIELD.into());
402 let final_level_field_key = arena.create_symbol(FINAL_LEVEL_FIELD.into());
403 let weapon_fix_field_key = arena.create_symbol(WEAPON_FIX_FIELD.into());
404 let armor1_id_field_key = arena.create_symbol(ARMOR1_ID_FIELD.into());
405 let id_field_key = arena.create_symbol(ID_FIELD.into());
406 let character_hue_field_key = arena.create_symbol(CHARACTER_HUE_FIELD.into());
407 let battler_name_field_key = arena.create_symbol(BATTLER_NAME_FIELD.into());
408 let armor3_fix_field_key = arena.create_symbol(ARMOR3_FIX_FIELD.into());
409
410 let initial_level_field_value = self.initial_level.into_value(arena)?;
411 let armor4_id_field_value = self.armor4_id.into_value(arena)?;
412 let weapon_id_field_value = self.weapon_id.into_value(arena)?;
413 let character_name_field_value = arena.create_string(self.character_name.into()).into();
414 let name_field_value = arena.create_string(self.name.into()).into();
415 let exp_inflation_field_value = self.exp_inflation.into_value(arena)?;
416 let parameters_field_value = self.parameters.into_value(arena)?;
417 let armor2_fix_field_value = self.armor2_fix.into_value(arena)?;
418 let class_id_field_value = self.class_id.into_value(arena)?;
419 let armor3_id_field_value = self.armor3_id.into_value(arena)?;
420 let armor1_fix_field_value = self.armor1_fix.into_value(arena)?;
421 let exp_basis_field_value = self.exp_basis.into_value(arena)?;
422 let armor2_id_field_value = self.armor2_id.into_value(arena)?;
423 let battler_hue_field_value = self.battler_hue.into_value(arena)?;
424 let armor4_fix_field_value = self.armor4_fix.into_value(arena)?;
425 let final_level_field_value = self.final_level.into_value(arena)?;
426 let weapon_fix_field_value = self.weapon_fix.into_value(arena)?;
427 let armor1_id_field_value = self.armor1_id.into_value(arena)?;
428 let id_field_value = self.id.into_value(arena)?;
429 let character_hue_field_value = self.character_hue.into_value(arena)?;
430 let battler_name_field_value = arena.create_string(self.battler_name.into()).into();
431 let armor3_fix_field_value = self.armor3_fix.into_value(arena)?;
432
433 let fields = vec![
434 (initial_level_field_key, initial_level_field_value),
435 (armor4_id_field_key, armor4_id_field_value),
436 (weapon_id_field_key, weapon_id_field_value),
437 (character_name_field_key, character_name_field_value),
438 (name_field_key, name_field_value),
439 (exp_inflation_field_key, exp_inflation_field_value),
440 (parameters_field_key, parameters_field_value),
441 (armor2_fix_field_key, armor2_fix_field_value),
442 (class_id_field_key, class_id_field_value),
443 (armor3_id_field_key, armor3_id_field_value),
444 (armor1_fix_field_key, armor1_fix_field_value),
445 (exp_basis_field_key, exp_basis_field_value),
446 (armor2_id_field_key, armor2_id_field_value),
447 (battler_hue_field_key, battler_hue_field_value),
448 (armor4_fix_field_key, armor4_fix_field_value),
449 (final_level_field_key, final_level_field_value),
450 (weapon_fix_field_key, weapon_fix_field_value),
451 (armor1_id_field_key, armor1_id_field_value),
452 (id_field_key, id_field_value),
453 (character_hue_field_key, character_hue_field_value),
454 (battler_name_field_key, battler_name_field_value),
455 (armor3_fix_field_key, armor3_fix_field_value),
456 ];
457
458 let object = arena.create_object(object_name, fields);
459
460 Ok(object.into())
461 }
462}