1#[doc(hidden)]
25pub mod wit {
29 #![allow(missing_docs)]
30 use crate::wit_bindgen;
31
32 wit_bindgen::generate!({
33 runtime_path: "crate::wit_bindgen::rt",
34 world: "spin-sdk-mysql",
35 path: "wit",
36 generate_all,
37 });
38}
39
40#[doc(inline)]
105pub use wit::fermyon::spin::mysql::Connection;
106
107#[doc(inline)]
138pub use wit::fermyon::spin::mysql::RowSet;
139
140#[doc(inline)]
141pub use wit::fermyon::spin::mysql::Error as MysqlError;
142
143#[doc(inline)]
144pub use wit::fermyon::spin::rdbms_types::*;
145
146#[derive(Debug, thiserror::Error)]
148pub enum Error {
149 #[error("error value decoding: {0}")]
151 Decode(String),
152 #[error(transparent)]
154 MysqlError(#[from] MysqlError),
155}
156
157pub trait Decode: Sized {
159 fn decode(value: &DbValue) -> Result<Self, Error>;
161}
162
163impl<T> Decode for Option<T>
164where
165 T: Decode,
166{
167 fn decode(value: &DbValue) -> Result<Self, Error> {
168 match value {
169 DbValue::DbNull => Ok(None),
170 v => Ok(Some(T::decode(v)?)),
171 }
172 }
173}
174
175impl Decode for bool {
176 fn decode(value: &DbValue) -> Result<Self, Error> {
177 match value {
178 DbValue::Int8(0) => Ok(false),
179 DbValue::Int8(1) => Ok(true),
180 _ => Err(Error::Decode(format_decode_err(
181 "TINYINT(1), BOOLEAN",
182 value,
183 ))),
184 }
185 }
186}
187
188impl Decode for i8 {
189 fn decode(value: &DbValue) -> Result<Self, Error> {
190 match value {
191 DbValue::Int8(n) => Ok(*n),
192 _ => Err(Error::Decode(format_decode_err("TINYINT", value))),
193 }
194 }
195}
196
197impl Decode for i16 {
198 fn decode(value: &DbValue) -> Result<Self, Error> {
199 match value {
200 DbValue::Int16(n) => Ok(*n),
201 _ => Err(Error::Decode(format_decode_err("SMALLINT", value))),
202 }
203 }
204}
205
206impl Decode for i32 {
207 fn decode(value: &DbValue) -> Result<Self, Error> {
208 match value {
209 DbValue::Int32(n) => Ok(*n),
210 _ => Err(Error::Decode(format_decode_err("INT", value))),
211 }
212 }
213}
214
215impl Decode for i64 {
216 fn decode(value: &DbValue) -> Result<Self, Error> {
217 match value {
218 DbValue::Int64(n) => Ok(*n),
219 _ => Err(Error::Decode(format_decode_err("BIGINT", value))),
220 }
221 }
222}
223
224impl Decode for u8 {
225 fn decode(value: &DbValue) -> Result<Self, Error> {
226 match value {
227 DbValue::Uint8(n) => Ok(*n),
228 _ => Err(Error::Decode(format_decode_err("UNSIGNED TINYINT", value))),
229 }
230 }
231}
232
233impl Decode for u16 {
234 fn decode(value: &DbValue) -> Result<Self, Error> {
235 match value {
236 DbValue::Uint16(n) => Ok(*n),
237 _ => Err(Error::Decode(format_decode_err("UNSIGNED SMALLINT", value))),
238 }
239 }
240}
241
242impl Decode for u32 {
243 fn decode(value: &DbValue) -> Result<Self, Error> {
244 match value {
245 DbValue::Uint32(n) => Ok(*n),
246 _ => Err(Error::Decode(format_decode_err(
247 "UNISIGNED MEDIUMINT, UNSIGNED INT",
248 value,
249 ))),
250 }
251 }
252}
253
254impl Decode for u64 {
255 fn decode(value: &DbValue) -> Result<Self, Error> {
256 match value {
257 DbValue::Uint64(n) => Ok(*n),
258 _ => Err(Error::Decode(format_decode_err("UNSIGNED BIGINT", value))),
259 }
260 }
261}
262
263impl Decode for f32 {
264 fn decode(value: &DbValue) -> Result<Self, Error> {
265 match value {
266 DbValue::Floating32(n) => Ok(*n),
267 _ => Err(Error::Decode(format_decode_err("FLOAT", value))),
268 }
269 }
270}
271
272impl Decode for f64 {
273 fn decode(value: &DbValue) -> Result<Self, Error> {
274 match value {
275 DbValue::Floating64(n) => Ok(*n),
276 _ => Err(Error::Decode(format_decode_err("DOUBLE", value))),
277 }
278 }
279}
280
281impl Decode for Vec<u8> {
282 fn decode(value: &DbValue) -> Result<Self, Error> {
283 match value {
284 DbValue::Binary(n) => Ok(n.to_owned()),
285 _ => Err(Error::Decode(format_decode_err("BINARY, VARBINARY", value))),
286 }
287 }
288}
289
290impl Decode for String {
291 fn decode(value: &DbValue) -> Result<Self, Error> {
292 match value {
293 DbValue::Str(s) => Ok(s.to_owned()),
294 _ => Err(Error::Decode(format_decode_err(
295 "CHAR, VARCHAR, TEXT",
296 value,
297 ))),
298 }
299 }
300}
301
302fn format_decode_err(types: &str, value: &DbValue) -> String {
303 format!("Expected {} from the DB but got {:?}", types, value)
304}
305
306#[cfg(test)]
307mod tests {
308 use super::*;
309
310 #[test]
311 fn boolean() {
312 assert!(bool::decode(&DbValue::Int8(1)).unwrap());
313 assert!(bool::decode(&DbValue::Int8(3)).is_err());
314 assert!(bool::decode(&DbValue::Int32(0)).is_err());
315 assert!(Option::<bool>::decode(&DbValue::DbNull).unwrap().is_none());
316 }
317
318 #[test]
319 fn int8() {
320 assert_eq!(i8::decode(&DbValue::Int8(0)).unwrap(), 0);
321 assert!(i8::decode(&DbValue::Int32(0)).is_err());
322 assert!(Option::<i8>::decode(&DbValue::DbNull).unwrap().is_none());
323 }
324
325 #[test]
326 fn int16() {
327 assert_eq!(i16::decode(&DbValue::Int16(0)).unwrap(), 0);
328 assert!(i16::decode(&DbValue::Int32(0)).is_err());
329 assert!(Option::<i16>::decode(&DbValue::DbNull).unwrap().is_none());
330 }
331
332 #[test]
333 fn int32() {
334 assert_eq!(i32::decode(&DbValue::Int32(0)).unwrap(), 0);
335 assert!(i32::decode(&DbValue::Boolean(false)).is_err());
336 assert!(Option::<i32>::decode(&DbValue::DbNull).unwrap().is_none());
337 }
338
339 #[test]
340 fn int64() {
341 assert_eq!(i64::decode(&DbValue::Int64(0)).unwrap(), 0);
342 assert!(i64::decode(&DbValue::Boolean(false)).is_err());
343 assert!(Option::<i64>::decode(&DbValue::DbNull).unwrap().is_none());
344 }
345
346 #[test]
347 fn uint8() {
348 assert_eq!(u8::decode(&DbValue::Uint8(0)).unwrap(), 0);
349 assert!(u8::decode(&DbValue::Uint32(0)).is_err());
350 assert!(Option::<u16>::decode(&DbValue::DbNull).unwrap().is_none());
351 }
352
353 #[test]
354 fn uint16() {
355 assert_eq!(u16::decode(&DbValue::Uint16(0)).unwrap(), 0);
356 assert!(u16::decode(&DbValue::Uint32(0)).is_err());
357 assert!(Option::<u16>::decode(&DbValue::DbNull).unwrap().is_none());
358 }
359
360 #[test]
361 fn uint32() {
362 assert_eq!(u32::decode(&DbValue::Uint32(0)).unwrap(), 0);
363 assert!(u32::decode(&DbValue::Boolean(false)).is_err());
364 assert!(Option::<u32>::decode(&DbValue::DbNull).unwrap().is_none());
365 }
366
367 #[test]
368 fn uint64() {
369 assert_eq!(u64::decode(&DbValue::Uint64(0)).unwrap(), 0);
370 assert!(u64::decode(&DbValue::Boolean(false)).is_err());
371 assert!(Option::<u64>::decode(&DbValue::DbNull).unwrap().is_none());
372 }
373
374 #[test]
375 fn floating32() {
376 assert!(f32::decode(&DbValue::Floating32(0.0)).is_ok());
377 assert!(f32::decode(&DbValue::Boolean(false)).is_err());
378 assert!(Option::<f32>::decode(&DbValue::DbNull).unwrap().is_none());
379 }
380
381 #[test]
382 fn floating64() {
383 assert!(f64::decode(&DbValue::Floating64(0.0)).is_ok());
384 assert!(f64::decode(&DbValue::Boolean(false)).is_err());
385 assert!(Option::<f64>::decode(&DbValue::DbNull).unwrap().is_none());
386 }
387
388 #[test]
389 fn str() {
390 assert_eq!(
391 String::decode(&DbValue::Str(String::from("foo"))).unwrap(),
392 String::from("foo")
393 );
394
395 assert!(String::decode(&DbValue::Int32(0)).is_err());
396 assert!(Option::<String>::decode(&DbValue::DbNull)
397 .unwrap()
398 .is_none());
399 }
400}