1use crate::ast::*;
2use crate::error::{Error, ErrorKind};
3
4#[cfg(feature = "bigdecimal")]
5use bigdecimal::{BigDecimal, FromPrimitive, ToPrimitive};
6#[cfg(feature = "chrono")]
7use chrono::{DateTime, NaiveDate, NaiveTime, Utc};
8#[cfg(feature = "json")]
9use serde_json::{Number, Value as JsonValue};
10use std::{
11 borrow::{Borrow, Cow},
12 convert::TryFrom,
13 fmt,
14 str::FromStr,
15};
16#[cfg(feature = "uuid")]
17use uuid::Uuid;
18
19#[derive(Debug, Clone, PartialEq)]
21pub struct Raw<'a>(pub(crate) Value<'a>);
22
23pub trait IntoRaw<'a> {
27 fn raw(self) -> Raw<'a>;
28}
29
30impl<'a, T> IntoRaw<'a> for T
31where
32 T: Into<Value<'a>>,
33{
34 fn raw(self) -> Raw<'a> {
35 Raw(self.into())
36 }
37}
38
39#[derive(Debug, Clone, PartialEq)]
43pub enum Value<'a> {
44 Int32(Option<i32>),
46 Int64(Option<i64>),
48 Float(Option<f32>),
50 Double(Option<f64>),
52 Text(Option<Cow<'a, str>>),
54 Enum(Option<Cow<'a, str>>),
56 Bytes(Option<Cow<'a, [u8]>>),
58 Boolean(Option<bool>),
60 Char(Option<char>),
62 Array(Option<Vec<Value<'a>>>),
64 #[cfg(feature = "bigdecimal")]
66 #[cfg_attr(feature = "docs", doc(cfg(feature = "bigdecimal")))]
67 Numeric(Option<BigDecimal>),
68 #[cfg(feature = "json")]
69 #[cfg_attr(feature = "docs", doc(cfg(feature = "json")))]
70 Json(Option<serde_json::Value>),
72 Xml(Option<Cow<'a, str>>),
74 #[cfg(feature = "uuid")]
75 #[cfg_attr(feature = "docs", doc(cfg(feature = "uuid")))]
76 Uuid(Option<Uuid>),
78 #[cfg(feature = "chrono")]
79 #[cfg_attr(feature = "docs", doc(cfg(feature = "chrono")))]
80 DateTime(Option<DateTime<Utc>>),
82 #[cfg(feature = "chrono")]
83 #[cfg_attr(feature = "docs", doc(cfg(feature = "chrono")))]
84 Date(Option<NaiveDate>),
86 #[cfg(feature = "chrono")]
87 #[cfg_attr(feature = "docs", doc(cfg(feature = "chrono")))]
88 Time(Option<NaiveTime>),
90}
91
92pub(crate) struct Params<'a>(pub(crate) &'a [Value<'a>]);
93
94impl<'a> fmt::Display for Params<'a> {
95 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
96 let len = self.0.len();
97
98 write!(f, "[")?;
99 for (i, val) in self.0.iter().enumerate() {
100 write!(f, "{val}")?;
101
102 if i < (len - 1) {
103 write!(f, ",")?;
104 }
105 }
106 write!(f, "]")
107 }
108}
109
110impl<'a> fmt::Display for Value<'a> {
111 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112 let res = match self {
113 Value::Int32(val) => val.map(|v| write!(f, "{v}")),
114 Value::Int64(val) => val.map(|v| write!(f, "{v}")),
115 Value::Float(val) => val.map(|v| write!(f, "{v}")),
116 Value::Double(val) => val.map(|v| write!(f, "{v}")),
117 Value::Text(val) => val.as_ref().map(|v| write!(f, "\"{v}\"")),
118 Value::Bytes(val) => val.as_ref().map(|v| write!(f, "<{} bytes blob>", v.len())),
119 Value::Enum(val) => val.as_ref().map(|v| write!(f, "\"{v}\"")),
120 Value::Boolean(val) => val.map(|v| write!(f, "{v}")),
121 Value::Char(val) => val.map(|v| write!(f, "'{v}'")),
122 Value::Array(vals) => vals.as_ref().map(|vals| {
123 let len = vals.len();
124
125 write!(f, "[")?;
126 for (i, val) in vals.iter().enumerate() {
127 write!(f, "{val}")?;
128
129 if i < (len - 1) {
130 write!(f, ",")?;
131 }
132 }
133 write!(f, "]")
134 }),
135 Value::Xml(val) => val.as_ref().map(|v| write!(f, "{v}")),
136 #[cfg(feature = "bigdecimal")]
137 Value::Numeric(val) => val.as_ref().map(|v| write!(f, "{v}")),
138 #[cfg(feature = "json")]
139 Value::Json(val) => val.as_ref().map(|v| write!(f, "{v}")),
140 #[cfg(feature = "uuid")]
141 Value::Uuid(val) => val.map(|v| write!(f, "\"{v}\"")),
142 #[cfg(feature = "chrono")]
143 Value::DateTime(val) => val.map(|v| write!(f, "\"{v}\"")),
144 #[cfg(feature = "chrono")]
145 Value::Date(val) => val.map(|v| write!(f, "\"{v}\"")),
146 #[cfg(feature = "chrono")]
147 Value::Time(val) => val.map(|v| write!(f, "\"{v}\"")),
148 };
149
150 match res {
151 Some(r) => r,
152 None => write!(f, "null"),
153 }
154 }
155}
156
157#[cfg(feature = "json")]
158#[cfg_attr(feature = "docs", doc(cfg(feature = "json")))]
159impl<'a> From<Value<'a>> for serde_json::Value {
160 fn from(pv: Value<'a>) -> Self {
161 let res = match pv {
162 Value::Int32(i) => i.map(|i| serde_json::Value::Number(Number::from(i))),
163 Value::Int64(i) => i.map(|i| serde_json::Value::Number(Number::from(i))),
164 Value::Float(f) => f.map(|f| match Number::from_f64(f as f64) {
165 Some(number) => serde_json::Value::Number(number),
166 None => serde_json::Value::Null,
167 }),
168 Value::Double(f) => f.map(|f| match Number::from_f64(f) {
169 Some(number) => serde_json::Value::Number(number),
170 None => serde_json::Value::Null,
171 }),
172 Value::Text(cow) => cow.map(|cow| serde_json::Value::String(cow.into_owned())),
173 Value::Bytes(bytes) => bytes.map(|bytes| serde_json::Value::String(base64::encode(bytes))),
174 Value::Enum(cow) => cow.map(|cow| serde_json::Value::String(cow.into_owned())),
175 Value::Boolean(b) => b.map(serde_json::Value::Bool),
176 Value::Char(c) => c.map(|c| {
177 let bytes = [c as u8];
178 let s = std::str::from_utf8(&bytes).expect("interpret byte as UTF-8").to_string();
179 serde_json::Value::String(s)
180 }),
181 Value::Xml(cow) => cow.map(|cow| serde_json::Value::String(cow.into_owned())),
182 Value::Array(v) => {
183 v.map(|v| serde_json::Value::Array(v.into_iter().map(serde_json::Value::from).collect()))
184 }
185 #[cfg(feature = "bigdecimal")]
186 Value::Numeric(d) => d.map(|d| serde_json::to_value(d.to_f64().unwrap()).unwrap()),
187 #[cfg(feature = "json")]
188 Value::Json(v) => v,
189 #[cfg(feature = "uuid")]
190 Value::Uuid(u) => u.map(|u| serde_json::Value::String(u.hyphenated().to_string())),
191 #[cfg(feature = "chrono")]
192 Value::DateTime(dt) => dt.map(|dt| serde_json::Value::String(dt.to_rfc3339())),
193 #[cfg(feature = "chrono")]
194 Value::Date(date) => date.map(|date| serde_json::Value::String(format!("{date}"))),
195 #[cfg(feature = "chrono")]
196 Value::Time(time) => time.map(|time| serde_json::Value::String(format!("{time}"))),
197 };
198
199 match res {
200 Some(val) => val,
201 None => serde_json::Value::Null,
202 }
203 }
204}
205
206impl<'a> Value<'a> {
207 pub fn int32<I>(value: I) -> Self
209 where
210 I: Into<i32>,
211 {
212 Value::Int32(Some(value.into()))
213 }
214
215 pub fn int64<I>(value: I) -> Self
217 where
218 I: Into<i64>,
219 {
220 Value::Int64(Some(value.into()))
221 }
222
223 pub fn integer<I>(value: I) -> Self
225 where
226 I: Into<i32>,
227 {
228 Value::Int32(Some(value.into()))
229 }
230
231 #[cfg(feature = "bigdecimal")]
233 #[cfg_attr(feature = "docs", doc(cfg(feature = "bigdecimal")))]
234 pub const fn numeric(value: BigDecimal) -> Self {
235 Value::Numeric(Some(value))
236 }
237
238 pub const fn float(value: f32) -> Self {
240 Self::Float(Some(value))
241 }
242
243 pub const fn double(value: f64) -> Self {
245 Self::Double(Some(value))
246 }
247
248 pub fn text<T>(value: T) -> Self
250 where
251 T: Into<Cow<'a, str>>,
252 {
253 Value::Text(Some(value.into()))
254 }
255
256 pub fn enum_variant<T>(value: T) -> Self
258 where
259 T: Into<Cow<'a, str>>,
260 {
261 Value::Enum(Some(value.into()))
262 }
263
264 pub fn bytes<B>(value: B) -> Self
266 where
267 B: Into<Cow<'a, [u8]>>,
268 {
269 Value::Bytes(Some(value.into()))
270 }
271
272 pub fn boolean<B>(value: B) -> Self
274 where
275 B: Into<bool>,
276 {
277 Value::Boolean(Some(value.into()))
278 }
279
280 pub fn character<C>(value: C) -> Self
282 where
283 C: Into<char>,
284 {
285 Value::Char(Some(value.into()))
286 }
287
288 pub fn array<I, V>(value: I) -> Self
290 where
291 I: IntoIterator<Item = V>,
292 V: Into<Value<'a>>,
293 {
294 Value::Array(Some(value.into_iter().map(|v| v.into()).collect()))
295 }
296
297 #[cfg(feature = "uuid")]
299 #[cfg_attr(feature = "docs", doc(cfg(feature = "uuid")))]
300 pub const fn uuid(value: Uuid) -> Self {
301 Value::Uuid(Some(value))
302 }
303
304 #[cfg(feature = "chrono")]
306 #[cfg_attr(feature = "docs", doc(cfg(feature = "chrono")))]
307 pub const fn datetime(value: DateTime<Utc>) -> Self {
308 Value::DateTime(Some(value))
309 }
310
311 #[cfg(feature = "chrono")]
313 #[cfg_attr(feature = "docs", doc(cfg(feature = "chrono")))]
314 pub const fn date(value: NaiveDate) -> Self {
315 Value::Date(Some(value))
316 }
317
318 #[cfg(feature = "chrono")]
320 #[cfg_attr(feature = "docs", doc(cfg(feature = "chrono")))]
321 pub const fn time(value: NaiveTime) -> Self {
322 Value::Time(Some(value))
323 }
324
325 #[cfg(feature = "json")]
327 #[cfg_attr(feature = "docs", doc(cfg(feature = "json")))]
328 pub const fn json(value: serde_json::Value) -> Self {
329 Value::Json(Some(value))
330 }
331
332 pub fn xml<T>(value: T) -> Self
334 where
335 T: Into<Cow<'a, str>>,
336 {
337 Value::Xml(Some(value.into()))
338 }
339
340 pub const fn is_null(&self) -> bool {
342 match self {
343 Value::Int32(i) => i.is_none(),
344 Value::Int64(i) => i.is_none(),
345 Value::Float(i) => i.is_none(),
346 Value::Double(i) => i.is_none(),
347 Value::Text(t) => t.is_none(),
348 Value::Enum(e) => e.is_none(),
349 Value::Bytes(b) => b.is_none(),
350 Value::Boolean(b) => b.is_none(),
351 Value::Char(c) => c.is_none(),
352 Value::Array(v) => v.is_none(),
353 Value::Xml(s) => s.is_none(),
354 #[cfg(feature = "bigdecimal")]
355 Value::Numeric(r) => r.is_none(),
356 #[cfg(feature = "uuid")]
357 Value::Uuid(u) => u.is_none(),
358 #[cfg(feature = "chrono")]
359 Value::DateTime(dt) => dt.is_none(),
360 #[cfg(feature = "chrono")]
361 Value::Date(d) => d.is_none(),
362 #[cfg(feature = "chrono")]
363 Value::Time(t) => t.is_none(),
364 #[cfg(feature = "json")]
365 Value::Json(json) => json.is_none(),
366 }
367 }
368
369 pub const fn is_text(&self) -> bool {
371 matches!(self, Value::Text(_))
372 }
373
374 pub fn as_str(&self) -> Option<&str> {
376 match self {
377 Value::Text(Some(cow)) => Some(cow.borrow()),
378 Value::Bytes(Some(cow)) => std::str::from_utf8(cow.as_ref()).ok(),
379 _ => None,
380 }
381 }
382
383 pub const fn as_char(&self) -> Option<char> {
385 match self {
386 Value::Char(c) => *c,
387 _ => None,
388 }
389 }
390
391 pub fn to_string(&self) -> Option<String> {
393 match self {
394 Value::Text(Some(cow)) => Some(cow.to_string()),
395 Value::Bytes(Some(cow)) => std::str::from_utf8(cow.as_ref()).map(|s| s.to_owned()).ok(),
396 _ => None,
397 }
398 }
399
400 pub fn into_string(self) -> Option<String> {
403 match self {
404 Value::Text(Some(cow)) => Some(cow.into_owned()),
405 Value::Bytes(Some(cow)) => String::from_utf8(cow.into_owned()).ok(),
406 _ => None,
407 }
408 }
409
410 pub const fn is_bytes(&self) -> bool {
412 matches!(self, Value::Bytes(_))
413 }
414
415 pub fn as_bytes(&self) -> Option<&[u8]> {
417 match self {
418 Value::Text(Some(cow)) => Some(cow.as_ref().as_bytes()),
419 Value::Bytes(Some(cow)) => Some(cow.as_ref()),
420 _ => None,
421 }
422 }
423
424 pub fn to_bytes(&self) -> Option<Vec<u8>> {
426 match self {
427 Value::Text(Some(cow)) => Some(cow.to_string().into_bytes()),
428 Value::Bytes(Some(cow)) => Some(cow.to_vec()),
429 _ => None,
430 }
431 }
432
433 pub const fn is_i32(&self) -> bool {
435 matches!(self, Value::Int32(_))
436 }
437
438 pub const fn is_i64(&self) -> bool {
440 matches!(self, Value::Int64(_))
441 }
442
443 pub const fn is_integer(&self) -> bool {
445 matches!(self, Value::Int32(_) | Value::Int64(_))
446 }
447
448 pub const fn as_i64(&self) -> Option<i64> {
450 match self {
451 Value::Int64(i) => *i,
452 _ => None,
453 }
454 }
455
456 pub const fn as_i32(&self) -> Option<i32> {
458 match self {
459 Value::Int32(i) => *i,
460 _ => None,
461 }
462 }
463
464 pub fn as_integer(&self) -> Option<i64> {
466 match self {
467 Value::Int32(i) => i.map(|i| i as i64),
468 Value::Int64(i) => *i,
469 _ => None,
470 }
471 }
472
473 pub const fn as_f64(&self) -> Option<f64> {
475 match self {
476 Value::Double(Some(f)) => Some(*f),
477 _ => None,
478 }
479 }
480
481 pub const fn as_f32(&self) -> Option<f32> {
483 match self {
484 Value::Float(Some(f)) => Some(*f),
485 _ => None,
486 }
487 }
488
489 #[cfg(feature = "bigdecimal")]
491 #[cfg_attr(feature = "docs", doc(cfg(feature = "bigdecimal")))]
492 pub const fn is_numeric(&self) -> bool {
493 matches!(self, Value::Numeric(_) | Value::Float(_) | Value::Double(_))
494 }
495
496 #[cfg(feature = "bigdecimal")]
499 #[cfg_attr(feature = "docs", doc(cfg(feature = "bigdecimal")))]
500 pub fn into_numeric(self) -> Option<BigDecimal> {
501 match self {
502 Value::Numeric(d) => d,
503 Value::Float(f) => f.and_then(BigDecimal::from_f32),
504 Value::Double(f) => f.and_then(BigDecimal::from_f64),
505 _ => None,
506 }
507 }
508
509 #[cfg(feature = "bigdecimal")]
512 #[cfg_attr(feature = "docs", doc(cfg(feature = "bigdecimal")))]
513 pub const fn as_numeric(&self) -> Option<&BigDecimal> {
514 match self {
515 Value::Numeric(d) => d.as_ref(),
516 _ => None,
517 }
518 }
519
520 pub const fn is_bool(&self) -> bool {
522 match self {
523 Value::Boolean(_) => true,
524 Value::Int32(Some(i)) if *i == 0 || *i == 1 => true,
526 Value::Int64(Some(i)) if *i == 0 || *i == 1 => true,
527 _ => false,
528 }
529 }
530
531 pub const fn as_bool(&self) -> Option<bool> {
533 match self {
534 Value::Boolean(b) => *b,
535 Value::Int32(Some(i)) if *i == 0 || *i == 1 => Some(*i == 1),
537 Value::Int64(Some(i)) if *i == 0 || *i == 1 => Some(*i == 1),
538 _ => None,
539 }
540 }
541
542 pub const fn is_array(&self) -> bool {
544 matches!(self, Value::Array(_))
545 }
546
547 #[cfg(feature = "uuid")]
549 #[cfg_attr(feature = "docs", doc(cfg(feature = "uuid")))]
550 pub const fn is_uuid(&self) -> bool {
551 matches!(self, Value::Uuid(_))
552 }
553
554 #[cfg(feature = "uuid")]
556 #[cfg_attr(feature = "docs", doc(cfg(feature = "uuid")))]
557 pub const fn as_uuid(&self) -> Option<Uuid> {
558 match self {
559 Value::Uuid(u) => *u,
560 _ => None,
561 }
562 }
563
564 #[cfg(feature = "chrono")]
566 #[cfg_attr(feature = "docs", doc(cfg(feature = "chrono")))]
567 pub const fn is_datetime(&self) -> bool {
568 matches!(self, Value::DateTime(_))
569 }
570
571 #[cfg(feature = "chrono")]
573 #[cfg_attr(feature = "docs", doc(cfg(feature = "chrono")))]
574 pub const fn as_datetime(&self) -> Option<DateTime<Utc>> {
575 match self {
576 Value::DateTime(dt) => *dt,
577 _ => None,
578 }
579 }
580
581 #[cfg(feature = "chrono")]
583 #[cfg_attr(feature = "docs", doc(cfg(feature = "chrono")))]
584 pub const fn is_date(&self) -> bool {
585 matches!(self, Value::Date(_))
586 }
587
588 #[cfg(feature = "chrono")]
590 #[cfg_attr(feature = "docs", doc(cfg(feature = "chrono")))]
591 pub const fn as_date(&self) -> Option<NaiveDate> {
592 match self {
593 Value::Date(dt) => *dt,
594 _ => None,
595 }
596 }
597
598 #[cfg(feature = "chrono")]
600 #[cfg_attr(feature = "docs", doc(cfg(feature = "chrono")))]
601 pub const fn is_time(&self) -> bool {
602 matches!(self, Value::Time(_))
603 }
604
605 #[cfg(feature = "chrono")]
607 #[cfg_attr(feature = "docs", doc(cfg(feature = "chrono")))]
608 pub const fn as_time(&self) -> Option<NaiveTime> {
609 match self {
610 Value::Time(time) => *time,
611 _ => None,
612 }
613 }
614
615 #[cfg(feature = "json")]
617 #[cfg_attr(feature = "docs", doc(cfg(feature = "json")))]
618 pub const fn is_json(&self) -> bool {
619 matches!(self, Value::Json(_))
620 }
621
622 #[cfg(feature = "json")]
624 #[cfg_attr(feature = "docs", doc(cfg(feature = "json")))]
625 pub const fn as_json(&self) -> Option<&serde_json::Value> {
626 match self {
627 Value::Json(Some(j)) => Some(j),
628 _ => None,
629 }
630 }
631
632 #[cfg(feature = "json")]
634 #[cfg_attr(feature = "docs", doc(cfg(feature = "json")))]
635 pub fn into_json(self) -> Option<serde_json::Value> {
636 match self {
637 Value::Json(Some(j)) => Some(j),
638 _ => None,
639 }
640 }
641
642 pub fn into_vec<T>(self) -> Option<Vec<T>>
644 where
645 T: TryFrom<Value<'a>>,
647 {
648 match self {
649 Value::Array(Some(vec)) => {
650 let rslt: Result<Vec<_>, _> = vec.into_iter().map(T::try_from).collect();
651 match rslt {
652 Err(_) => None,
653 Ok(values) => Some(values),
654 }
655 }
656 _ => None,
657 }
658 }
659
660 pub fn to_vec<T>(&self) -> Option<Vec<T>>
662 where
663 T: TryFrom<Value<'a>>,
664 {
665 match self {
666 Value::Array(Some(vec)) => {
667 let rslt: Result<Vec<_>, _> = vec.clone().into_iter().map(T::try_from).collect();
668 match rslt {
669 Err(_) => None,
670 Ok(values) => Some(values),
671 }
672 }
673 _ => None,
674 }
675 }
676}
677
678value!(val: i64, Int64, val);
679value!(val: i32, Int32, val);
680value!(val: bool, Boolean, val);
681value!(val: &'a str, Text, val.into());
682value!(val: String, Text, val.into());
683value!(val: usize, Int64, i64::try_from(val).unwrap());
684value!(val: &'a [u8], Bytes, val.into());
685value!(val: f64, Double, val);
686value!(val: f32, Float, val);
687
688#[cfg(feature = "chrono")]
689value!(val: DateTime<Utc>, DateTime, val);
690#[cfg(feature = "chrono")]
691value!(val: chrono::NaiveTime, Time, val);
692#[cfg(feature = "chrono")]
693value!(val: chrono::NaiveDate, Date, val);
694#[cfg(feature = "bigdecimal")]
695value!(val: BigDecimal, Numeric, val);
696#[cfg(feature = "json")]
697value!(val: JsonValue, Json, val);
698#[cfg(feature = "uuid")]
699value!(val: Uuid, Uuid, val);
700
701impl<'a> TryFrom<Value<'a>> for i64 {
702 type Error = Error;
703
704 fn try_from(value: Value<'a>) -> Result<i64, Self::Error> {
705 value.as_i64().ok_or_else(|| Error::builder(ErrorKind::conversion("Not an i64")).build())
706 }
707}
708
709impl<'a> TryFrom<Value<'a>> for i32 {
710 type Error = Error;
711
712 fn try_from(value: Value<'a>) -> Result<i32, Self::Error> {
713 value.as_i32().ok_or_else(|| Error::builder(ErrorKind::conversion("Not an i32")).build())
714 }
715}
716
717#[cfg(feature = "bigdecimal")]
718impl<'a> TryFrom<Value<'a>> for BigDecimal {
719 type Error = Error;
720
721 fn try_from(value: Value<'a>) -> Result<BigDecimal, Self::Error> {
722 value.into_numeric().ok_or_else(|| Error::builder(ErrorKind::conversion("Not a decimal")).build())
723 }
724}
725
726impl<'a> TryFrom<Value<'a>> for f64 {
727 type Error = Error;
728
729 fn try_from(value: Value<'a>) -> Result<f64, Self::Error> {
730 value.as_f64().ok_or_else(|| Error::builder(ErrorKind::conversion("Not a f64")).build())
731 }
732}
733
734impl<'a> TryFrom<Value<'a>> for String {
735 type Error = Error;
736
737 fn try_from(value: Value<'a>) -> Result<String, Self::Error> {
738 value.into_string().ok_or_else(|| Error::builder(ErrorKind::conversion("Not a string")).build())
739 }
740}
741
742impl<'a> TryFrom<Value<'a>> for bool {
743 type Error = Error;
744
745 fn try_from(value: Value<'a>) -> Result<bool, Self::Error> {
746 value.as_bool().ok_or_else(|| Error::builder(ErrorKind::conversion("Not a bool")).build())
747 }
748}
749
750#[cfg(feature = "chrono")]
751#[cfg_attr(feature = "docs", doc(cfg(feature = "chrono")))]
752impl<'a> TryFrom<Value<'a>> for DateTime<Utc> {
753 type Error = Error;
754
755 fn try_from(value: Value<'a>) -> Result<DateTime<Utc>, Self::Error> {
756 value.as_datetime().ok_or_else(|| Error::builder(ErrorKind::conversion("Not a datetime")).build())
757 }
758}
759
760impl<'a> TryFrom<&Value<'a>> for Option<std::net::IpAddr> {
761 type Error = Error;
762
763 fn try_from(value: &Value<'a>) -> Result<Option<std::net::IpAddr>, Self::Error> {
764 match value {
765 val @ Value::Text(Some(_)) => {
766 let text = val.as_str().unwrap();
767
768 match std::net::IpAddr::from_str(text) {
769 Ok(ip) => Ok(Some(ip)),
770 Err(e) => Err(e.into()),
771 }
772 }
773 val @ Value::Bytes(Some(_)) => {
774 let text = val.as_str().unwrap();
775
776 match std::net::IpAddr::from_str(text) {
777 Ok(ip) => Ok(Some(ip)),
778 Err(e) => Err(e.into()),
779 }
780 }
781 v if v.is_null() => Ok(None),
782 v => {
783 let kind =
784 ErrorKind::conversion(format!("Couldn't convert value of type `{v:?}` to std::net::IpAddr."));
785
786 Err(Error::builder(kind).build())
787 }
788 }
789 }
790}
791
792#[cfg(feature = "uuid")]
793impl<'a> TryFrom<&Value<'a>> for Option<uuid::Uuid> {
794 type Error = Error;
795
796 fn try_from(value: &Value<'a>) -> Result<Option<uuid::Uuid>, Self::Error> {
797 match value {
798 Value::Uuid(uuid) => Ok(*uuid),
799 val @ Value::Text(Some(_)) => {
800 let text = val.as_str().unwrap();
801
802 match uuid::Uuid::from_str(text) {
803 Ok(ip) => Ok(Some(ip)),
804 Err(e) => Err(e.into()),
805 }
806 }
807 val @ Value::Bytes(Some(_)) => {
808 let text = val.as_str().unwrap();
809
810 match uuid::Uuid::from_str(text) {
811 Ok(ip) => Ok(Some(ip)),
812 Err(e) => Err(e.into()),
813 }
814 }
815 v if v.is_null() => Ok(None),
816 v => {
817 let kind = ErrorKind::conversion(format!("Couldn't convert value of type `{v:?}` to uuid::Uuid."));
818
819 Err(Error::builder(kind).build())
820 }
821 }
822 }
823}
824
825#[derive(Debug, Clone, Default, PartialEq)]
828pub struct Values<'a> {
829 pub(crate) rows: Vec<Row<'a>>,
830}
831
832impl<'a> Values<'a> {
833 pub fn empty() -> Self {
835 Self { rows: Vec::new() }
836 }
837
838 pub fn new(rows: Vec<Row<'a>>) -> Self {
840 Self { rows }
841 }
842
843 pub fn with_capacity(capacity: usize) -> Self {
845 Self { rows: Vec::with_capacity(capacity) }
846 }
847
848 pub fn push<T>(&mut self, row: T)
850 where
851 T: Into<Row<'a>>,
852 {
853 self.rows.push(row.into());
854 }
855
856 pub fn len(&self) -> usize {
858 self.rows.len()
859 }
860
861 pub fn is_empty(&self) -> bool {
863 self.len() == 0
864 }
865
866 pub fn row_len(&self) -> usize {
867 match self.rows.split_first() {
868 Some((row, _)) => row.len(),
869 None => 0,
870 }
871 }
872
873 pub fn flatten_row(self) -> Option<Row<'a>> {
874 let mut result = Row::with_capacity(self.len());
875
876 for mut row in self.rows.into_iter() {
877 match row.pop() {
878 Some(value) => result.push(value),
879 None => return None,
880 }
881 }
882
883 Some(result)
884 }
885}
886
887impl<'a, I, R> From<I> for Values<'a>
888where
889 I: Iterator<Item = R>,
890 R: Into<Row<'a>>,
891{
892 fn from(rows: I) -> Self {
893 Self { rows: rows.map(|r| r.into()).collect() }
894 }
895}
896
897impl<'a> IntoIterator for Values<'a> {
898 type Item = Row<'a>;
899 type IntoIter = std::vec::IntoIter<Self::Item>;
900
901 fn into_iter(self) -> Self::IntoIter {
902 self.rows.into_iter()
903 }
904}
905
906#[cfg(test)]
907mod tests {
908 use super::*;
909 #[cfg(feature = "chrono")]
910 use std::str::FromStr;
911
912 #[test]
913 fn a_parameterized_value_of_ints32_can_be_converted_into_a_vec() {
914 let pv = Value::array(vec![1]);
915 let values: Vec<i32> = pv.into_vec().expect("convert into Vec<i32>");
916 assert_eq!(values, vec![1]);
917 }
918
919 #[test]
920 fn a_parameterized_value_of_ints64_can_be_converted_into_a_vec() {
921 let pv = Value::array(vec![1_i64]);
922 let values: Vec<i64> = pv.into_vec().expect("convert into Vec<i64>");
923 assert_eq!(values, vec![1]);
924 }
925
926 #[test]
927 fn a_parameterized_value_of_reals_can_be_converted_into_a_vec() {
928 let pv = Value::array(vec![1.0]);
929 let values: Vec<f64> = pv.into_vec().expect("convert into Vec<f64>");
930 assert_eq!(values, vec![1.0]);
931 }
932
933 #[test]
934 fn a_parameterized_value_of_texts_can_be_converted_into_a_vec() {
935 let pv = Value::array(vec!["test"]);
936 let values: Vec<String> = pv.into_vec().expect("convert into Vec<String>");
937 assert_eq!(values, vec!["test"]);
938 }
939
940 #[test]
941 fn a_parameterized_value_of_booleans_can_be_converted_into_a_vec() {
942 let pv = Value::array(vec![true]);
943 let values: Vec<bool> = pv.into_vec().expect("convert into Vec<bool>");
944 assert_eq!(values, vec![true]);
945 }
946
947 #[test]
948 #[cfg(feature = "chrono")]
949 fn a_parameterized_value_of_datetimes_can_be_converted_into_a_vec() {
950 let datetime = DateTime::from_str("2019-07-27T05:30:30Z").expect("parsing date/time");
951 let pv = Value::array(vec![datetime]);
952 let values: Vec<DateTime<Utc>> = pv.into_vec().expect("convert into Vec<DateTime>");
953 assert_eq!(values, vec![datetime]);
954 }
955
956 #[test]
957 fn a_parameterized_value_of_an_array_cant_be_converted_into_a_vec_of_the_wrong_type() {
958 let pv = Value::array(vec![1]);
959 let rslt: Option<Vec<f64>> = pv.into_vec();
960 assert!(rslt.is_none());
961 }
962
963 #[test]
964 #[cfg(feature = "chrono")]
965 fn display_format_for_datetime() {
966 let dt: DateTime<Utc> = DateTime::from_str("2019-07-27T05:30:30Z").expect("failed while parsing date");
967 let pv = Value::datetime(dt);
968
969 assert_eq!(format!("{pv}"), "\"2019-07-27 05:30:30 UTC\"");
970 }
971
972 #[test]
973 #[cfg(feature = "chrono")]
974 fn display_format_for_date() {
975 let date = NaiveDate::from_ymd_opt(2022, 8, 11).unwrap();
976 let pv = Value::date(date);
977
978 assert_eq!(format!("{pv}"), "\"2022-08-11\"");
979 }
980
981 #[test]
982 #[cfg(feature = "chrono")]
983 fn display_format_for_time() {
984 let time = NaiveTime::from_hms_opt(16, 17, 00).unwrap();
985 let pv = Value::time(time);
986
987 assert_eq!(format!("{pv}"), "\"16:17:00\"");
988 }
989
990 #[test]
991 #[cfg(feature = "uuid")]
992 fn display_format_for_uuid() {
993 let id = Uuid::from_str("67e5504410b1426f9247bb680e5fe0c8").unwrap();
994 let pv = Value::uuid(id);
995
996 assert_eq!(format!("{pv}"), "\"67e55044-10b1-426f-9247-bb680e5fe0c8\"");
997 }
998}