1#![allow(unused_imports)]
2use crate::{
3 Error, FixedDecimal, Interval, Passive, Result, Value, consume_while, extract_number,
4 month_to_number, number_to_month, truncate_long,
5};
6use anyhow::Context;
7#[cfg(feature = "chrono")]
8use chrono::{Datelike, Timelike};
9use rust_decimal::{Decimal, prelude::FromPrimitive, prelude::ToPrimitive};
10use std::{
11 any, array,
12 borrow::Cow,
13 cell::{Cell, RefCell},
14 collections::{BTreeMap, HashMap, LinkedList, VecDeque},
15 hash::Hash,
16 rc::Rc,
17 sync::{Arc, RwLock},
18};
19use time::{Month, PrimitiveDateTime, format_description::parse_borrowed};
20use uuid::Uuid;
21
22pub trait AsValue {
24 fn as_empty_value() -> Value;
26 fn as_value(self) -> Value;
28 fn try_from_value(value: Value) -> Result<Self>
30 where
31 Self: Sized;
32 fn parse(input: impl AsRef<str>) -> Result<Self>
34 where
35 Self: Sized,
36 {
37 Err(Error::msg(format!(
38 "Cannot parse '{}' as {} (the parse method is not implemented)",
39 truncate_long!(input.as_ref()),
40 any::type_name::<Self>()
41 )))
42 }
43}
44
45impl AsValue for Value {
46 fn as_empty_value() -> Value {
47 Value::Null
48 }
49 fn as_value(self) -> Value {
50 self
51 }
52 fn try_from_value(value: Value) -> Result<Self>
53 where
54 Self: Sized,
55 {
56 Ok(value)
57 }
58}
59
60impl From<&'static str> for Value {
61 fn from(value: &'static str) -> Self {
62 Value::Varchar(Some(value.into()))
63 }
64}
65
66macro_rules! impl_as_value {
67 ($source:ty, $destination:path $(, $pat_rest:pat => $expr_rest:expr)* $(,)?) => {
68 impl AsValue for $source {
69 fn as_empty_value() -> Value {
70 $destination(None)
71 }
72 fn as_value(self) -> Value {
73 $destination(Some(self as _))
74 }
75 fn try_from_value(value: Value) -> Result<Self> {
76 match value {
77 $destination(Some(v), ..) => Ok(v as _),
78 $($pat_rest => $expr_rest,)*
79 #[allow(unreachable_patterns)]
80 Value::Int32(Some(v), ..) => {
81 if (v as i128).clamp(<$source>::MIN as _, <$source>::MAX as _) != v as i128 {
82 return Err(Error::msg(format!(
83 "Value {v}: i32 is out of range for {}",
84 any::type_name::<Self>(),
85 )));
86 }
87 Ok(v as $source)
88 }
89 #[allow(unreachable_patterns)]
90 Value::Int64(Some(v), ..) => {
92 if (v as i128).clamp(<$source>::MIN as _, <$source>::MAX as _) != v as i128 {
93 return Err(Error::msg(format!(
94 "Value {v}: i64 is out of range for {}",
95 any::type_name::<Self>(),
96 )));
97 }
98 Ok(v as $source)
99 }
100 #[allow(unreachable_patterns)]
101 Value::Int128(Some(v), ..) => {
103 if v < 0 || v > u64::MAX as _ {
104 return Err(Error::msg(format!("Value {v}: i128 does not fit into u64")));
105 }
106 Ok(v as _)
107 },
108 Value::Json(Some(serde_json::Value::Number(v)), ..) => {
109 if let Some(v) = v.as_i128()
110 && v.clamp(<$source>::MIN as _, <$source>::MAX as _) == v as i128 {
111 return Ok(v as $source);
112 }
113 Err(Error::msg(format!(
114 "Value {v} from json number is out of range for {}",
115 any::type_name::<Self>(),
116 )))
117 }
118 Value::Json(Some(serde_json::Value::String(ref v)), ..) => <Self as AsValue>::parse(v),
120 Value::Unknown(Some(ref v), ..) => Self::parse(v),
121 _ => Err(Error::msg(format!(
122 "Cannot convert {value:?} to {}",
123 any::type_name::<Self>(),
124 ))),
125 }
126 }
127 fn parse(input: impl AsRef<str>) -> Result<Self> {
128 input.as_ref().parse::<Self>().map_err(Into::into)
129 }
130 }
131 };
132}
133impl_as_value!(
134 i8,
135 Value::Int8,
136 Value::UInt8(Some(v), ..) => Ok(v as _),
137 Value::Int16(Some(v), ..) => {
138 let result = v as i8;
139 if result as i16 != v {
140 return Err(Error::msg(format!("Value {v}: i16 is out of range for i8")));
141 }
142 Ok(result)
143 },
144);
145impl_as_value!(
146 i16,
147 Value::Int16,
148 Value::Int8(Some(v), ..) => Ok(v as _),
149 Value::UInt16(Some(v), ..) => Ok(v as _),
150 Value::UInt8(Some(v), ..) => Ok(v as _),
151);
152impl_as_value!(
153 i32,
154 Value::Int32,
155 Value::Int16(Some(v), ..) => Ok(v as _),
156 Value::Int8(Some(v), ..) => Ok(v as _),
157 Value::UInt32(Some(v), ..) => Ok(v as _),
158 Value::UInt16(Some(v), ..) => Ok(v as _),
159 Value::UInt8(Some(v), ..) => Ok(v as _),
160 Value::Decimal(Some(v), ..) => {
161 let error = Error::msg(format!("Value {v}: Decimal does not fit into i32"));
162 if !v.is_integer() {
163 return Err(error.context("The value is not an integer"));
164 }
165 v.to_i32().ok_or(error)
166 }
167);
168impl_as_value!(
169 i64,
170 Value::Int64,
171 Value::Int32(Some(v), ..) => Ok(v as _),
172 Value::Int16(Some(v), ..) => Ok(v as _),
173 Value::Int8(Some(v), ..) => Ok(v as _),
174 Value::UInt64(Some(v), ..) => Ok(v as _),
175 Value::UInt32(Some(v), ..) => Ok(v as _),
176 Value::UInt16(Some(v), ..) => Ok(v as _),
177 Value::UInt8(Some(v), ..) => Ok(v as _),
178 Value::Decimal(Some(v), ..) => {
179 let error = Error::msg(format!("Value {v}: Decimal does not fit into i64"));
180 if !v.is_integer() {
181 return Err(error.context("The value is not an integer"));
182 }
183 v.to_i64().ok_or(error)
184 }
185);
186impl_as_value!(
187 i128,
188 Value::Int128,
189 Value::Int64(Some(v), ..) => Ok(v as _),
190 Value::Int32(Some(v), ..) => Ok(v as _),
191 Value::Int16(Some(v), ..) => Ok(v as _),
192 Value::Int8(Some(v), ..) => Ok(v as _),
193 Value::UInt128(Some(v), ..) => Ok(v as _),
194 Value::UInt64(Some(v), ..) => Ok(v as _),
195 Value::UInt32(Some(v), ..) => Ok(v as _),
196 Value::UInt16(Some(v), ..) => Ok(v as _),
197 Value::UInt8(Some(v), ..) => Ok(v as _),
198 Value::Decimal(Some(v), ..) => {
199 let error = Error::msg(format!("Value {v}: Decimal does not fit into i128"));
200 if !v.is_integer() {
201 return Err(error.context("The value is not an integer"));
202 }
203 v.to_i128().ok_or(error)
204 }
205);
206impl_as_value!(
207 isize,
208 Value::Int64,
209 Value::Int32(Some(v), ..) => Ok(v as _),
210 Value::Int16(Some(v), ..) => Ok(v as _),
211 Value::Int8(Some(v), ..) => Ok(v as _),
212 Value::UInt64(Some(v), ..) => Ok(v as _),
213 Value::UInt32(Some(v), ..) => Ok(v as _),
214 Value::UInt16(Some(v), ..) => Ok(v as _),
215 Value::UInt8(Some(v), ..) => Ok(v as _),
216 Value::Decimal(Some(v), ..) => {
217 let error = Error::msg(format!("Value {v}: Decimal does not fit into i64"));
218 if !v.is_integer() {
219 return Err(error.context("The value is not an integer"));
220 }
221 v.to_isize().ok_or(error)
222 }
223);
224impl_as_value!(
225 u8,
226 Value::UInt8,
227 Value::Int16(Some(v), ..) => {
228 v.to_u8().ok_or(Error::msg(format!("Value {v}: i16 is out of range for u8")))
229 }
230);
231impl_as_value!(
232 u16,
233 Value::UInt16,
234 Value::UInt8(Some(v), ..) => Ok(v as _),
235 Value::Int32(Some(v), ..) => {
236 let result = v as u16;
237 if result as i32 != v {
238 return Err(Error::msg(format!("Value {v}: i32 is out of range for u16")));
239 }
240 Ok(result)
241 }
242);
243impl_as_value!(
244 u32,
245 Value::UInt32,
246 Value::UInt16(Some(v), ..) => Ok(v as _),
247 Value::UInt8(Some(v), ..) => Ok(v as _),
248);
249impl_as_value!(
250 u64,
251 Value::UInt64,
252 Value::UInt32(Some(v), ..) => Ok(v as _),
253 Value::UInt16(Some(v), ..) => Ok(v as _),
254 Value::UInt8(Some(v), ..) => Ok(v as _),
255 Value::Decimal(Some(v), ..) => {
256 let error = Error::msg(format!("Value {v}: Decimal does not fit into u64"));
257 if !v.is_integer() {
258 return Err(error.context("The value is not an integer"));
259 }
260 v.to_u64().ok_or(error)
261 }
262);
263impl_as_value!(
264 u128,
265 Value::UInt128,
266 Value::UInt64(Some(v), ..) => Ok(v as _),
267 Value::UInt32(Some(v), ..) => Ok(v as _),
268 Value::UInt16(Some(v), ..) => Ok(v as _),
269 Value::UInt8(Some(v), ..) => Ok(v as _),
270 Value::Decimal(Some(v), ..) => {
271 let error = Error::msg(format!("Value {v}: Decimal does not fit into u128"));
272 if !v.is_integer() {
273 return Err(error.context("The value is not an integer"));
274 }
275 v.to_u128().ok_or(error)
276 }
277);
278impl_as_value!(
279 usize,
280 Value::UInt64,
281 Value::UInt32(Some(v), ..) => Ok(v as _),
282 Value::UInt16(Some(v), ..) => Ok(v as _),
283 Value::UInt8(Some(v), ..) => Ok(v as _),
284 Value::Decimal(Some(v), ..) => {
285 let error = Error::msg(format!("Value {v}: Decimal does not fit into u64"));
286 if !v.is_integer() {
287 return Err(error.context("The value is not an integer"));
288 }
289 v.to_usize().ok_or(error)
290 }
291);
292
293macro_rules! impl_as_value {
294 ($source:ty, $destination:path, $extract:expr $(, $pat_rest:pat => $expr_rest:expr)* $(,)?) => {
295 impl AsValue for $source {
296 fn as_empty_value() -> Value {
297 $destination(None)
298 }
299 fn as_value(self) -> Value {
300 $destination(Some(self.into()))
301 }
302 fn try_from_value(value: Value) -> Result<Self> {
303 match value {
304 $destination(Some(v), ..) => Ok(v.into()),
305 $($pat_rest => $expr_rest,)*
306 Value::Unknown(Some(ref v), ..) => <Self as AsValue>::parse(v),
307 _ => Err(Error::msg(format!(
308 "Cannot convert {value:?} to {}",
309 any::type_name::<Self>(),
310 ))),
311 }
312 }
313 fn parse(input: impl AsRef<str>) -> Result<Self> {
314 $extract(input.as_ref())
315 }
316 }
317 };
318}
319impl_as_value!(
320 bool,
321 Value::Boolean,
322 |input: &str| {
323 match input {
324 x if x.eq_ignore_ascii_case("true") || x.eq_ignore_ascii_case("t") || x.eq("1") => Ok(true),
325 x if x.eq_ignore_ascii_case("false") || x.eq_ignore_ascii_case("f") || x.eq("0") => Ok(false),
326 _ => return Err(Error::msg(format!("Cannot parse boolean from `{input}`")))
327 }
328 },
329 Value::Int8(Some(v), ..) => Ok(v != 0),
330 Value::Int16(Some(v), ..) => Ok(v != 0),
331 Value::Int32(Some(v), ..) => Ok(v != 0),
332 Value::Int64(Some(v), ..) => Ok(v != 0),
333 Value::Int128(Some(v), ..) => Ok(v != 0),
334 Value::UInt8(Some(v), ..) => Ok(v != 0),
335 Value::UInt16(Some(v), ..) => Ok(v != 0),
336 Value::UInt32(Some(v), ..) => Ok(v != 0),
337 Value::UInt64(Some(v), ..) => Ok(v != 0),
338 Value::UInt128(Some(v), ..) => Ok(v != 0),
339 Value::Json(Some(serde_json::Value::Bool(v)), ..) => Ok(v)
340);
341impl_as_value!(
342 f32,
343 Value::Float32,
344 |input: &str| Ok(input.parse::<f32>()?),
345 Value::Float64(Some(v), ..) => Ok(v as _),
346 Value::Decimal(Some(v), ..) => Ok(v.try_into()?),
347 Value::Json(Some(serde_json::Value::Number(v)), ..) => {
348 let Some(v) = v.as_f64() else {
349 return Err(Error::msg(format!("Cannot convert json number `{v:?}` into f32")));
350 };
351 Ok(v as _)
352 }
353);
354impl_as_value!(
355 f64,
356 Value::Float64,
357 |input: &str| Ok(input.parse::<f64>()?),
358 Value::Float32(Some(v), ..) => Ok(v as _),
359 Value::Decimal(Some(v), ..) => Ok(v.try_into()?),
360 Value::Json(Some(serde_json::Value::Number(v)), ..) => {
361 let Some(v) = v.as_f64() else {
362 return Err(Error::msg(format!("Cannot convert json number `{v:?}` into f32")));
363 };
364 Ok(v)
365 }
366);
367
368impl_as_value!(
369 char,
370 Value::Char,
371 |input: &str| {
372 if input.len() != 1 {
373 return Err(Error::msg(format!("Cannot convert `{input:?}` into a char")))
374 }
375 Ok(input.chars().next().expect("Should have one character"))
376 },
377 Value::Varchar(Some(v), ..) => {
378 if v.len() != 1 {
379 return Err(Error::msg(format!(
380 "Cannot convert varchar `{}` into a char because it has more than one character",
381 truncate_long!(v)
382 )))
383 }
384 Ok(v.chars().next().unwrap())
385 },
386 Value::Json(Some(serde_json::Value::String(v)), ..) => {
387 if v.len() != 1 {
388 return Err(Error::msg(format!(
389 "Cannot convert json `{}` into a char because it has more than one character",
390 truncate_long!(v)
391 )))
392 }
393 Ok(v.chars().next().unwrap())
394 }
395);
396impl_as_value!(
397 String,
398 Value::Varchar,
399 |input: &str| {
400 Ok(input.into())
401 },
402 Value::Char(Some(v), ..) => Ok(v.into()),
403 Value::Json(Some(serde_json::Value::String(v)), ..) => Ok(v),
404);
405impl_as_value!(Box<[u8]>, Value::Blob, |mut input: &str| {
406 if input.starts_with("\\x") {
407 input = &input[2..];
408 }
409 let filter_x = input.contains('x');
410 let result = if filter_x {
411 hex::decode(input.chars().filter(|c| *c != 'x').collect::<String>())
412 } else {
413 hex::decode(input)
414 }
415 .map(Into::into)
416 .context(format!(
417 "While decoding `{}` as {}",
418 truncate_long!(input),
419 any::type_name::<Self>()
420 ))?;
421 Ok(result)
422});
423impl_as_value!(
424 Interval,
425 Value::Interval,
426 |mut input: &str| {
427 let context = || {
428 Error::msg(format!(
429 "Cannot parse interval from `{}`",
430 truncate_long!(input)
431 ))
432 .into()
433 };
434 match input.chars().peekable().peek() {
435 Some(v) if *v == '"' || *v == '\'' => {
436 input = &input[1..];
437 if !input.ends_with(*v) {
438 return Err(context());
439 }
440 input = input.trim_end_matches(*v);
441 }
442 _ => {}
443 };
444 let mut interval = Interval::ZERO;
445 loop {
446 let mut cur = input;
447 let Ok(count) = extract_number::<true>(&mut cur).parse::<i128>() else {
448 break;
449 };
450 cur = cur.trim_start();
451 let unit = consume_while(&mut cur, char::is_ascii_alphabetic);
452 if unit.is_empty() {
453 break;
454 }
455 match unit {
456 x if x.eq_ignore_ascii_case("y")
457 || x.eq_ignore_ascii_case("year")
458 || x.eq_ignore_ascii_case("years") =>
459 {
460 interval += Interval::from_years(count as _)
461 }
462 x if x.eq_ignore_ascii_case("mon")
463 || x.eq_ignore_ascii_case("mons")
464 || x.eq_ignore_ascii_case("month")
465 || x.eq_ignore_ascii_case("months") =>
466 {
467 interval += Interval::from_months(count as _)
468 }
469 x if x.eq_ignore_ascii_case("d")
470 || x.eq_ignore_ascii_case("day")
471 || x.eq_ignore_ascii_case("days") =>
472 {
473 interval += Interval::from_days(count as _)
474 }
475 x if x.eq_ignore_ascii_case("h")
476 || x.eq_ignore_ascii_case("hour")
477 || x.eq_ignore_ascii_case("hours") =>
478 {
479 interval += Interval::from_hours(count as _)
480 }
481 x if x.eq_ignore_ascii_case("min")
482 || x.eq_ignore_ascii_case("mins")
483 || x.eq_ignore_ascii_case("minute")
484 || x.eq_ignore_ascii_case("minutes") =>
485 {
486 interval += Interval::from_mins(count as _)
487 }
488 x if x.eq_ignore_ascii_case("s")
489 || x.eq_ignore_ascii_case("sec")
490 || x.eq_ignore_ascii_case("secs")
491 || x.eq_ignore_ascii_case("second")
492 || x.eq_ignore_ascii_case("seconds") =>
493 {
494 interval += Interval::from_secs(count as _)
495 }
496 x if x.eq_ignore_ascii_case("micro")
497 || x.eq_ignore_ascii_case("micros")
498 || x.eq_ignore_ascii_case("microsecond")
499 || x.eq_ignore_ascii_case("microseconds") =>
500 {
501 interval += Interval::from_micros(count as _)
502 }
503 x if x.eq_ignore_ascii_case("ns")
504 || x.eq_ignore_ascii_case("nano")
505 || x.eq_ignore_ascii_case("nanos")
506 || x.eq_ignore_ascii_case("nanosecond")
507 || x.eq_ignore_ascii_case("nanoseconds") =>
508 {
509 interval += Interval::from_nanos(count as _)
510 }
511 _ => return Err(context()),
512 }
513 input = cur.trim_start();
514 }
515 let neg = if Some('-') == input.chars().next() {
516 input = input[1..].trim_ascii_start();
517 true
518 } else {
519 false
520 };
521 let mut time_interval = Interval::ZERO;
522 let num = extract_number::<true>(&mut input);
523 if !num.is_empty() {
524 let num = num.parse::<u64>().with_context(context)?;
525 time_interval += Interval::from_hours(num as _);
526 if Some(':') == input.chars().next() {
527 input = &input[1..];
528 let num = extract_number::<false>(&mut input).parse::<u64>()?;
529 if input.is_empty() {
530 return Err(context());
531 }
532 time_interval += Interval::from_mins(num as _);
533 if Some(':') == input.chars().next() {
534 input = &input[1..];
535 let num = extract_number::<false>(&mut input)
536 .parse::<u64>()
537 .with_context(context)?;
538 time_interval += Interval::from_secs(num as _);
539 if Some('.') == input.chars().next() {
540 input = &input[1..];
541 let len = input.len();
542 let mut num = extract_number::<true>(&mut input)
543 .parse::<i128>()
544 .with_context(context)?;
545 let magnitude = (len - 1) / 3;
546 num *= 10_i128.pow(2 - (len + 2) as u32 % 3);
547 match magnitude {
548 0 => time_interval += Interval::from_millis(num),
549 1 => time_interval += Interval::from_micros(num),
550 2 => time_interval += Interval::from_nanos(num),
551 _ => return Err(context()),
552 }
553 }
554 }
555 }
556 if neg {
557 interval -= time_interval;
558 } else {
559 interval += time_interval;
560 }
561 }
562 if !input.is_empty() {
563 return Err(context());
564 }
565 Ok(interval)
566 },
567 Value::Json(Some(serde_json::Value::String(ref v)), ..) => <Self as AsValue>::parse(v),
568);
569impl_as_value!(
570 std::time::Duration,
571 Value::Interval,
572 |v| <Interval as AsValue>::parse(v).map(Into::into),
573 Value::Json(Some(serde_json::Value::String(ref v)), ..) => <Self as AsValue>::parse(v),
574);
575impl_as_value!(
576 time::Duration,
577 Value::Interval,
578 |v| <Interval as AsValue>::parse(v).map(Into::into),
579 Value::Json(Some(serde_json::Value::String(ref v)), ..) => <Self as AsValue>::parse(v),
580);
581impl_as_value!(
582 Uuid,
583 Value::Uuid,
584 |input: &str| {
585 let uuid = Uuid::parse_str(input).with_context(|| {
586 format!(
587 "Cannot parse a uuid value from `{}`",
588 truncate_long!(input)
589 )
590 })?;
591 Ok(uuid)
592 },
593 Value::Varchar(Some(v), ..) => <Self as AsValue>::parse(v),
594 Value::Json(Some(serde_json::Value::String(ref v)), ..) => <Self as AsValue>::parse(v),
595);
596
597macro_rules! parse_time {
598 ($value: ident, $($formats:literal),+ $(,)?) => {
599 'value: {
600 let context = || Error::msg(format!(
601 "Cannot parse `{}` as {}",
602 truncate_long!($value),
603 any::type_name::<Self>()
604 ));
605 for format in [$($formats,)+] {
606 let format = parse_borrowed::<2>(format)?;
607 let mut parsed = time::parsing::Parsed::new();
608 let remaining = parsed.parse_items($value.as_bytes(), &format);
609 if let Ok(remaining) = remaining {
610 let result = parsed.try_into().with_context(context)?;
611 $value = &$value[($value.len() - remaining.len())..];
612 break 'value Ok(result);
613 }
614 }
615 Err(context())
616 }
617 }
618}
619
620impl_as_value!(
621 time::Date,
622 Value::Date,
623 |input: &str| {
624 let mut value = input;
625 let mut result: time::Date = parse_time!(value, "[year]-[month]-[day]")?;
626 {
627 let mut attempt = value.trim_start();
628 let suffix = consume_while(&mut attempt, char::is_ascii_alphabetic);
629 if suffix.eq_ignore_ascii_case("bc") {
630 result =
631 time::Date::from_calendar_date(-(result.year() - 1), result.month(), result.day())?;
632 value = attempt;
633 }
634 if suffix.eq_ignore_ascii_case("ad") {
635 value = attempt
636 }
637 }
638 if !value.is_empty() {
639 return Err(Error::msg(format!("Cannot parse `{}` as time::Date", truncate_long!(input))))
640 }
641 Ok(result)
642 },
643 Value::Varchar(Some(v), ..) => <Self as AsValue>::parse(v),
644 Value::Json(Some(serde_json::Value::String(ref v)), ..) => <Self as AsValue>::parse(v),
645);
646impl_as_value!(
647 time::Time,
648 Value::Time,
649 |mut input: &str| {
650 let result: time::Time = parse_time!(
651 input,
652 "[hour]:[minute]:[second].[subsecond]",
653 "[hour]:[minute]:[second]",
654 "[hour]:[minute]",
655 )?;
656 if !input.is_empty() {
657 return Err(Error::msg(format!("Cannot parse `{}` as time::Time", truncate_long!(input))))
658 }
659 Ok(result)
660 },
661 Value::Interval(Some(v), ..) => {
662 let (h, m, s, ns) = v.as_hmsns();
663 time::Time::from_hms_nano(h as _, m, s, ns,)
664 .map_err(|e| Error::msg(format!("Cannot convert interval `{v:?}` into time: {e:?}")))
665 },
666 Value::Varchar(Some(v), ..) => <Self as AsValue>::parse(v),
667 Value::Json(Some(serde_json::Value::String(ref v)), ..) => <Self as AsValue>::parse(v),
668);
669
670impl_as_value!(
671 time::PrimitiveDateTime,
672 Value::Timestamp,
673 |mut input: &str| {
674 let result: time::PrimitiveDateTime = parse_time!(
675 input,
676 "[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond]",
677 "[year]-[month]-[day]T[hour]:[minute]:[second]",
678 "[year]-[month]-[day]T[hour]:[minute]",
679 "[year]-[month]-[day] [hour]:[minute]:[second].[subsecond]",
680 "[year]-[month]-[day] [hour]:[minute]:[second]",
681 "[year]-[month]-[day] [hour]:[minute]",
682 )?;
683 if !input.is_empty() {
684 return Err(Error::msg(format!("Cannot parse `{}` as time::PrimitiveDateTime", truncate_long!(input))))
685 }
686 Ok(result)
687 },
688 Value::Varchar(Some(v), ..) => <Self as AsValue>::parse(v),
689 Value::Json(Some(serde_json::Value::String(ref v)), ..) => <Self as AsValue>::parse(v),
690);
691
692impl_as_value!(
693 time::OffsetDateTime,
694 Value::TimestampWithTimezone,
695 |mut input: &str| {
696 if let Ok::<time::OffsetDateTime, _>(result) = parse_time!(
697 input,
698 "[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond][offset_hour sign:mandatory]:[offset_minute]",
699 "[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond][offset_hour sign:mandatory]",
700 "[year]-[month]-[day]T[hour]:[minute]:[second][offset_hour sign:mandatory]:[offset_minute]",
701 "[year]-[month]-[day]T[hour]:[minute]:[second][offset_hour sign:mandatory]",
702 "[year]-[month]-[day]T[hour]:[minute][offset_hour sign:mandatory]:[offset_minute]",
703 "[year]-[month]-[day]T[hour]:[minute][offset_hour sign:mandatory]",
704 "[year]-[month]-[day] [hour]:[minute]:[second].[subsecond][offset_hour sign:mandatory]:[offset_minute]",
705 "[year]-[month]-[day] [hour]:[minute]:[second].[subsecond][offset_hour sign:mandatory]",
706 "[year]-[month]-[day] [hour]:[minute]:[second][offset_hour sign:mandatory]:[offset_minute]",
707 "[year]-[month]-[day] [hour]:[minute]:[second][offset_hour sign:mandatory]",
708 "[year]-[month]-[day] [hour]:[minute][offset_hour sign:mandatory]:[offset_minute]",
709 "[year]-[month]-[day] [hour]:[minute][offset_hour sign:mandatory]",
710 ) {
711 return Ok(result);
712 }
713 if let Ok(result) = <PrimitiveDateTime as AsValue>::parse(input).map(|v| v.assume_utc()) {
714 return Ok(result);
715 }
716 Err(Error::msg(format!("Cannot parse `{}` as time::OffsetDateTime", truncate_long!(input))))
717 },
718 Value::Timestamp(Some(timestamp), ..) => Ok(timestamp.assume_utc()),
719 Value::Varchar(Some(v), ..) => <Self as AsValue>::parse(v),
720 Value::Json(Some(serde_json::Value::String(ref v)), ..) => <Self as AsValue>::parse(v),
721);
722
723#[cfg(feature = "chrono")]
724impl AsValue for chrono::NaiveDate {
725 fn as_empty_value() -> Value {
726 Value::Date(None)
727 }
728 fn as_value(self) -> Value {
729 Value::Date(
730 'date: {
731 time::Date::from_calendar_date(
732 self.year(),
733 number_to_month!(
734 self.month(),
735 break 'date Err(Error::msg(format!(
736 "Unexpected month value {}",
737 self.month()
738 )))
739 ),
740 self.day() as _,
741 )
742 .map_err(Into::into)
743 }
744 .inspect_err(|e| {
745 log::error!("Could not create a Value::Date from chrono::NaiveDate: {e:?}");
746 })
747 .ok(),
748 )
749 }
750 fn try_from_value(value: Value) -> Result<Self>
751 where
752 Self: Sized,
753 {
754 let context = Arc::new(format!(
755 "Could not create a chrono::NaiveDate from {value:?}"
756 ));
757 let v = <time::Date as AsValue>::try_from_value(value).context(context.clone())?;
758 chrono::NaiveDate::from_ymd_opt(v.year(), month_to_number!(v.month()), v.day() as _)
759 .context(context)
760 }
761}
762
763#[cfg(feature = "chrono")]
764impl AsValue for chrono::NaiveTime {
765 fn as_empty_value() -> Value {
766 Value::Time(None)
767 }
768 fn as_value(self) -> Value {
769 Value::Time(
770 time::Time::from_hms_nano(
771 self.hour() as _,
772 self.minute() as _,
773 self.second() as _,
774 self.nanosecond() as _,
775 )
776 .inspect_err(|e| {
777 log::error!("Could not create a Value::Time from chrono::NaiveTime: {e:?}",)
778 })
779 .ok(),
780 )
781 }
782 fn try_from_value(value: Value) -> Result<Self>
783 where
784 Self: Sized,
785 {
786 let context = Arc::new(format!(
787 "Could not create a chrono::NaiveTime from {value:?}"
788 ));
789 let v = <time::Time as AsValue>::try_from_value(value).context(context.clone())?;
790 Self::from_hms_nano_opt(
791 v.hour() as _,
792 v.minute() as _,
793 v.second() as _,
794 v.nanosecond() as _,
795 )
796 .context(context)
797 }
798}
799
800#[cfg(feature = "chrono")]
801impl AsValue for chrono::NaiveDateTime {
802 fn as_empty_value() -> Value {
803 Value::Timestamp(None)
804 }
805 fn as_value(self) -> Value {
806 Value::Timestamp(
807 'value: {
808 let Ok(date) = AsValue::try_from_value(self.date().as_value()) else {
809 break 'value Err(Error::msg(
810 "failed to convert the date part from chrono::NaiveDate to time::Date",
811 ));
812 };
813 let Ok(time) = AsValue::try_from_value(self.time().as_value()) else {
814 break 'value Err(Error::msg(
815 "failed to convert the time part from chrono::NaiveTime to time::Time",
816 ));
817 };
818 Ok(time::PrimitiveDateTime::new(date, time))
819 }
820 .inspect_err(|e| {
821 log::error!(
822 "Could not create a Value::Timestamp from chrono::NaiveDateTime: {e:?}",
823 );
824 })
825 .ok(),
826 )
827 }
828 fn try_from_value(value: Value) -> Result<Self>
829 where
830 Self: Sized,
831 {
832 let context = Arc::new(format!(
833 "Could not create a chrono::NaiveDateTime from {value:?}"
834 ));
835 let v =
836 <time::PrimitiveDateTime as AsValue>::try_from_value(value).context(context.clone())?;
837 let date = AsValue::try_from_value(v.date().as_value()).context(context.clone())?;
838 let time = AsValue::try_from_value(v.time().as_value()).context(context.clone())?;
839 Ok(Self::new(date, time))
840 }
841}
842
843#[cfg(feature = "chrono")]
844impl AsValue for chrono::DateTime<chrono::FixedOffset> {
845 fn as_empty_value() -> Value {
846 Value::TimestampWithTimezone(None)
847 }
848 fn as_value(self) -> Value {
849 Value::TimestampWithTimezone(
850 'value: {
851 use chrono::Offset;
852 let Ok(date) = AsValue::try_from_value(self.date_naive().as_value()) else {
853 break 'value Err(Error::msg(
854 "failed to convert the date part from chrono::NaiveDate to time::Date",
855 ));
856 };
857 let Ok(time) = AsValue::try_from_value(self.time().as_value()) else {
858 break 'value Err(Error::msg(
859 "failed to convert the time part from chrono::NaiveTime to time::Time",
860 ));
861 };
862 let Ok(offset) =
863 time::UtcOffset::from_whole_seconds(self.offset().fix().local_minus_utc())
864 else {
865 break 'value Err(Error::msg("failed to convert the offset part from"));
866 };
867 Ok(time::OffsetDateTime::new_in_offset(date, time, offset))
868 }
869 .inspect_err(|e| {
870 log::error!(
871 "Could not create a Value::Timestamp from chrono::NaiveDateTime: {e:?}",
872 );
873 })
874 .ok(),
875 )
876 }
877 fn try_from_value(value: Value) -> Result<Self>
878 where
879 Self: Sized,
880 {
881 let context = Arc::new(format!(
882 "Could not create a chrono::DateTime from {value:?}"
883 ));
884 let v =
885 <time::OffsetDateTime as AsValue>::try_from_value(value).context(context.clone())?;
886 let date = AsValue::try_from_value(v.date().as_value()).context(context.clone())?;
887 let time = AsValue::try_from_value(v.time().as_value()).context(context.clone())?;
888 let date_time = chrono::NaiveDateTime::new(date, time);
889 let offset =
890 chrono::FixedOffset::east_opt(v.offset().whole_seconds()).context(context.clone())?;
891 Ok(Self::from_naive_utc_and_offset(date_time, offset))
892 }
893}
894
895#[cfg(feature = "chrono")]
896impl AsValue for chrono::DateTime<chrono::Utc> {
897 fn as_empty_value() -> Value {
898 Value::TimestampWithTimezone(None)
899 }
900 fn as_value(self) -> Value {
901 let odt = time::OffsetDateTime::from_unix_timestamp_nanos(
902 self.timestamp_nanos_opt().unwrap() as i128,
903 )
904 .unwrap();
905 Value::TimestampWithTimezone(Some(odt))
906 }
907 fn try_from_value(value: Value) -> Result<Self> {
908 let odt = <time::OffsetDateTime as AsValue>::try_from_value(value)?;
909 let utc_odt = odt.to_offset(time::UtcOffset::UTC);
910 let secs = utc_odt.unix_timestamp();
911 let nanos = utc_odt.nanosecond();
912 Self::from_timestamp(secs, nanos)
913 .ok_or_else(|| Error::msg("Timestamp out of range for chrono::DateTime<Utc>"))
914 }
915}
916
917impl AsValue for Decimal {
918 fn as_empty_value() -> Value {
919 Value::Decimal(None, 0, 0)
920 }
921 fn as_value(self) -> Value {
922 Value::Decimal(Some(self), 0, self.scale() as _)
923 }
924 fn try_from_value(value: Value) -> Result<Self> {
925 match value {
926 Value::Decimal(Some(v), ..) => Ok(v),
927 Value::Int8(Some(v), ..) => Ok(Decimal::new(v as i64, 0)),
928 Value::Int16(Some(v), ..) => Ok(Decimal::new(v as i64, 0)),
929 Value::Int32(Some(v), ..) => Ok(Decimal::new(v as i64, 0)),
930 Value::Int64(Some(v), ..) => Ok(Decimal::new(v, 0)),
931 Value::UInt8(Some(v), ..) => Ok(Decimal::new(v as i64, 0)),
932 Value::UInt16(Some(v), ..) => Ok(Decimal::new(v as i64, 0)),
933 Value::UInt32(Some(v), ..) => Ok(Decimal::new(v as i64, 0)),
934 Value::UInt64(Some(v), ..) => Ok(Decimal::new(v as i64, 0)),
935 Value::Float32(Some(v), ..) => Ok(Decimal::from_f32(v)
936 .ok_or(Error::msg(format!("Cannot convert {value:?} to Decimal")))?),
937 Value::Float64(Some(v), ..) => Ok(Decimal::from_f64(v)
938 .ok_or(Error::msg(format!("Cannot convert {value:?} to Decimal")))?),
939 Value::Json(Some(serde_json::Value::Number(v)), ..) => {
940 if let Some(v) = v.as_i128()
941 && let Some(v) = Decimal::from_i128(v)
942 {
943 return Ok(v);
944 }
945 Err(Error::msg(format!(
946 "Value {v} from json number is out of range for {}",
947 any::type_name::<Self>(),
948 )))
949 }
950 Value::Unknown(Some(v), ..) => Self::parse(&v),
951 _ => Err(Error::msg(format!("Cannot convert {value:?} to Decimal"))),
952 }
953 }
954 fn parse(input: impl AsRef<str>) -> Result<Self> {
955 let input = input.as_ref();
956 Ok(input.parse::<Decimal>().with_context(|| {
957 Error::msg(format!(
958 "Cannot parse a decimal value from `{}`",
959 truncate_long!(input)
960 ))
961 })?)
962 }
963}
964
965impl<const W: u8, const S: u8> AsValue for FixedDecimal<W, S> {
966 fn as_empty_value() -> Value {
967 Decimal::as_empty_value()
968 }
969 fn as_value(self) -> Value {
970 Value::Decimal(Some(self.0), W, self.0.scale() as _)
971 }
972 fn try_from_value(value: Value) -> Result<Self>
973 where
974 Self: Sized,
975 {
976 Ok(Self(Decimal::try_from_value(value)?))
977 }
978 fn parse(input: impl AsRef<str>) -> Result<Self> {
979 <Decimal as AsValue>::parse(input).map(Into::into)
980 }
981}
982
983impl<T: AsValue, const N: usize> AsValue for [T; N] {
984 fn as_empty_value() -> Value {
985 Value::Array(None, Box::new(T::as_empty_value()), N as u32)
986 }
987 fn as_value(self) -> Value {
988 Value::Array(
989 Some(self.into_iter().map(AsValue::as_value).collect()),
990 Box::new(T::as_empty_value()),
991 N as u32,
992 )
993 }
994 fn try_from_value(value: Value) -> Result<Self> {
995 fn convert_iter<T: AsValue, const N: usize>(
996 iter: impl IntoIterator<Item: AsValue>,
997 ) -> Result<[T; N]> {
998 iter.into_iter()
999 .map(|v| T::try_from_value(v.as_value()))
1000 .collect::<Result<Vec<_>>>()?
1001 .try_into()
1002 .map_err(|v: Vec<T>| {
1003 Error::msg(format!(
1004 "Expected array of length {N}, got {} elements ({})",
1005 v.len(),
1006 any::type_name::<[T; N]>()
1007 ))
1008 })
1009 }
1010 match value {
1011 Value::Varchar(Some(v), ..)
1012 if matches!(T::as_empty_value(), Value::Char(..)) && v.len() == N =>
1013 {
1014 convert_iter(v.chars())
1015 }
1016 Value::List(Some(v), ..) if v.len() == N => convert_iter(v.into_iter()),
1017 Value::Array(Some(v), ..) if v.len() == N => convert_iter(v.into_iter()),
1018 Value::Json(Some(serde_json::Value::Array(v))) if v.len() == N => {
1019 convert_iter(v.into_iter())
1020 }
1021 Value::Unknown(Some(v)) => <Self as AsValue>::parse(v),
1022 _ => Err(Error::msg(format!(
1023 "Cannot convert {value:?} to array {}",
1024 any::type_name::<Self>()
1025 ))),
1026 }
1027 }
1028}
1029
1030macro_rules! impl_as_value {
1031 ($source:ident) => {
1032 impl<T: AsValue> AsValue for $source<T> {
1033 fn as_empty_value() -> Value {
1034 Value::List(None, Box::new(T::as_empty_value()))
1035 }
1036 fn as_value(self) -> Value {
1037 Value::List(
1038 Some(self.into_iter().map(AsValue::as_value).collect()),
1039 Box::new(T::as_empty_value()),
1040 )
1041 }
1042 fn try_from_value(value: Value) -> Result<Self> {
1043 match value {
1044 Value::List(Some(v), ..) => Ok(v
1045 .into_iter()
1046 .map(|v| Ok::<_, Error>(<T as AsValue>::try_from_value(v)?))
1047 .collect::<Result<_>>()?),
1048 Value::List(None, ..) => Ok($source::<T>::new()),
1049 Value::Array(Some(v), ..) => Ok(v
1050 .into_iter()
1051 .map(|v| Ok::<_, Error>(<T as AsValue>::try_from_value(v)?))
1052 .collect::<Result<_>>()?),
1053 Value::Json(Some(serde_json::Value::Array(v)), ..) => Ok(v
1054 .into_iter()
1055 .map(|v| Ok::<_, Error>(<T as AsValue>::try_from_value(v.as_value())?))
1056 .collect::<Result<_>>()?),
1057 _ => Err(Error::msg(format!(
1058 "Cannot convert {value:?} to {}",
1059 any::type_name::<Self>(),
1060 ))),
1061 }
1062 }
1063 }
1064 };
1065}
1066impl_as_value!(Vec);
1067impl_as_value!(VecDeque);
1068impl_as_value!(LinkedList);
1069
1070macro_rules! impl_as_value {
1071 ($source:ident, $($key_trait:ident),+) => {
1072 impl<K: AsValue $(+ $key_trait)+, V: AsValue> AsValue for $source<K, V> {
1073 fn as_empty_value() -> Value {
1074 Value::Map(None, K::as_empty_value().into(), V::as_empty_value().into())
1075 }
1076 fn as_value(self) -> Value {
1077 Value::Map(
1078 Some(
1079 self.into_iter()
1080 .map(|(k, v)| (k.as_value(), v.as_value()))
1081 .collect(),
1082 ),
1083 K::as_empty_value().into(),
1084 V::as_empty_value().into(),
1085 )
1086 }
1087 fn try_from_value(value: Value) -> Result<Self> {
1088 match value {
1089 Value::Map(Some(v), ..) => {
1090 Ok(v.into_iter()
1091 .map(|(k, v)| {
1092 Ok((
1093 <K as AsValue>::try_from_value(k)?,
1094 <V as AsValue>::try_from_value(v)?,
1095 ))
1096 })
1097 .collect::<Result<_>>()?)
1098 }
1099 Value::Json(Some(serde_json::Value::Object(v)), ..) => {
1100 Ok(v.into_iter()
1101 .map(|(k, v)| {
1102 Ok((
1103 <K as AsValue>::try_from_value(serde_json::Value::String(k).as_value())?,
1104 <V as AsValue>::try_from_value(v.as_value())?,
1105 ))
1106 })
1107 .collect::<Result<_>>()?)
1108 }
1109 _=> {
1110 Err(Error::msg(format!(
1111 "Cannot convert {value:?} to {}",
1112 any::type_name::<Self>(),
1113 )))
1114 }
1115 }
1116 }
1117 }
1118 }
1119}
1120impl_as_value!(BTreeMap, Ord);
1121impl_as_value!(HashMap, Eq, Hash);
1122
1123impl AsValue for &'static str {
1124 fn as_empty_value() -> Value {
1125 Value::Varchar(None)
1126 }
1127 fn as_value(self) -> Value {
1128 Value::Varchar(Some(self.into()))
1129 }
1130 fn try_from_value(_value: Value) -> Result<Self>
1131 where
1132 Self: Sized,
1133 {
1134 Err(Error::msg(
1135 "Cannot get a string reference from a owned value",
1136 ))
1137 }
1138}
1139
1140impl AsValue for Cow<'static, str> {
1141 fn as_empty_value() -> Value {
1142 Value::Varchar(None)
1143 }
1144 fn as_value(self) -> Value {
1145 Value::Varchar(Some(self.into()))
1146 }
1147 fn try_from_value(value: Value) -> Result<Self>
1148 where
1149 Self: Sized,
1150 {
1151 String::try_from_value(value).map(Into::into)
1152 }
1153 fn parse(input: impl AsRef<str>) -> Result<Self>
1154 where
1155 Self: Sized,
1156 {
1157 <String as AsValue>::parse(input).map(Into::into)
1158 }
1159}
1160
1161impl<T: AsValue> AsValue for Passive<T> {
1162 fn as_empty_value() -> Value {
1163 T::as_empty_value()
1164 }
1165 fn as_value(self) -> Value {
1166 match self {
1167 Passive::Set(v) => v.as_value(),
1168 Passive::NotSet => T::as_empty_value(),
1169 }
1170 }
1171 fn try_from_value(value: Value) -> Result<Self> {
1172 Ok(Passive::Set(<T as AsValue>::try_from_value(value)?))
1173 }
1174}
1175
1176impl<T: AsValue> AsValue for Option<T> {
1177 fn as_empty_value() -> Value {
1178 T::as_empty_value()
1179 }
1180 fn as_value(self) -> Value {
1181 match self {
1182 Some(v) => v.as_value(),
1183 None => T::as_empty_value(),
1184 }
1185 }
1186 fn try_from_value(value: Value) -> Result<Self> {
1187 Ok(if value.is_null() {
1188 None
1189 } else {
1190 Some(<T as AsValue>::try_from_value(value)?)
1191 })
1192 }
1193 fn parse(input: impl AsRef<str>) -> Result<Self>
1194 where
1195 Self: Sized,
1196 {
1197 let mut value = input.as_ref();
1198 let result = consume_while(&mut value, |v| v.is_alphanumeric() || *v == '_');
1199 if result.eq_ignore_ascii_case("null") {
1200 return Ok(None);
1201 };
1202 T::parse(input).map(Some)
1203 }
1204}
1205
1206impl<T: AsValue> AsValue for Box<T> {
1208 fn as_empty_value() -> Value {
1209 T::as_empty_value()
1210 }
1211 fn as_value(self) -> Value {
1212 (*self).as_value()
1213 }
1214 fn try_from_value(value: Value) -> Result<Self> {
1215 Ok(Self::new(<T as AsValue>::try_from_value(value)?))
1216 }
1217 fn parse(input: impl AsRef<str>) -> Result<Self>
1218 where
1219 Self: Sized,
1220 {
1221 T::parse(input).map(Self::new)
1222 }
1223}
1224
1225macro_rules! impl_as_value {
1226 ($source:ident) => {
1227 impl<T: AsValue + ToOwned<Owned = impl AsValue>> AsValue for $source<T> {
1228 fn as_empty_value() -> Value {
1229 T::as_empty_value()
1230 }
1231 fn as_value(self) -> Value {
1232 $source::<T>::into_inner(self).as_value()
1233 }
1234 fn try_from_value(value: Value) -> Result<Self> {
1235 Ok($source::new(<T as AsValue>::try_from_value(value)?))
1236 }
1237 }
1238 };
1239}
1240impl_as_value!(Cell);
1242impl_as_value!(RefCell);
1243
1244impl<T: AsValue> AsValue for RwLock<T> {
1245 fn as_empty_value() -> Value {
1246 T::as_empty_value()
1247 }
1248 fn as_value(self) -> Value {
1249 self.into_inner()
1250 .expect("Error occurred while trying to take the content of the RwLock")
1251 .as_value()
1252 }
1253 fn try_from_value(value: Value) -> Result<Self> {
1254 Ok(RwLock::new(<T as AsValue>::try_from_value(value)?))
1255 }
1256 fn parse(input: impl AsRef<str>) -> Result<Self>
1257 where
1258 Self: Sized,
1259 {
1260 T::parse(input).map(Self::new)
1261 }
1262}
1263
1264macro_rules! impl_as_value {
1265 ($source:ident) => {
1266 impl<T: AsValue + ToOwned<Owned = impl AsValue>> AsValue for $source<T> {
1267 fn as_empty_value() -> Value {
1268 T::as_empty_value()
1269 }
1270 fn as_value(self) -> Value {
1271 $source::try_unwrap(self)
1272 .map(|v| v.as_value())
1273 .unwrap_or_else(|v| v.as_ref().to_owned().as_value())
1274 }
1275 fn try_from_value(value: Value) -> Result<Self> {
1276 Ok($source::new(<T as AsValue>::try_from_value(value)?))
1277 }
1278 fn parse(input: impl AsRef<str>) -> Result<Self>
1279 where
1280 Self: Sized,
1281 {
1282 T::parse(input).map(Self::new)
1283 }
1284 }
1285 };
1286}
1287impl_as_value!(Arc);
1288impl_as_value!(Rc);
1289
1290impl AsValue for serde_json::Value {
1291 fn as_empty_value() -> Value {
1292 Value::Json(None)
1293 }
1294 fn as_value(self) -> Value {
1295 Value::Json(Some(self))
1296 }
1297 fn try_from_value(value: Value) -> Result<Self>
1298 where
1299 Self: Sized,
1300 {
1301 Ok(if let Value::Json(v) = value {
1302 match v {
1303 Some(v) => v,
1304 None => Self::Null,
1305 }
1306 } else {
1307 return Err(Error::msg(
1308 "Cannot convert non json tank::Value to serde_json::Value",
1309 ));
1310 })
1311 }
1312}