1use chrono::{
16 DateTime, Datelike, FixedOffset, LocalResult, NaiveDate, NaiveDateTime, TimeZone, Utc,
17};
18use chrono_tz::Tz;
19use std::collections::HashMap;
20use std::hash::Hash;
21
22use crate::error::{ConvertError, Error, Result};
23
24use super::{NumberValue, Value, DAYS_FROM_CE};
25use jiff::{tz::TimeZone as JiffTimeZone, Timestamp, Zoned};
26
27impl TryFrom<Value> for bool {
28 type Error = Error;
29 fn try_from(val: Value) -> Result<Self> {
30 match val {
31 Value::Boolean(b) => Ok(b),
32 Value::Number(n) => Ok(n != NumberValue::Int8(0)),
33 _ => Err(ConvertError::new("bool", format!("{val:?}")).into()),
34 }
35 }
36}
37
38macro_rules! impl_try_from_number_value {
40 ($($t:ty),*) => {
41 $(
42 impl TryFrom<Value> for $t {
43 type Error = Error;
44 fn try_from(val: Value) -> Result<Self> {
45 match val {
46 Value::Number(NumberValue::Int8(i)) => Ok(i as $t),
47 Value::Number(NumberValue::Int16(i)) => Ok(i as $t),
48 Value::Number(NumberValue::Int32(i)) => Ok(i as $t),
49 Value::Number(NumberValue::Int64(i)) => Ok(i as $t),
50 Value::Number(NumberValue::UInt8(i)) => Ok(i as $t),
51 Value::Number(NumberValue::UInt16(i)) => Ok(i as $t),
52 Value::Number(NumberValue::UInt32(i)) => Ok(i as $t),
53 Value::Number(NumberValue::UInt64(i)) => Ok(i as $t),
54 Value::Number(NumberValue::Float32(i)) => Ok(i as $t),
55 Value::Number(NumberValue::Float64(i)) => Ok(i as $t),
56 Value::Date(i) => Ok(i as $t),
57 _ => Err(ConvertError::new("number", format!("{:?}", val)).into()),
58 }
59 }
60 }
61 )*
62 };
63}
64
65impl_try_from_number_value!(u8);
66impl_try_from_number_value!(u16);
67impl_try_from_number_value!(u32);
68impl_try_from_number_value!(u64);
69impl_try_from_number_value!(i8);
70impl_try_from_number_value!(i16);
71impl_try_from_number_value!(i32);
72impl_try_from_number_value!(i64);
73impl_try_from_number_value!(f32);
74impl_try_from_number_value!(f64);
75
76fn unix_micros_from_zoned(zdt: &Zoned) -> i64 {
77 zdt.timestamp().as_microsecond()
78}
79
80fn naive_datetime_from_micros(micros: i64) -> Result<NaiveDateTime> {
81 DateTime::<Utc>::from_timestamp_micros(micros)
82 .map(|dt| dt.naive_utc())
83 .ok_or_else(|| Error::Parsing(format!("invalid unix timestamp {micros}")))
84}
85
86pub fn zoned_to_chrono_datetime(zdt: &Zoned) -> Result<DateTime<Tz>> {
87 let tz_name = zdt.time_zone().iana_name().ok_or_else(|| {
88 ConvertError::new(
89 "DateTime",
90 "timestamp does not contain an IANA time zone".to_string(),
91 )
92 })?;
93 let tz: Tz = tz_name.parse().map_err(|_| {
94 ConvertError::new(
95 "DateTime",
96 format!("invalid time zone identifier {tz_name}"),
97 )
98 })?;
99 let micros = unix_micros_from_zoned(zdt);
100 match tz.timestamp_micros(micros) {
101 LocalResult::Single(dt) => Ok(dt),
102 LocalResult::Ambiguous(dt, _) => Ok(dt),
103 LocalResult::None => Err(Error::Parsing(format!(
104 "time {micros} not exists in timezone {tz_name}"
105 ))),
106 }
107}
108
109pub fn zoned_to_chrono_fixed_offset(zdt: &Zoned) -> Result<DateTime<FixedOffset>> {
110 let offset_seconds = zdt.offset().seconds();
111 let offset = FixedOffset::east_opt(offset_seconds)
112 .ok_or_else(|| Error::Parsing(format!("invalid offset {offset_seconds}")))?;
113 let micros = unix_micros_from_zoned(zdt);
114 let naive = naive_datetime_from_micros(micros)?;
115 Ok(DateTime::<FixedOffset>::from_naive_utc_and_offset(
116 naive, offset,
117 ))
118}
119
120fn zoned_from_naive_datetime(naive_dt: &NaiveDateTime) -> Zoned {
121 let micros = naive_dt.and_utc().timestamp_micros();
122 let timestamp = Timestamp::from_microsecond(micros)
123 .expect("NaiveDateTime out of range for Timestamp conversion");
124 timestamp.to_zoned(JiffTimeZone::UTC)
125}
126
127impl TryFrom<Value> for NaiveDateTime {
128 type Error = Error;
129 fn try_from(val: Value) -> Result<Self> {
130 match val {
131 Value::Timestamp(dt) => naive_datetime_from_micros(unix_micros_from_zoned(&dt)),
132 _ => Err(ConvertError::new("NaiveDateTime", format!("{val}")).into()),
133 }
134 }
135}
136
137impl TryFrom<Value> for DateTime<Tz> {
138 type Error = Error;
139 fn try_from(val: Value) -> Result<Self> {
140 match val {
141 Value::Timestamp(dt) => zoned_to_chrono_datetime(&dt),
142 _ => Err(ConvertError::new("DateTime", format!("{val}")).into()),
143 }
144 }
145}
146
147impl TryFrom<Value> for NaiveDate {
148 type Error = Error;
149 fn try_from(val: Value) -> Result<Self> {
150 match val {
151 Value::Date(i) => {
152 let days = i + DAYS_FROM_CE;
153 match NaiveDate::from_num_days_from_ce_opt(days) {
154 Some(d) => Ok(d),
155 None => Err(ConvertError::new("NaiveDate", "".to_string()).into()),
156 }
157 }
158 _ => Err(ConvertError::new("NaiveDate", format!("{val}")).into()),
159 }
160 }
161}
162
163impl<V> TryFrom<Value> for Vec<V>
164where
165 V: TryFrom<Value, Error = Error>,
166{
167 type Error = Error;
168 fn try_from(val: Value) -> Result<Self> {
169 match val {
170 Value::Binary(vals) => vals
171 .into_iter()
172 .map(|v| V::try_from(Value::Number(NumberValue::UInt8(v))))
173 .collect(),
174 Value::Array(vals) => vals.into_iter().map(V::try_from).collect(),
175 Value::EmptyArray => Ok(vec![]),
176 _ => Err(ConvertError::new("Vec", format!("{val}")).into()),
177 }
178 }
179}
180
181impl<K, V> TryFrom<Value> for HashMap<K, V>
182where
183 K: TryFrom<Value, Error = Error> + Eq + Hash,
184 V: TryFrom<Value, Error = Error>,
185{
186 type Error = Error;
187 fn try_from(val: Value) -> Result<Self> {
188 match val {
189 Value::Map(kvs) => {
190 let mut map = HashMap::new();
191 for (k, v) in kvs {
192 let k = K::try_from(k)?;
193 let v = V::try_from(v)?;
194 map.insert(k, v);
195 }
196 Ok(map)
197 }
198 Value::EmptyMap => Ok(HashMap::new()),
199 _ => Err(ConvertError::new("HashMap", format!("{val}")).into()),
200 }
201 }
202}
203
204macro_rules! replace_expr {
205 ($_t:tt $sub:expr) => {
206 $sub
207 };
208}
209
210macro_rules! impl_tuple_from_value {
212 ( $($Ti:tt),+ ) => {
213 impl<$($Ti),+> TryFrom<Value> for ($($Ti,)+)
214 where
215 $($Ti: TryFrom<Value>),+
216 {
217 type Error = String;
218 fn try_from(val: Value) -> Result<Self, String> {
219 let expected_len = <[()]>::len(&[$(replace_expr!(($Ti) ())),*]);
223
224 match val {
225 Value::Tuple(vals) => {
226 if expected_len != vals.len() {
227 return Err(format!("value tuple size mismatch: expected {} columns, got {}", expected_len, vals.len()));
228 }
229 let mut vals_iter = vals.into_iter().enumerate();
230
231 Ok((
232 $(
233 {
234 let (col_ix, col_value) = vals_iter
235 .next()
236 .unwrap(); let t = col_value.get_type();
239 $Ti::try_from(col_value)
240 .map_err(|_| format!("failed converting column {} from type({:?}) to type({})", col_ix, t, std::any::type_name::<$Ti>()))?
241 }
242 ,)+
243 ))
244 }
245 _ => Err(format!("expected tuple, got {:?}", val)),
246 }
247 }
248 }
249 }
250}
251
252impl_tuple_from_value!(T1);
254impl_tuple_from_value!(T1, T2);
255impl_tuple_from_value!(T1, T2, T3);
256impl_tuple_from_value!(T1, T2, T3, T4);
257impl_tuple_from_value!(T1, T2, T3, T4, T5);
258impl_tuple_from_value!(T1, T2, T3, T4, T5, T6);
259impl_tuple_from_value!(T1, T2, T3, T4, T5, T6, T7);
260impl_tuple_from_value!(T1, T2, T3, T4, T5, T6, T7, T8);
261impl_tuple_from_value!(T1, T2, T3, T4, T5, T6, T7, T8, T9);
262impl_tuple_from_value!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
263impl_tuple_from_value!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
264impl_tuple_from_value!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
265impl_tuple_from_value!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13);
266impl_tuple_from_value!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14);
267impl_tuple_from_value!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15);
268impl_tuple_from_value!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16);
269impl_tuple_from_value!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17);
270impl_tuple_from_value!(
271 T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18
272);
273impl_tuple_from_value!(
274 T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19
275);
276impl_tuple_from_value!(
277 T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20
278);
279impl_tuple_from_value!(
280 T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21
281);
282impl_tuple_from_value!(
283 T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21,
284 T22
285);
286
287macro_rules! impl_try_from_to_option {
289 ($($t:ty),*) => {
290 $(
291 impl TryFrom<Value> for Option<$t> {
292 type Error = Error;
293 fn try_from(val: Value) -> Result<Self> {
294 match val {
295 Value::Null => Ok(None),
296 _ => {
297 let inner: $t = val.try_into()?;
298 Ok(Some(inner))
299 },
300 }
301
302 }
303 }
304 )*
305 };
306}
307
308impl_try_from_to_option!(String);
309impl_try_from_to_option!(bool);
310impl_try_from_to_option!(u8);
311impl_try_from_to_option!(u16);
312impl_try_from_to_option!(u32);
313impl_try_from_to_option!(u64);
314impl_try_from_to_option!(i8);
315impl_try_from_to_option!(i16);
316impl_try_from_to_option!(i32);
317impl_try_from_to_option!(i64);
318impl_try_from_to_option!(f32);
319impl_try_from_to_option!(f64);
320impl_try_from_to_option!(NaiveDateTime);
321impl_try_from_to_option!(NaiveDate);
322
323impl From<&String> for Value {
324 fn from(s: &String) -> Self {
325 Value::String(s.clone())
326 }
327}
328
329impl From<String> for Value {
330 fn from(s: String) -> Self {
331 Value::String(s)
332 }
333}
334
335impl From<&str> for Value {
336 fn from(s: &str) -> Self {
337 Value::String(s.to_string())
338 }
339}
340
341impl From<bool> for Value {
342 fn from(b: bool) -> Self {
343 Value::Boolean(b)
344 }
345}
346
347impl From<&bool> for Value {
348 fn from(b: &bool) -> Self {
349 Value::Boolean(*b)
350 }
351}
352
353impl From<u8> for Value {
354 fn from(n: u8) -> Self {
355 Value::Number(NumberValue::UInt8(n))
356 }
357}
358
359impl From<&u8> for Value {
360 fn from(n: &u8) -> Self {
361 Value::Number(NumberValue::UInt8(*n))
362 }
363}
364
365impl From<u16> for Value {
366 fn from(n: u16) -> Self {
367 Value::Number(NumberValue::UInt16(n))
368 }
369}
370
371impl From<&u16> for Value {
372 fn from(n: &u16) -> Self {
373 Value::Number(NumberValue::UInt16(*n))
374 }
375}
376
377impl From<u32> for Value {
378 fn from(n: u32) -> Self {
379 Value::Number(NumberValue::UInt32(n))
380 }
381}
382
383impl From<&u32> for Value {
384 fn from(n: &u32) -> Self {
385 Value::Number(NumberValue::UInt32(*n))
386 }
387}
388
389impl From<u64> for Value {
390 fn from(n: u64) -> Self {
391 Value::Number(NumberValue::UInt64(n))
392 }
393}
394
395impl From<&u64> for Value {
396 fn from(n: &u64) -> Self {
397 Value::Number(NumberValue::UInt64(*n))
398 }
399}
400
401impl From<i8> for Value {
402 fn from(n: i8) -> Self {
403 Value::Number(NumberValue::Int8(n))
404 }
405}
406
407impl From<&i8> for Value {
408 fn from(n: &i8) -> Self {
409 Value::Number(NumberValue::Int8(*n))
410 }
411}
412
413impl From<i16> for Value {
414 fn from(n: i16) -> Self {
415 Value::Number(NumberValue::Int16(n))
416 }
417}
418
419impl From<&i16> for Value {
420 fn from(n: &i16) -> Self {
421 Value::Number(NumberValue::Int16(*n))
422 }
423}
424
425impl From<i32> for Value {
426 fn from(n: i32) -> Self {
427 Value::Number(NumberValue::Int32(n))
428 }
429}
430
431impl From<&i32> for Value {
432 fn from(n: &i32) -> Self {
433 Value::Number(NumberValue::Int32(*n))
434 }
435}
436
437impl From<i64> for Value {
438 fn from(n: i64) -> Self {
439 Value::Number(NumberValue::Int64(n))
440 }
441}
442
443impl From<&i64> for Value {
444 fn from(n: &i64) -> Self {
445 Value::Number(NumberValue::Int64(*n))
446 }
447}
448
449impl From<f32> for Value {
450 fn from(n: f32) -> Self {
451 Value::Number(NumberValue::Float32(n))
452 }
453}
454
455impl From<&f32> for Value {
456 fn from(n: &f32) -> Self {
457 Value::Number(NumberValue::Float32(*n))
458 }
459}
460
461impl From<f64> for Value {
462 fn from(n: f64) -> Self {
463 Value::Number(NumberValue::Float64(n))
464 }
465}
466
467impl From<NaiveDate> for Value {
468 fn from(date: NaiveDate) -> Self {
469 let days = date.num_days_from_ce() - DAYS_FROM_CE;
470 Value::Date(days)
471 }
472}
473
474impl From<&NaiveDate> for Value {
475 fn from(date: &NaiveDate) -> Self {
476 let days = date.num_days_from_ce() - DAYS_FROM_CE;
477 Value::Date(days)
478 }
479}
480
481impl From<NaiveDateTime> for Value {
482 fn from(naive_dt: NaiveDateTime) -> Self {
483 Value::Timestamp(zoned_from_naive_datetime(&naive_dt))
484 }
485}
486
487impl From<&NaiveDateTime> for Value {
488 fn from(naive_dt: &NaiveDateTime) -> Self {
489 Value::Timestamp(zoned_from_naive_datetime(naive_dt))
490 }
491}
492
493impl From<&f64> for Value {
494 fn from(n: &f64) -> Self {
495 Value::Number(NumberValue::Float64(*n))
496 }
497}