rpgmvx_types/
event_command_parameter.rs

1use crate::Bgm;
2use crate::Bgs;
3use crate::Color;
4use crate::Me;
5use crate::MoveCommand;
6use crate::MoveRoute;
7use crate::Se;
8use crate::Tone;
9use ruby_marshal::DisplayByteString;
10use ruby_marshal::FromValue;
11use ruby_marshal::FromValueContext;
12use ruby_marshal::FromValueError;
13use ruby_marshal::IntoValue;
14use ruby_marshal::IntoValueError;
15use ruby_marshal::StringValue;
16use ruby_marshal::SymbolValue;
17use ruby_marshal::Value;
18use ruby_marshal::ValueArena;
19use ruby_marshal::ValueHandle;
20use ruby_marshal::ValueKind;
21
22#[derive(Debug)]
23pub enum EventCommandParameterFromValueError {
24    UnexpectedValueKind { kind: ValueKind },
25    UnexpectedUserDefinedName { name: Vec<u8> },
26    EmptyArray,
27    UnexpectedArrayValueKind { kind: ValueKind },
28}
29
30impl std::fmt::Display for EventCommandParameterFromValueError {
31    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
32        match self {
33            Self::UnexpectedValueKind { kind } => {
34                write!(
35                    f,
36                    "unexpected value kind for event command parameter: {kind:?}"
37                )
38            }
39            Self::UnexpectedUserDefinedName { name } => {
40                let name = DisplayByteString(name);
41                write!(
42                    f,
43                    "unexpected event command parameter user defined name: {name}"
44                )
45            }
46            Self::EmptyArray => write!(f, "the event command parameter array is empty"),
47            Self::UnexpectedArrayValueKind { kind } => {
48                write!(
49                    f,
50                    "unexpected event command parameter array value kind: {kind:?}"
51                )
52            }
53        }
54    }
55}
56
57impl std::error::Error for EventCommandParameterFromValueError {}
58
59#[derive(Debug, serde::Serialize, serde::Deserialize)]
60#[serde(tag = "type", content = "data")]
61pub enum EventCommandParameter {
62    #[serde(rename = "string")]
63    String(String),
64    #[serde(rename = "int")]
65    Int(i32),
66    #[serde(rename = "bool")]
67    Bool(bool),
68    #[serde(rename = "nil")]
69    Nil,
70    #[serde(rename = "string-array")]
71    StringArray(Vec<String>),
72    #[serde(rename = "move-route")]
73    MoveRoute(MoveRoute),
74    #[serde(rename = "move-command")]
75    MoveCommand(MoveCommand),
76    #[serde(rename = "se")]
77    Se(Se),
78    #[serde(rename = "tone")]
79    Tone(Tone),
80    #[serde(rename = "color")]
81    Color(Color),
82    #[serde(rename = "bgm")]
83    Bgm(Bgm),
84    #[serde(rename = "bgs")]
85    Bgs(Bgs),
86    #[serde(rename = "me")]
87    Me(Me),
88}
89
90impl<'a> FromValue<'a> for EventCommandParameter {
91    fn from_value(ctx: &FromValueContext<'a>, value: &Value) -> Result<Self, FromValueError> {
92        match value {
93            Value::String(value) => {
94                let value = value.value();
95                let value = std::str::from_utf8(value)
96                    .map_err(FromValueError::new_other)?
97                    .to_string();
98                Ok(Self::String(value))
99            }
100            Value::Fixnum(value) => {
101                let value = value.value();
102                Ok(Self::Int(value))
103            }
104            Value::Bool(value) => {
105                let value = value.value();
106                Ok(Self::Bool(value))
107            }
108            Value::Nil(_) => Ok(Self::Nil),
109            Value::Array(value) => {
110                let value = value.value();
111                // TODO: Maybe make the internal array elements polymorphic.
112                // If empty, static typing is impossible.
113                let first = value.first().ok_or(FromValueError::new_other(
114                    EventCommandParameterFromValueError::EmptyArray,
115                ))?;
116                let first: &Value = ctx.from_value(*first)?;
117                let first_kind = first.kind();
118
119                match first_kind {
120                    ValueKind::String => {
121                        let mut new_value = Vec::with_capacity(value.len());
122                        for value in value.iter().copied() {
123                            let value: &StringValue = ctx.from_value(value)?;
124                            let value = std::str::from_utf8(value.value())
125                                .map_err(FromValueError::new_other)?
126                                .to_string();
127                            new_value.push(value);
128                        }
129
130                        Ok(Self::StringArray(new_value))
131                    }
132                    _ => Err(FromValueError::new_other(
133                        EventCommandParameterFromValueError::UnexpectedArrayValueKind {
134                            kind: first_kind,
135                        },
136                    )),
137                }
138            }
139            Value::Object(object_value) => {
140                let name = object_value.name();
141                let name: &SymbolValue = ctx.from_value(name.into())?;
142                let name = name.value();
143
144                match name {
145                    crate::move_route::OBJECT_NAME => {
146                        let value = FromValue::from_value(ctx, value)?;
147                        Ok(Self::MoveRoute(value))
148                    }
149                    crate::move_command::OBJECT_NAME => {
150                        let value = FromValue::from_value(ctx, value)?;
151                        Ok(Self::MoveCommand(value))
152                    }
153                    crate::se::OBJECT_NAME => {
154                        let value = FromValue::from_value(ctx, value)?;
155                        Ok(Self::Se(value))
156                    }
157                    crate::bgm::OBJECT_NAME => {
158                        let value = FromValue::from_value(ctx, value)?;
159                        Ok(Self::Bgm(value))
160                    }
161                    crate::bgs::OBJECT_NAME => {
162                        let value = FromValue::from_value(ctx, value)?;
163                        Ok(Self::Bgs(value))
164                    }
165                    crate::me::OBJECT_NAME => {
166                        let value = FromValue::from_value(ctx, value)?;
167                        Ok(Self::Me(value))
168                    }
169                    _ => Err(FromValueError::UnexpectedObjectName { name: name.into() }),
170                }
171            }
172            Value::UserDefined(user_defined_value) => {
173                let name = user_defined_value.name();
174                let name: &SymbolValue = ctx.from_value(name.into())?;
175                let name = name.value();
176
177                match name {
178                    crate::tone::USER_DEFINED_NAME => {
179                        let value = FromValue::from_value(ctx, value)?;
180                        Ok(Self::Tone(value))
181                    }
182                    crate::color::USER_DEFINED_NAME => {
183                        let value = FromValue::from_value(ctx, value)?;
184                        Ok(Self::Color(value))
185                    }
186                    _ => Err(FromValueError::new_other(
187                        EventCommandParameterFromValueError::UnexpectedUserDefinedName {
188                            name: name.into(),
189                        },
190                    )),
191                }
192            }
193            _ => Err(FromValueError::new_other(
194                EventCommandParameterFromValueError::UnexpectedValueKind { kind: value.kind() },
195            )),
196        }
197    }
198}
199
200impl IntoValue for EventCommandParameter {
201    fn into_value(self, arena: &mut ValueArena) -> Result<ValueHandle, IntoValueError> {
202        match self {
203            Self::String(value) => Ok(arena.create_string(value.into()).into()),
204            Self::Int(value) => value.into_value(arena),
205            Self::Bool(value) => value.into_value(arena),
206            Self::Nil => Ok(arena.create_nil().into()),
207            Self::StringArray(value) => {
208                let values: Vec<_> = value
209                    .into_iter()
210                    .map(|value| arena.create_string(value.into()).into())
211                    .collect();
212                Ok(arena.create_array(values).into())
213            }
214            Self::MoveRoute(value) => value.into_value(arena),
215            Self::MoveCommand(value) => value.into_value(arena),
216            Self::Se(value) => value.into_value(arena),
217            Self::Tone(value) => value.into_value(arena),
218            Self::Color(value) => value.into_value(arena),
219            Self::Bgm(value) => value.into_value(arena),
220            Self::Bgs(value) => value.into_value(arena),
221            Self::Me(value) => value.into_value(arena),
222        }
223    }
224}