hdbconnect_impl/serde_db_impl/
de.rs

1use crate::{HdbError, HdbValue, OutputParameters, ParameterDescriptor, Row, Rows};
2use bigdecimal::ToPrimitive;
3use serde_db::de::{
4    ConversionError, DbValue, DbValueInto, DeserializableResultSet, DeserializableRow,
5    DeserializationError, DeserializationResult,
6};
7use std::{
8    fmt,
9    num::{ParseFloatError, ParseIntError},
10};
11
12impl DeserializableResultSet for Rows {
13    type Row = Row;
14    type Error = DeserializationError;
15
16    fn has_multiple_rows(&mut self) -> Result<bool, DeserializationError> {
17        Ok(self.len > 1)
18    }
19
20    fn next(&mut self) -> DeserializationResult<Option<Row>> {
21        Ok(self.row_iter.next())
22    }
23
24    fn number_of_fields(&self) -> usize {
25        self.metadata.len()
26    }
27
28    fn field_name(&self, i: usize) -> Option<&str> {
29        Some(self.metadata[i].displayname())
30    }
31}
32
33impl DeserializableRow for Row {
34    type Value = HdbValue<'static>;
35    type Error = DeserializationError;
36
37    fn len(&self) -> usize {
38        self.len()
39    }
40
41    fn next(&mut self) -> Option<HdbValue<'static>> {
42        self.next_value()
43    }
44
45    fn number_of_fields(&self) -> usize {
46        self.metadata().len()
47    }
48
49    fn field_name(&self, field_idx: usize) -> Option<&str> {
50        Some(self.metadata()[field_idx].displayname())
51    }
52}
53
54pub(crate) struct DeserializableOutputParameters {
55    descriptors: Vec<ParameterDescriptor>,
56    value_iter: <Vec<HdbValue<'static>> as IntoIterator>::IntoIter,
57}
58impl DeserializableOutputParameters {
59    pub(crate) fn new(op: OutputParameters) -> DeserializableOutputParameters {
60        let (descriptors, values) = op.into_descriptors_and_values();
61        DeserializableOutputParameters {
62            descriptors,
63            value_iter: values.into_iter(),
64        }
65    }
66}
67
68impl DeserializableRow for DeserializableOutputParameters {
69    type Value = HdbValue<'static>;
70    type Error = DeserializationError;
71
72    fn len(&self) -> usize {
73        self.value_iter.len()
74    }
75
76    fn next(&mut self) -> Option<HdbValue<'static>> {
77        self.value_iter.next()
78    }
79
80    fn number_of_fields(&self) -> usize {
81        self.descriptors.len()
82    }
83
84    fn field_name(&self, field_idx: usize) -> Option<&str> {
85        self.descriptors
86            .get(field_idx)
87            .and_then(ParameterDescriptor::name)
88    }
89}
90
91impl DbValue for HdbValue<'static> {
92    fn is_null(&self) -> bool {
93        matches!(*self, HdbValue::NULL)
94    }
95}
96
97impl DbValueInto<bool> for HdbValue<'static> {
98    fn try_into(self) -> Result<bool, ConversionError> {
99        match self {
100            HdbValue::BOOLEAN(b) => Ok(b),
101            HdbValue::TINYINT(1)
102            | HdbValue::SMALLINT(1)
103            | HdbValue::INT(1)
104            | HdbValue::BIGINT(1) => Ok(true),
105            HdbValue::STRING(ref s) => match s.as_ref() {
106                "true" | "TRUE" | "True" => Ok(true),
107                "false" | "FALSE" | "False" => Ok(false),
108                _ => Err(wrong_type(&self, "bool")),
109            },
110            HdbValue::TINYINT(0)
111            | HdbValue::SMALLINT(0)
112            | HdbValue::INT(0)
113            | HdbValue::BIGINT(0) => Ok(false),
114            value => Err(wrong_type(&value, "bool")),
115        }
116    }
117}
118
119impl DbValueInto<u8> for HdbValue<'static> {
120    fn try_into(self) -> Result<u8, ConversionError> {
121        match self {
122            HdbValue::TINYINT(u) => Ok(u),
123            HdbValue::SMALLINT(i) => {
124                Ok(num::cast(i).ok_or_else(|| number_range(i64::from(i), "u8"))?)
125            }
126            HdbValue::INT(i) => Ok(num::cast(i).ok_or_else(|| number_range(i64::from(i), "u8"))?),
127            HdbValue::BIGINT(i) => Ok(num::cast(i).ok_or_else(|| number_range(i, "u8"))?),
128            HdbValue::DECIMAL(bigdec) => bigdec.to_u8().ok_or_else(|| decimal_range("u8")),
129            HdbValue::STRING(s) => s.parse().map_err(|e: ParseIntError| parse_int_err(&e)),
130            value => Err(wrong_type(&value, "u8")),
131        }
132    }
133}
134
135impl DbValueInto<u16> for HdbValue<'static> {
136    fn try_into(self) -> Result<u16, ConversionError> {
137        match self {
138            HdbValue::TINYINT(u) => Ok(u16::from(u)),
139            HdbValue::SMALLINT(i) => {
140                Ok(num::cast(i).ok_or_else(|| number_range(i64::from(i), "u16"))?)
141            }
142            HdbValue::INT(i) => Ok(num::cast(i).ok_or_else(|| number_range(i64::from(i), "u16"))?),
143            HdbValue::BIGINT(i) => Ok(num::cast(i).ok_or_else(|| number_range(i, "u16"))?),
144            HdbValue::DECIMAL(bigdec) => bigdec.to_u16().ok_or_else(|| decimal_range("u16")),
145            HdbValue::STRING(s) => s.parse().map_err(|e: ParseIntError| parse_int_err(&e)),
146            value => Err(wrong_type(&value, "u16")),
147        }
148    }
149}
150
151impl DbValueInto<u32> for HdbValue<'static> {
152    fn try_into(self) -> Result<u32, ConversionError> {
153        match self {
154            HdbValue::TINYINT(u) => Ok(u32::from(u)),
155            HdbValue::SMALLINT(i) => {
156                Ok(num::cast(i).ok_or_else(|| number_range(i64::from(i), "u32"))?)
157            }
158            HdbValue::INT(i) => Ok(num::cast(i).ok_or_else(|| number_range(i64::from(i), "u32"))?),
159            HdbValue::BIGINT(i) => Ok(num::cast(i).ok_or_else(|| number_range(i, "u32"))?),
160            HdbValue::DECIMAL(bigdec) => bigdec.to_u32().ok_or_else(|| decimal_range("u32")),
161            HdbValue::STRING(s) => s.parse().map_err(|e: ParseIntError| parse_int_err(&e)),
162            value => Err(wrong_type(&value, "u32")),
163        }
164    }
165}
166
167impl DbValueInto<u64> for HdbValue<'static> {
168    fn try_into(self) -> Result<u64, ConversionError> {
169        match self {
170            HdbValue::TINYINT(u) => Ok(u64::from(u)),
171            HdbValue::SMALLINT(i) => {
172                Ok(num::cast(i).ok_or_else(|| number_range(i64::from(i), "u64"))?)
173            }
174            HdbValue::INT(i) => Ok(num::cast(i).ok_or_else(|| number_range(i64::from(i), "u64"))?),
175            HdbValue::BIGINT(i) => Ok(num::cast(i).ok_or_else(|| number_range(i, "u64"))?),
176            HdbValue::DECIMAL(bigdec) => bigdec.to_u64().ok_or_else(|| decimal_range("u64")),
177            HdbValue::STRING(s) => s.parse().map_err(|e: ParseIntError| parse_int_err(&e)),
178            value => Err(wrong_type(&value, "u64")),
179        }
180    }
181}
182
183impl DbValueInto<i8> for HdbValue<'static> {
184    fn try_into(self) -> Result<i8, ConversionError> {
185        match self {
186            HdbValue::TINYINT(i) => {
187                Ok(num::cast(i).ok_or_else(|| number_range(i64::from(i), "i8"))?)
188            }
189            HdbValue::SMALLINT(i) => {
190                Ok(num::cast(i).ok_or_else(|| number_range(i64::from(i), "i8"))?)
191            }
192            HdbValue::INT(i) => Ok(num::cast(i).ok_or_else(|| number_range(i64::from(i), "i8"))?),
193            HdbValue::BIGINT(i) => Ok(num::cast(i).ok_or_else(|| number_range(i, "i8"))?),
194            HdbValue::DECIMAL(bigdec) => bigdec.to_i8().ok_or_else(|| decimal_range("i8")),
195            HdbValue::STRING(s) => s.parse().map_err(|e: ParseIntError| parse_int_err(&e)),
196            value => Err(wrong_type(&value, "i8")),
197        }
198    }
199}
200
201impl DbValueInto<i16> for HdbValue<'static> {
202    fn try_into(self) -> Result<i16, ConversionError> {
203        match self {
204            HdbValue::TINYINT(u) => Ok(i16::from(u)),
205            HdbValue::SMALLINT(i) => Ok(i),
206            HdbValue::INT(i) => Ok(num::cast(i).ok_or_else(|| number_range(i64::from(i), "u8"))?),
207            HdbValue::BIGINT(i) => Ok(num::cast(i).ok_or_else(|| number_range(i, "u8"))?),
208            HdbValue::DECIMAL(bigdec) => bigdec.to_i16().ok_or_else(|| decimal_range("i16")),
209            HdbValue::STRING(s) => s.parse().map_err(|e: ParseIntError| parse_int_err(&e)),
210            value => Err(wrong_type(&value, "i16")),
211        }
212    }
213}
214
215impl DbValueInto<i32> for HdbValue<'static> {
216    fn try_into(self) -> Result<i32, ConversionError> {
217        match self {
218            HdbValue::TINYINT(u) => Ok(i32::from(u)),
219            HdbValue::SMALLINT(i) => Ok(i32::from(i)),
220            HdbValue::INT(i) => Ok(i),
221            HdbValue::BIGINT(i) => Ok(num::cast(i).ok_or_else(|| number_range(i, "i32"))?),
222            HdbValue::DECIMAL(bigdec) => bigdec.to_i32().ok_or_else(|| decimal_range("i32")),
223            HdbValue::STRING(s) => s.parse().map_err(|e: ParseIntError| parse_int_err(&e)),
224            value => Err(wrong_type(&value, "i32")),
225        }
226    }
227}
228
229impl DbValueInto<i64> for HdbValue<'static> {
230    fn try_into(self) -> Result<i64, ConversionError> {
231        match self {
232            HdbValue::TINYINT(u) => Ok(i64::from(u)),
233            HdbValue::SMALLINT(i) => Ok(i64::from(i)),
234            HdbValue::INT(i) => Ok(i64::from(i)),
235            HdbValue::BIGINT(i) => Ok(i),
236            HdbValue::LONGDATE(ld) => Ok(*ld.ref_raw()),
237            HdbValue::SECONDDATE(sd) => Ok(*sd.ref_raw()),
238            HdbValue::DECIMAL(bigdec) => bigdec.to_i64().ok_or_else(|| decimal_range("i64")),
239            HdbValue::STRING(s) => s.parse().map_err(|e: ParseIntError| parse_int_err(&e)),
240            value => Err(wrong_type(&value, "i64")),
241        }
242    }
243}
244
245impl DbValueInto<f32> for HdbValue<'static> {
246    fn try_into(self) -> Result<f32, ConversionError> {
247        match self {
248            HdbValue::DECIMAL(bigdec) => bigdec.to_f32().ok_or_else(|| decimal_range("f32")),
249            HdbValue::REAL(f) => Ok(f),
250            HdbValue::STRING(s) => s.parse().map_err(|e: ParseFloatError| parse_float_err(&e)),
251            value => Err(wrong_type(&value, "f32")),
252        }
253    }
254}
255
256impl DbValueInto<f64> for HdbValue<'static> {
257    fn try_into(self) -> Result<f64, ConversionError> {
258        match self {
259            HdbValue::DECIMAL(bigdec) => bigdec.to_f64().ok_or_else(|| decimal_range("f64")),
260            HdbValue::DOUBLE(f) => Ok(f),
261            HdbValue::STRING(s) => s.parse().map_err(|e: ParseFloatError| parse_float_err(&e)),
262            value => Err(wrong_type(&value, "f64")),
263        }
264    }
265}
266
267impl DbValueInto<String> for HdbValue<'static> {
268    fn try_into(self) -> Result<String, ConversionError> {
269        trace!("try_into -> String");
270        match self {
271            HdbValue::NULL => Ok(String::from("<NULL>")), // FIXME intentionally NOT implemented!?
272            HdbValue::TINYINT(i) => Ok(format!("{i}")),
273            HdbValue::SMALLINT(i) => Ok(format!("{i}")),
274            HdbValue::INT(i) => Ok(format!("{i}")),
275            HdbValue::BIGINT(i) => Ok(format!("{i}")),
276            HdbValue::REAL(f) => Ok(format!("{f}")),
277            HdbValue::DOUBLE(f) => Ok(format!("{f}")),
278            HdbValue::STRING(s) => Ok(s),
279            HdbValue::DBSTRING(bytes) => {
280                Err(ConversionError::Other(Box::new(HdbError::Cesu8AsBytes {
281                    bytes,
282                })))
283            }
284            HdbValue::LONGDATE(ld) => Ok(str_from(&ld)),
285            HdbValue::SECONDDATE(sd) => Ok(str_from(&sd)),
286            HdbValue::DAYDATE(date) => Ok(str_from(&date)),
287            HdbValue::SECONDTIME(time) => Ok(str_from(&time)),
288            HdbValue::DECIMAL(bigdec) => Ok(format!("{bigdec}")),
289
290            #[cfg(feature = "sync")]
291            HdbValue::SYNC_CLOB(clob) => Ok(clob
292                .into_string_if_complete()
293                .map_err(|e| ConversionError::Incomplete(e.to_string()))?),
294            #[cfg(feature = "async")]
295            HdbValue::ASYNC_CLOB(clob) => Ok(clob
296                .into_string_if_complete()
297                .map_err(|e| ConversionError::Incomplete(e.to_string()))?),
298
299            #[cfg(feature = "sync")]
300            HdbValue::SYNC_NCLOB(nclob) => Ok(nclob
301                .into_string_if_complete()
302                .map_err(|e| ConversionError::Incomplete(e.to_string()))?),
303            #[cfg(feature = "async")]
304            HdbValue::ASYNC_NCLOB(nclob) => Ok(nclob
305                .into_string_if_complete()
306                .map_err(|e| ConversionError::Incomplete(e.to_string()))?),
307
308            value => Err(wrong_type(&value, "String")),
309        }
310    }
311}
312
313impl DbValueInto<Vec<u8>> for HdbValue<'static> {
314    fn try_into(self) -> Result<Vec<u8>, ConversionError> {
315        match self {
316            #[cfg(feature = "sync")]
317            HdbValue::SYNC_BLOB(blob) => Ok(blob
318                .into_bytes_if_complete()
319                .map_err(|e| ConversionError::Incomplete(e.to_string()))?),
320
321            #[cfg(feature = "async")]
322            HdbValue::ASYNC_BLOB(blob) => Ok(blob
323                .into_bytes_if_complete()
324                .map_err(|e| ConversionError::Incomplete(e.to_string()))?),
325
326            HdbValue::BINARY(v) | HdbValue::GEOMETRY(v) | HdbValue::POINT(v) => Ok(v),
327
328            HdbValue::STRING(s) => Ok(s.into_bytes()),
329            HdbValue::DBSTRING(v) => Ok(v),
330
331            value => Err(wrong_type(&value, "Vec<u8>")),
332        }
333    }
334}
335
336fn wrong_type(tv: &HdbValue, ovt: &str) -> ConversionError {
337    ConversionError::ValueType(format!(
338        "The value {tv:?} cannot be converted into type {ovt}",
339    ))
340}
341
342fn number_range(value: i64, ovt: &str) -> ConversionError {
343    ConversionError::NumberRange(format!(
344        "The value {value:?} exceeds the number range of type {ovt}",
345    ))
346}
347
348fn decimal_range(ovt: &str) -> ConversionError {
349    ConversionError::NumberRange(format!(
350        "The given decimal value cannot be converted into a number of type {ovt}",
351    ))
352}
353
354fn parse_int_err(e: &ParseIntError) -> ConversionError {
355    ConversionError::ValueType(e.to_string())
356}
357
358fn parse_float_err(e: &ParseFloatError) -> ConversionError {
359    ConversionError::ValueType(e.to_string())
360}
361
362/// Deserializes a `LongDate` into a String format.
363fn str_from<T: fmt::Display>(t: &T) -> String {
364    format!("{t}")
365}
366
367// TODO improve this implementation
368impl From<HdbError> for DeserializationError {
369    fn from(e: HdbError) -> Self {
370        Self::Usage(e.to_string())
371    }
372}