1#[doc(inline)]
22pub use super::wit::v2::mysql::{Connection, Error as MysqlError};
23#[doc(inline)]
24pub use super::wit::v2::rdbms_types::*;
25
26#[derive(Debug, thiserror::Error)]
28pub enum Error {
29 #[error("error value decoding: {0}")]
31 Decode(String),
32 #[error(transparent)]
34 MysqlError(#[from] MysqlError),
35}
36
37pub trait Decode: Sized {
39 fn decode(value: &DbValue) -> Result<Self, Error>;
41}
42
43impl<T> Decode for Option<T>
44where
45 T: Decode,
46{
47 fn decode(value: &DbValue) -> Result<Self, Error> {
48 match value {
49 DbValue::DbNull => Ok(None),
50 v => Ok(Some(T::decode(v)?)),
51 }
52 }
53}
54
55impl Decode for bool {
56 fn decode(value: &DbValue) -> Result<Self, Error> {
57 match value {
58 DbValue::Int8(0) => Ok(false),
59 DbValue::Int8(1) => Ok(true),
60 _ => Err(Error::Decode(format_decode_err(
61 "TINYINT(1), BOOLEAN",
62 value,
63 ))),
64 }
65 }
66}
67
68impl Decode for i8 {
69 fn decode(value: &DbValue) -> Result<Self, Error> {
70 match value {
71 DbValue::Int8(n) => Ok(*n),
72 _ => Err(Error::Decode(format_decode_err("TINYINT", value))),
73 }
74 }
75}
76
77impl Decode for i16 {
78 fn decode(value: &DbValue) -> Result<Self, Error> {
79 match value {
80 DbValue::Int16(n) => Ok(*n),
81 _ => Err(Error::Decode(format_decode_err("SMALLINT", value))),
82 }
83 }
84}
85
86impl Decode for i32 {
87 fn decode(value: &DbValue) -> Result<Self, Error> {
88 match value {
89 DbValue::Int32(n) => Ok(*n),
90 _ => Err(Error::Decode(format_decode_err("INT", value))),
91 }
92 }
93}
94
95impl Decode for i64 {
96 fn decode(value: &DbValue) -> Result<Self, Error> {
97 match value {
98 DbValue::Int64(n) => Ok(*n),
99 _ => Err(Error::Decode(format_decode_err("BIGINT", value))),
100 }
101 }
102}
103
104impl Decode for u8 {
105 fn decode(value: &DbValue) -> Result<Self, Error> {
106 match value {
107 DbValue::Uint8(n) => Ok(*n),
108 _ => Err(Error::Decode(format_decode_err("UNSIGNED TINYINT", value))),
109 }
110 }
111}
112
113impl Decode for u16 {
114 fn decode(value: &DbValue) -> Result<Self, Error> {
115 match value {
116 DbValue::Uint16(n) => Ok(*n),
117 _ => Err(Error::Decode(format_decode_err("UNSIGNED SMALLINT", value))),
118 }
119 }
120}
121
122impl Decode for u32 {
123 fn decode(value: &DbValue) -> Result<Self, Error> {
124 match value {
125 DbValue::Uint32(n) => Ok(*n),
126 _ => Err(Error::Decode(format_decode_err(
127 "UNISIGNED MEDIUMINT, UNSIGNED INT",
128 value,
129 ))),
130 }
131 }
132}
133
134impl Decode for u64 {
135 fn decode(value: &DbValue) -> Result<Self, Error> {
136 match value {
137 DbValue::Uint64(n) => Ok(*n),
138 _ => Err(Error::Decode(format_decode_err("UNSIGNED BIGINT", value))),
139 }
140 }
141}
142
143impl Decode for f32 {
144 fn decode(value: &DbValue) -> Result<Self, Error> {
145 match value {
146 DbValue::Floating32(n) => Ok(*n),
147 _ => Err(Error::Decode(format_decode_err("FLOAT", value))),
148 }
149 }
150}
151
152impl Decode for f64 {
153 fn decode(value: &DbValue) -> Result<Self, Error> {
154 match value {
155 DbValue::Floating64(n) => Ok(*n),
156 _ => Err(Error::Decode(format_decode_err("DOUBLE", value))),
157 }
158 }
159}
160
161impl Decode for Vec<u8> {
162 fn decode(value: &DbValue) -> Result<Self, Error> {
163 match value {
164 DbValue::Binary(n) => Ok(n.to_owned()),
165 _ => Err(Error::Decode(format_decode_err("BINARY, VARBINARY", value))),
166 }
167 }
168}
169
170impl Decode for String {
171 fn decode(value: &DbValue) -> Result<Self, Error> {
172 match value {
173 DbValue::Str(s) => Ok(s.to_owned()),
174 _ => Err(Error::Decode(format_decode_err(
175 "CHAR, VARCHAR, TEXT",
176 value,
177 ))),
178 }
179 }
180}
181
182fn format_decode_err(types: &str, value: &DbValue) -> String {
183 format!("Expected {} from the DB but got {:?}", types, value)
184}
185
186#[cfg(test)]
187mod tests {
188 use super::*;
189
190 #[test]
191 fn boolean() {
192 assert!(bool::decode(&DbValue::Int8(1)).unwrap());
193 assert!(bool::decode(&DbValue::Int8(3)).is_err());
194 assert!(bool::decode(&DbValue::Int32(0)).is_err());
195 assert!(Option::<bool>::decode(&DbValue::DbNull).unwrap().is_none());
196 }
197
198 #[test]
199 fn int8() {
200 assert_eq!(i8::decode(&DbValue::Int8(0)).unwrap(), 0);
201 assert!(i8::decode(&DbValue::Int32(0)).is_err());
202 assert!(Option::<i8>::decode(&DbValue::DbNull).unwrap().is_none());
203 }
204
205 #[test]
206 fn int16() {
207 assert_eq!(i16::decode(&DbValue::Int16(0)).unwrap(), 0);
208 assert!(i16::decode(&DbValue::Int32(0)).is_err());
209 assert!(Option::<i16>::decode(&DbValue::DbNull).unwrap().is_none());
210 }
211
212 #[test]
213 fn int32() {
214 assert_eq!(i32::decode(&DbValue::Int32(0)).unwrap(), 0);
215 assert!(i32::decode(&DbValue::Boolean(false)).is_err());
216 assert!(Option::<i32>::decode(&DbValue::DbNull).unwrap().is_none());
217 }
218
219 #[test]
220 fn int64() {
221 assert_eq!(i64::decode(&DbValue::Int64(0)).unwrap(), 0);
222 assert!(i64::decode(&DbValue::Boolean(false)).is_err());
223 assert!(Option::<i64>::decode(&DbValue::DbNull).unwrap().is_none());
224 }
225
226 #[test]
227 fn uint8() {
228 assert_eq!(u8::decode(&DbValue::Uint8(0)).unwrap(), 0);
229 assert!(u8::decode(&DbValue::Uint32(0)).is_err());
230 assert!(Option::<u16>::decode(&DbValue::DbNull).unwrap().is_none());
231 }
232
233 #[test]
234 fn uint16() {
235 assert_eq!(u16::decode(&DbValue::Uint16(0)).unwrap(), 0);
236 assert!(u16::decode(&DbValue::Uint32(0)).is_err());
237 assert!(Option::<u16>::decode(&DbValue::DbNull).unwrap().is_none());
238 }
239
240 #[test]
241 fn uint32() {
242 assert_eq!(u32::decode(&DbValue::Uint32(0)).unwrap(), 0);
243 assert!(u32::decode(&DbValue::Boolean(false)).is_err());
244 assert!(Option::<u32>::decode(&DbValue::DbNull).unwrap().is_none());
245 }
246
247 #[test]
248 fn uint64() {
249 assert_eq!(u64::decode(&DbValue::Uint64(0)).unwrap(), 0);
250 assert!(u64::decode(&DbValue::Boolean(false)).is_err());
251 assert!(Option::<u64>::decode(&DbValue::DbNull).unwrap().is_none());
252 }
253
254 #[test]
255 fn floating32() {
256 assert!(f32::decode(&DbValue::Floating32(0.0)).is_ok());
257 assert!(f32::decode(&DbValue::Boolean(false)).is_err());
258 assert!(Option::<f32>::decode(&DbValue::DbNull).unwrap().is_none());
259 }
260
261 #[test]
262 fn floating64() {
263 assert!(f64::decode(&DbValue::Floating64(0.0)).is_ok());
264 assert!(f64::decode(&DbValue::Boolean(false)).is_err());
265 assert!(Option::<f64>::decode(&DbValue::DbNull).unwrap().is_none());
266 }
267
268 #[test]
269 fn str() {
270 assert_eq!(
271 String::decode(&DbValue::Str(String::from("foo"))).unwrap(),
272 String::from("foo")
273 );
274
275 assert!(String::decode(&DbValue::Int32(0)).is_err());
276 assert!(Option::<String>::decode(&DbValue::DbNull)
277 .unwrap()
278 .is_none());
279 }
280}