rpgmxp_types/
event_command_parameter.rs1use crate::AudioFile;
2use crate::Color;
3use crate::MoveCommand;
4use crate::MoveRoute;
5use crate::Tone;
6use ruby_marshal::DisplayByteString;
7use ruby_marshal::FromValue;
8use ruby_marshal::FromValueContext;
9use ruby_marshal::FromValueError;
10use ruby_marshal::IntoValue;
11use ruby_marshal::IntoValueError;
12use ruby_marshal::StringValue;
13use ruby_marshal::SymbolValue;
14use ruby_marshal::Value;
15use ruby_marshal::ValueArena;
16use ruby_marshal::ValueHandle;
17use ruby_marshal::ValueKind;
18
19#[derive(Debug)]
20pub enum EventCommandParameterFromValueError {
21 UnexpectedValueKind { kind: ValueKind },
22 EmptyArray,
23 UnexpectedArrayValueKind { kind: ValueKind },
24 UnexpectedUserDefinedName { name: Vec<u8> },
25}
26
27impl std::fmt::Display for EventCommandParameterFromValueError {
28 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
29 match self {
30 Self::UnexpectedValueKind { kind } => {
31 write!(
32 f,
33 "unexpected value kind for event command parameter: {kind:?}"
34 )
35 }
36 Self::EmptyArray => write!(f, "the event command parameter array is empty"),
37 Self::UnexpectedArrayValueKind { kind } => {
38 write!(
39 f,
40 "unexpected event command parameter array value kind: {kind:?}"
41 )
42 }
43 Self::UnexpectedUserDefinedName { name } => {
44 let name = DisplayByteString(name);
45 write!(
46 f,
47 "unexpected event command parameter user defined name: {name}"
48 )
49 }
50 }
51 }
52}
53
54impl std::error::Error for EventCommandParameterFromValueError {}
55
56#[derive(Debug, serde::Serialize, serde::Deserialize)]
58#[serde(untagged)]
59pub enum EventCommandParameter {
60 String(String),
61 StringArray(Vec<String>),
62 Int(i32),
63 MoveRoute(MoveRoute),
64 MoveCommand(MoveCommand),
65 AudioFile(AudioFile),
66 Tone(Tone),
67 Color(Color),
68}
69
70impl<'a> FromValue<'a> for EventCommandParameter {
71 fn from_value(ctx: &FromValueContext<'a>, value: &Value) -> Result<Self, FromValueError> {
72 match value {
73 Value::String(value) => {
74 let value = value.value();
75 let value = std::str::from_utf8(value)
76 .map_err(FromValueError::new_other)?
77 .to_string();
78 Ok(Self::String(value))
79 }
80 Value::Array(value) => {
81 let value = value.value();
82 let first = value.first().ok_or(FromValueError::new_other(
85 EventCommandParameterFromValueError::EmptyArray,
86 ))?;
87 let first: &Value = ctx.from_value(*first)?;
88 let first_kind = first.kind();
89
90 match first_kind {
91 ValueKind::String => {
92 let mut new_value = Vec::with_capacity(value.len());
93 for value in value.iter().copied() {
94 let value: &StringValue = ctx.from_value(value)?;
95 let value = std::str::from_utf8(value.value())
96 .map_err(FromValueError::new_other)?
97 .to_string();
98 new_value.push(value);
99 }
100
101 Ok(Self::StringArray(new_value))
102 }
103 _ => Err(FromValueError::new_other(
104 EventCommandParameterFromValueError::UnexpectedArrayValueKind {
105 kind: first_kind,
106 },
107 )),
108 }
109 }
110 Value::Fixnum(value) => {
111 let value = value.value();
112 Ok(Self::Int(value))
113 }
114 Value::Object(object_value) => {
115 let name = object_value.name();
116 let name: &SymbolValue = ctx.from_value(name.into())?;
117 let name = name.value();
118
119 match name {
120 crate::move_route::OBJECT_NAME => {
121 let value = FromValue::from_value(ctx, value)?;
122 Ok(Self::MoveRoute(value))
123 }
124 crate::move_command::OBJECT_NAME => {
125 let value = FromValue::from_value(ctx, value)?;
126 Ok(Self::MoveCommand(value))
127 }
128 crate::audio_file::OBJECT_NAME => {
129 let value = FromValue::from_value(ctx, value)?;
130 Ok(Self::AudioFile(value))
131 }
132 _ => Err(FromValueError::UnexpectedObjectName { name: name.into() }),
133 }
134 }
135 Value::UserDefined(user_defined_value) => {
136 let name = user_defined_value.name();
137 let name: &SymbolValue = ctx.from_value(name.into())?;
138 let name = name.value();
139
140 match name {
141 crate::tone::USER_DEFINED_NAME => {
142 let value = FromValue::from_value(ctx, value)?;
143 Ok(Self::Tone(value))
144 }
145 crate::color::USER_DEFINED_NAME => {
146 let value = FromValue::from_value(ctx, value)?;
147 Ok(Self::Color(value))
148 }
149 _ => Err(FromValueError::new_other(
150 EventCommandParameterFromValueError::UnexpectedUserDefinedName {
151 name: name.into(),
152 },
153 )),
154 }
155 }
156 _ => Err(FromValueError::new_other(
157 EventCommandParameterFromValueError::UnexpectedValueKind { kind: value.kind() },
158 )),
159 }
160 }
161}
162
163impl IntoValue for EventCommandParameter {
164 fn into_value(self, arena: &mut ValueArena) -> Result<ValueHandle, IntoValueError> {
165 match self {
166 Self::String(value) => Ok(arena.create_string(value.into()).into()),
167 Self::StringArray(value) => {
168 let values: Vec<_> = value
169 .into_iter()
170 .map(|value| arena.create_string(value.into()).into())
171 .collect();
172 Ok(arena.create_array(values).into())
173 }
174 Self::Int(value) => value.into_value(arena),
175 Self::MoveRoute(value) => value.into_value(arena),
176 Self::MoveCommand(value) => value.into_value(arena),
177 Self::AudioFile(value) => value.into_value(arena),
178 Self::Tone(value) => value.into_value(arena),
179 Self::Color(value) => value.into_value(arena),
180 }
181 }
182}