rpgm_common_types/
script.rs1use flate2::bufread::ZlibDecoder;
2use flate2::bufread::ZlibEncoder;
3use flate2::Compression;
4use ruby_marshal::ArrayValue;
5use ruby_marshal::FromValue;
6use ruby_marshal::FromValueContext;
7use ruby_marshal::FromValueError;
8use ruby_marshal::IntoValue;
9use ruby_marshal::IntoValueError;
10use ruby_marshal::StringValue;
11use ruby_marshal::Value;
12use ruby_marshal::ValueArena;
13use ruby_marshal::ValueHandle;
14use std::io::Read;
15
16const ARRAY_LEN: usize = 3;
17
18#[derive(Debug)]
20pub struct CompressedScriptList {
21 pub scripts: Vec<CompressedScript>,
23}
24
25impl<'a> FromValue<'a> for CompressedScriptList {
26 fn from_value(ctx: &FromValueContext<'a>, value: &Value) -> Result<Self, FromValueError> {
27 Ok(Self {
28 scripts: FromValue::from_value(ctx, value)?,
29 })
30 }
31}
32impl IntoValue for CompressedScriptList {
33 fn into_value(self, arena: &mut ValueArena) -> Result<ValueHandle, IntoValueError> {
34 self.scripts.into_value(arena)
35 }
36}
37
38#[derive(Debug)]
40pub struct ScriptList {
41 pub scripts: Vec<Script>,
43}
44
45impl<'a> FromValue<'a> for ScriptList {
46 fn from_value(ctx: &FromValueContext<'a>, value: &Value) -> Result<Self, FromValueError> {
47 Ok(Self {
48 scripts: FromValue::from_value(ctx, value)?,
49 })
50 }
51}
52impl IntoValue for ScriptList {
53 fn into_value(self, arena: &mut ValueArena) -> Result<ValueHandle, IntoValueError> {
54 self.scripts.into_value(arena)
55 }
56}
57
58#[derive(Debug)]
60pub enum ScriptFromValueError {
61 InvalidArrayLen { len: usize },
63
64 InvalidName { error: std::str::Utf8Error },
66}
67
68impl std::fmt::Display for ScriptFromValueError {
69 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70 match self {
71 Self::InvalidArrayLen { len } => {
72 write!(f, "invalid script array len of {len}, expected {ARRAY_LEN}")
73 }
74 Self::InvalidName { .. } => {
75 write!(f, "the script name is invalid")
76 }
77 }
78 }
79}
80
81impl std::error::Error for ScriptFromValueError {
82 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
83 match self {
84 Self::InvalidName { error } => Some(error),
85 _ => None,
86 }
87 }
88}
89
90impl From<ScriptFromValueError> for FromValueError {
91 fn from(error: ScriptFromValueError) -> Self {
92 FromValueError::Other {
93 error: error.into(),
94 }
95 }
96}
97
98#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
100pub struct CompressedScript {
101 pub id: i32,
105
106 pub name: String,
108
109 pub data: Vec<u8>,
111}
112
113impl<'a> FromValue<'a> for CompressedScript {
114 fn from_value(ctx: &FromValueContext<'a>, value: &Value) -> Result<Self, FromValueError> {
115 let script: &ArrayValue = FromValue::from_value(ctx, value)?;
116 let script = script.value();
117
118 let array_len = script.len();
119 if array_len != ARRAY_LEN {
120 return Err(ScriptFromValueError::InvalidArrayLen { len: array_len }.into());
121 }
122
123 let id: i32 = ctx.from_value(script[0])?;
124
125 let name: &StringValue = ctx.from_value(script[1])?;
126 let name = std::str::from_utf8(name.value())
127 .map_err(|error| ScriptFromValueError::InvalidName { error })?;
128
129 let data: &StringValue = ctx.from_value(script[2])?;
130 let data = data.value();
131
132 Ok(Self {
133 id,
134 name: name.into(),
135 data: data.into(),
136 })
137 }
138}
139
140impl IntoValue for CompressedScript {
141 fn into_value(self, arena: &mut ValueArena) -> Result<ValueHandle, IntoValueError> {
142 let id = self.id.into_value(arena)?;
143 let name = arena.create_string(self.name.into()).into_raw();
144 let data = arena.create_string(self.data).into_raw();
145
146 let array = arena.create_array(vec![id, name, data]);
147
148 Ok(array.into())
149 }
150}
151
152#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
154pub struct Script {
155 pub id: i32,
159
160 pub name: String,
162
163 pub data: String,
165}
166
167impl<'a> FromValue<'a> for Script {
168 fn from_value(ctx: &FromValueContext<'a>, value: &Value) -> Result<Self, FromValueError> {
169 let script: CompressedScript = FromValue::from_value(ctx, value)?;
170
171 let mut decoder = ZlibDecoder::new(&*script.data);
172 let mut data = String::new();
173 decoder
174 .read_to_string(&mut data)
175 .map_err(FromValueError::new_other)?;
176
177 Ok(Self {
178 id: script.id,
179 name: script.name,
180 data,
181 })
182 }
183}
184
185impl IntoValue for Script {
186 fn into_value(self, arena: &mut ValueArena) -> Result<ValueHandle, IntoValueError> {
187 let id = self.id.into_value(arena)?;
188 let name = arena.create_string(self.name.into()).into_raw();
189
190 let compression = Compression::default();
191 let mut encoder = ZlibEncoder::new(self.data.as_bytes(), compression);
192 let mut data = Vec::new();
193 encoder
194 .read_to_end(&mut data)
195 .map_err(IntoValueError::new_other)?;
196
197 let data = arena.create_string(data).into_raw();
198
199 let array = arena.create_array(vec![id, name, data]);
200
201 Ok(array.into())
202 }
203}