1use ruby_marshal::FromValue;
2use ruby_marshal::FromValueContext;
3use ruby_marshal::FromValueError;
4use ruby_marshal::IntoValue;
5use ruby_marshal::IntoValueError;
6use ruby_marshal::ObjectValue;
7use ruby_marshal::StringValue;
8use ruby_marshal::SymbolValue;
9use ruby_marshal::Value;
10use ruby_marshal::ValueArena;
11use ruby_marshal::ValueHandle;
12
13const OBJECT_NAME: &[u8] = b"RPG::System::Words";
14
15const STR_FIELD: &[u8] = b"@str";
16const ARMOR3_FIELD: &[u8] = b"@armor3";
17const MDEF_FIELD: &[u8] = b"@mdef";
18const GOLD_FIELD: &[u8] = b"@gold";
19const SP_FIELD: &[u8] = b"@sp";
20const SKILL_FIELD: &[u8] = b"@skill";
21const INT_FIELD: &[u8] = b"@int";
22const ARMOR2_FIELD: &[u8] = b"@armor2";
23const EQUIP_FIELD: &[u8] = b"@equip";
24const HP_FIELD: &[u8] = b"@hp";
25const PDEF_FIELD: &[u8] = b"@pdef";
26const ATTACK_FIELD: &[u8] = b"@attack";
27const AGI_FIELD: &[u8] = b"@agi";
28const ARMOR1_FIELD: &[u8] = b"@armor1";
29const ATK_FIELD: &[u8] = b"@atk";
30const ITEM_FIELD: &[u8] = b"@item";
31const DEX_FIELD: &[u8] = b"@dex";
32const ARMOR4_FIELD: &[u8] = b"@armor4";
33const WEAPON_FIELD: &[u8] = b"@weapon";
34const GUARD_FIELD: &[u8] = b"@guard";
35
36#[derive(Debug, serde::Serialize, serde::Deserialize)]
37pub struct SystemWords {
38 pub str_: String,
39 pub armor3: String,
40 pub mdef: String,
41 pub gold: String,
42 pub sp: String,
43 pub skill: String,
44 pub int: String,
45 pub armor2: String,
46 pub equip: String,
47 pub hp: String,
48 pub pdef: String,
49 pub attack: String,
50 pub agi: String,
51 pub armor1: String,
52 pub atk: String,
53 pub item: String,
54 pub dex: String,
55 pub armor4: String,
56 pub weapon: String,
57 pub guard: String,
58}
59
60impl<'a> FromValue<'a> for SystemWords {
61 fn from_value(ctx: &FromValueContext<'a>, value: &Value) -> Result<Self, FromValueError> {
62 let object: &ObjectValue = FromValue::from_value(ctx, value)?;
63 let name = object.name();
64 let name: &SymbolValue = ctx.from_value(name.into())?;
65 let name = name.value();
66
67 if name != OBJECT_NAME {
68 return Err(FromValueError::UnexpectedObjectName { name: name.into() });
69 }
70
71 let instance_variables = object.instance_variables();
72
73 let mut str_field = None;
74 let mut armor3_field = None;
75 let mut mdef_field = None;
76 let mut gold_field = None;
77 let mut sp_field = None;
78 let mut skill_field = None;
79 let mut int_field = None;
80 let mut armor2_field = None;
81 let mut equip_field = None;
82 let mut hp_field = None;
83 let mut pdef_field = None;
84 let mut attack_field = None;
85 let mut agi_field = None;
86 let mut armor1_field = None;
87 let mut atk_field = None;
88 let mut item_field = None;
89 let mut dex_field = None;
90 let mut armor4_field = None;
91 let mut weapon_field = None;
92 let mut guard_field = None;
93
94 for (key, value) in instance_variables.iter().copied() {
95 let key: &SymbolValue = ctx.from_value(key.into())?;
96 let key = key.value();
97
98 match key {
99 STR_FIELD => {
100 if str_field.is_some() {
101 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
102 }
103
104 let str_: &StringValue = ctx.from_value(value)?;
105 let str_ = std::str::from_utf8(str_.value())
106 .map_err(FromValueError::new_other)?
107 .to_string();
108 str_field = Some(str_);
109 }
110 ARMOR3_FIELD => {
111 if armor3_field.is_some() {
112 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
113 }
114
115 let armor3: &StringValue = ctx.from_value(value)?;
116 let armor3 = std::str::from_utf8(armor3.value())
117 .map_err(FromValueError::new_other)?
118 .to_string();
119 armor3_field = Some(armor3);
120 }
121 MDEF_FIELD => {
122 if mdef_field.is_some() {
123 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
124 }
125
126 let mdef: &StringValue = ctx.from_value(value)?;
127 let mdef = std::str::from_utf8(mdef.value())
128 .map_err(FromValueError::new_other)?
129 .to_string();
130 mdef_field = Some(mdef);
131 }
132 GOLD_FIELD => {
133 if gold_field.is_some() {
134 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
135 }
136
137 let gold: &StringValue = ctx.from_value(value)?;
138 let gold = std::str::from_utf8(gold.value())
139 .map_err(FromValueError::new_other)?
140 .to_string();
141 gold_field = Some(gold);
142 }
143 SP_FIELD => {
144 if sp_field.is_some() {
145 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
146 }
147
148 let sp: &StringValue = ctx.from_value(value)?;
149 let sp = std::str::from_utf8(sp.value())
150 .map_err(FromValueError::new_other)?
151 .to_string();
152 sp_field = Some(sp);
153 }
154 SKILL_FIELD => {
155 if skill_field.is_some() {
156 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
157 }
158
159 let skill: &StringValue = ctx.from_value(value)?;
160 let skill = std::str::from_utf8(skill.value())
161 .map_err(FromValueError::new_other)?
162 .to_string();
163 skill_field = Some(skill);
164 }
165 INT_FIELD => {
166 if int_field.is_some() {
167 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
168 }
169
170 let int: &StringValue = ctx.from_value(value)?;
171 let int = std::str::from_utf8(int.value())
172 .map_err(FromValueError::new_other)?
173 .to_string();
174 int_field = Some(int);
175 }
176 ARMOR2_FIELD => {
177 if armor2_field.is_some() {
178 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
179 }
180
181 let armor2: &StringValue = ctx.from_value(value)?;
182 let armor2 = std::str::from_utf8(armor2.value())
183 .map_err(FromValueError::new_other)?
184 .to_string();
185 armor2_field = Some(armor2);
186 }
187 EQUIP_FIELD => {
188 if equip_field.is_some() {
189 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
190 }
191
192 let equip: &StringValue = ctx.from_value(value)?;
193 let equip = std::str::from_utf8(equip.value())
194 .map_err(FromValueError::new_other)?
195 .to_string();
196 equip_field = Some(equip);
197 }
198 HP_FIELD => {
199 if hp_field.is_some() {
200 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
201 }
202
203 let hp: &StringValue = ctx.from_value(value)?;
204 let hp = std::str::from_utf8(hp.value())
205 .map_err(FromValueError::new_other)?
206 .to_string();
207 hp_field = Some(hp);
208 }
209 PDEF_FIELD => {
210 if pdef_field.is_some() {
211 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
212 }
213
214 let pdef: &StringValue = ctx.from_value(value)?;
215 let pdef = std::str::from_utf8(pdef.value())
216 .map_err(FromValueError::new_other)?
217 .to_string();
218 pdef_field = Some(pdef);
219 }
220 ATTACK_FIELD => {
221 if attack_field.is_some() {
222 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
223 }
224
225 let attack: &StringValue = ctx.from_value(value)?;
226 let attack = std::str::from_utf8(attack.value())
227 .map_err(FromValueError::new_other)?
228 .to_string();
229 attack_field = Some(attack);
230 }
231 AGI_FIELD => {
232 if agi_field.is_some() {
233 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
234 }
235
236 let agi: &StringValue = ctx.from_value(value)?;
237 let agi = std::str::from_utf8(agi.value())
238 .map_err(FromValueError::new_other)?
239 .to_string();
240 agi_field = Some(agi);
241 }
242 ARMOR1_FIELD => {
243 if armor1_field.is_some() {
244 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
245 }
246
247 let armor1: &StringValue = ctx.from_value(value)?;
248 let armor1 = std::str::from_utf8(armor1.value())
249 .map_err(FromValueError::new_other)?
250 .to_string();
251 armor1_field = Some(armor1);
252 }
253 ATK_FIELD => {
254 if atk_field.is_some() {
255 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
256 }
257
258 let atk: &StringValue = ctx.from_value(value)?;
259 let atk = std::str::from_utf8(atk.value())
260 .map_err(FromValueError::new_other)?
261 .to_string();
262 atk_field = Some(atk);
263 }
264 ITEM_FIELD => {
265 if item_field.is_some() {
266 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
267 }
268
269 let item: &StringValue = ctx.from_value(value)?;
270 let item = std::str::from_utf8(item.value())
271 .map_err(FromValueError::new_other)?
272 .to_string();
273 item_field = Some(item);
274 }
275 DEX_FIELD => {
276 if dex_field.is_some() {
277 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
278 }
279
280 let dex: &StringValue = ctx.from_value(value)?;
281 let dex = std::str::from_utf8(dex.value())
282 .map_err(FromValueError::new_other)?
283 .to_string();
284 dex_field = Some(dex);
285 }
286 ARMOR4_FIELD => {
287 if armor4_field.is_some() {
288 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
289 }
290
291 let armor4: &StringValue = ctx.from_value(value)?;
292 let armor4 = std::str::from_utf8(armor4.value())
293 .map_err(FromValueError::new_other)?
294 .to_string();
295 armor4_field = Some(armor4);
296 }
297 WEAPON_FIELD => {
298 if weapon_field.is_some() {
299 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
300 }
301
302 let weapon: &StringValue = ctx.from_value(value)?;
303 let weapon = std::str::from_utf8(weapon.value())
304 .map_err(FromValueError::new_other)?
305 .to_string();
306 weapon_field = Some(weapon);
307 }
308 GUARD_FIELD => {
309 if guard_field.is_some() {
310 return Err(FromValueError::DuplicateInstanceVariable { name: key.into() });
311 }
312
313 let guard: &StringValue = ctx.from_value(value)?;
314 let guard = std::str::from_utf8(guard.value())
315 .map_err(FromValueError::new_other)?
316 .to_string();
317 guard_field = Some(guard);
318 }
319 _ => {
320 return Err(FromValueError::UnknownInstanceVariable { name: key.into() });
321 }
322 }
323 }
324
325 let str_ = str_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
326 name: STR_FIELD.into(),
327 })?;
328 let armor3 = armor3_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
329 name: ARMOR3_FIELD.into(),
330 })?;
331 let mdef = mdef_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
332 name: MDEF_FIELD.into(),
333 })?;
334 let gold = gold_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
335 name: GOLD_FIELD.into(),
336 })?;
337 let sp = sp_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
338 name: SP_FIELD.into(),
339 })?;
340 let skill = skill_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
341 name: SKILL_FIELD.into(),
342 })?;
343 let int = int_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
344 name: INT_FIELD.into(),
345 })?;
346 let armor2 = armor2_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
347 name: ARMOR2_FIELD.into(),
348 })?;
349 let equip = equip_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
350 name: EQUIP_FIELD.into(),
351 })?;
352 let hp = hp_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
353 name: HP_FIELD.into(),
354 })?;
355 let pdef = pdef_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
356 name: PDEF_FIELD.into(),
357 })?;
358 let attack = attack_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
359 name: ATTACK_FIELD.into(),
360 })?;
361 let agi = agi_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
362 name: AGI_FIELD.into(),
363 })?;
364 let armor1 = armor1_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
365 name: ARMOR1_FIELD.into(),
366 })?;
367 let atk = atk_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
368 name: ATK_FIELD.into(),
369 })?;
370 let item = item_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
371 name: ITEM_FIELD.into(),
372 })?;
373 let dex = dex_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
374 name: DEX_FIELD.into(),
375 })?;
376 let armor4 = armor4_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
377 name: ARMOR4_FIELD.into(),
378 })?;
379 let weapon = weapon_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
380 name: WEAPON_FIELD.into(),
381 })?;
382 let guard = guard_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
383 name: GUARD_FIELD.into(),
384 })?;
385
386 Ok(Self {
387 str_,
388 armor3,
389 mdef,
390 gold,
391 sp,
392 skill,
393 int,
394 armor2,
395 equip,
396 hp,
397 pdef,
398 attack,
399 agi,
400 armor1,
401 atk,
402 item,
403 dex,
404 armor4,
405
406 weapon,
407 guard,
408 })
409 }
410}
411
412impl IntoValue for SystemWords {
413 fn into_value(self, arena: &mut ValueArena) -> Result<ValueHandle, IntoValueError> {
414 let object_name = arena.create_symbol(OBJECT_NAME.into());
415
416 let str_field_key = arena.create_symbol(STR_FIELD.into());
417 let armor3_field_key = arena.create_symbol(ARMOR3_FIELD.into());
418 let mdef_field_key = arena.create_symbol(MDEF_FIELD.into());
419 let gold_field_key = arena.create_symbol(GOLD_FIELD.into());
420 let sp_field_key = arena.create_symbol(SP_FIELD.into());
421 let skill_field_key = arena.create_symbol(SKILL_FIELD.into());
422 let int_field_key = arena.create_symbol(INT_FIELD.into());
423 let armor2_field_key = arena.create_symbol(ARMOR2_FIELD.into());
424 let equip_field_key = arena.create_symbol(EQUIP_FIELD.into());
425 let hp_field_key = arena.create_symbol(HP_FIELD.into());
426 let pdef_field_key = arena.create_symbol(PDEF_FIELD.into());
427 let attack_field_key = arena.create_symbol(ATTACK_FIELD.into());
428 let agi_field_key = arena.create_symbol(AGI_FIELD.into());
429 let armor1_field_key = arena.create_symbol(ARMOR1_FIELD.into());
430 let atk_field_key = arena.create_symbol(ATK_FIELD.into());
431 let item_field_key = arena.create_symbol(ITEM_FIELD.into());
432 let dex_field_key = arena.create_symbol(DEX_FIELD.into());
433 let armor4_field_key = arena.create_symbol(ARMOR4_FIELD.into());
434 let weapon_field_key = arena.create_symbol(WEAPON_FIELD.into());
435 let guard_field_key = arena.create_symbol(GUARD_FIELD.into());
436
437 let str_field_value = arena.create_string(self.str_.into()).into();
438 let armor3_field_value = arena.create_string(self.armor3.into()).into();
439 let mdef_field_value = arena.create_string(self.mdef.into()).into();
440 let gold_field_value = arena.create_string(self.gold.into()).into();
441 let sp_field_value = arena.create_string(self.sp.into()).into();
442 let skill_field_value = arena.create_string(self.skill.into()).into();
443 let int_field_value = arena.create_string(self.int.into()).into();
444 let armor2_field_value = arena.create_string(self.armor2.into()).into();
445 let equip_field_value = arena.create_string(self.equip.into()).into();
446 let hp_field_value = arena.create_string(self.hp.into()).into();
447 let pdef_field_value = arena.create_string(self.pdef.into()).into();
448 let attack_field_value = arena.create_string(self.attack.into()).into();
449 let agi_field_value = arena.create_string(self.agi.into()).into();
450 let armor1_field_value = arena.create_string(self.armor1.into()).into();
451 let atk_field_value = arena.create_string(self.atk.into()).into();
452 let item_field_value = arena.create_string(self.item.into()).into();
453 let dex_field_value = arena.create_string(self.dex.into()).into();
454 let armor4_field_value = arena.create_string(self.armor4.into()).into();
455 let weapon_field_value = arena.create_string(self.weapon.into()).into();
456 let guard_field_value = arena.create_string(self.guard.into()).into();
457
458 let fields = vec![
459 (str_field_key, str_field_value),
460 (armor3_field_key, armor3_field_value),
461 (mdef_field_key, mdef_field_value),
462 (gold_field_key, gold_field_value),
463 (sp_field_key, sp_field_value),
464 (skill_field_key, skill_field_value),
465 (int_field_key, int_field_value),
466 (armor2_field_key, armor2_field_value),
467 (equip_field_key, equip_field_value),
468 (hp_field_key, hp_field_value),
469 (pdef_field_key, pdef_field_value),
470 (attack_field_key, attack_field_value),
471 (agi_field_key, agi_field_value),
472 (armor1_field_key, armor1_field_value),
473 (atk_field_key, atk_field_value),
474 (item_field_key, item_field_value),
475 (dex_field_key, dex_field_value),
476 (armor4_field_key, armor4_field_value),
477 (weapon_field_key, weapon_field_value),
478 (guard_field_key, guard_field_value),
479 ];
480
481 let object = arena.create_object(object_name, fields);
482
483 Ok(object.into())
484 }
485}