1pub use crate::types::{Type, TypeCode};
16use crate::value::Kind;
17use crate::value::Value;
18use base64::Engine;
19use base64::prelude::BASE64_STANDARD;
20use rust_decimal::Decimal;
21use std::time::SystemTime;
22use time::{Date, OffsetDateTime};
23
24#[derive(thiserror::Error, Debug)]
26#[non_exhaustive]
27pub enum ConvertError {
28 #[error("expected {want:?}, got {got:?}")]
30 KindMismatch {
31 want: Kind,
33 got: Kind,
35 },
36
37 #[error("expected non-null value, got null")]
39 NotNull,
40
41 #[error("cannot convert value, source={0}")]
43 Convert(#[source] BoxedError),
44}
45
46type BoxedError = Box<dyn std::error::Error + Send + Sync>;
47
48pub trait FromValue: Sized {
53 fn from_value(value: &Value, type_: &Type) -> Result<Self, ConvertError>;
62}
63
64impl<T> FromValue for Option<T>
65where
66 T: FromValue,
67{
68 fn from_value(value: &Value, type_: &Type) -> Result<Self, ConvertError> {
69 match &value.0.kind {
70 Some(prost_types::value::Kind::NullValue(_)) => Ok(None),
71 _ => T::from_value(value, type_).map(Some),
72 }
73 }
74}
75
76impl FromValue for Value {
77 fn from_value(value: &Value, _type: &Type) -> Result<Self, ConvertError> {
78 Ok(value.clone())
79 }
80}
81
82impl FromValue for String {
83 fn from_value(value: &Value, _type: &Type) -> Result<Self, ConvertError> {
84 match &value.0.kind {
85 Some(prost_types::value::Kind::StringValue(s)) => Ok(s.clone()),
86 Some(prost_types::value::Kind::NullValue(_)) => Err(ConvertError::NotNull),
87 _ => Err(ConvertError::KindMismatch {
88 want: crate::value::Kind::String,
89 got: value.kind(),
90 }),
91 }
92 }
93}
94
95impl FromValue for i64 {
96 fn from_value(value: &Value, _type: &Type) -> Result<Self, ConvertError> {
97 match &value.0.kind {
98 Some(prost_types::value::Kind::StringValue(s)) => {
99 s.parse().map_err(|e| ConvertError::Convert(Box::new(e)))
100 }
101 Some(prost_types::value::Kind::NullValue(_)) => Err(ConvertError::NotNull),
102 _ => Err(ConvertError::KindMismatch {
103 want: crate::value::Kind::String,
104 got: value.kind(),
105 }),
106 }
107 }
108}
109
110impl FromValue for i32 {
111 fn from_value(value: &Value, _type: &Type) -> Result<Self, ConvertError> {
112 match &value.0.kind {
113 Some(prost_types::value::Kind::StringValue(s)) => {
114 s.parse().map_err(|e| ConvertError::Convert(Box::new(e)))
115 }
116 Some(prost_types::value::Kind::NullValue(_)) => Err(ConvertError::NotNull),
117 _ => Err(ConvertError::KindMismatch {
118 want: crate::value::Kind::String,
119 got: value.kind(),
120 }),
121 }
122 }
123}
124
125impl FromValue for Decimal {
126 fn from_value(value: &Value, type_: &Type) -> Result<Self, ConvertError> {
127 if type_.code() != TypeCode::Numeric {
128 return Err(ConvertError::KindMismatch {
129 want: crate::value::Kind::String,
130 got: value.kind(),
131 });
132 }
133 match &value.0.kind {
134 Some(prost_types::value::Kind::StringValue(s)) => {
135 Decimal::from_str_exact(s).map_err(|e| ConvertError::Convert(Box::new(e)))
136 }
137 Some(prost_types::value::Kind::NullValue(_)) => Err(ConvertError::NotNull),
138 _ => Err(ConvertError::KindMismatch {
139 want: crate::value::Kind::String,
140 got: value.kind(),
141 }),
142 }
143 }
144}
145
146impl FromValue for SystemTime {
147 fn from_value(value: &Value, type_: &Type) -> Result<Self, ConvertError> {
148 if type_.code() != TypeCode::Timestamp {
149 return Err(ConvertError::KindMismatch {
150 want: crate::value::Kind::String,
151 got: value.kind(),
152 });
153 }
154 match &value.0.kind {
155 Some(prost_types::value::Kind::StringValue(s)) => {
156 let dt = OffsetDateTime::parse(s, &time::format_description::well_known::Rfc3339)
157 .map_err(|e| ConvertError::Convert(Box::new(e)))?;
158 Ok(dt.into())
159 }
160 Some(prost_types::value::Kind::NullValue(_)) => Err(ConvertError::NotNull),
161 _ => Err(ConvertError::KindMismatch {
162 want: crate::value::Kind::String,
163 got: value.kind(),
164 }),
165 }
166 }
167}
168
169impl FromValue for OffsetDateTime {
170 fn from_value(value: &Value, type_: &Type) -> Result<Self, ConvertError> {
171 if type_.code() != TypeCode::Timestamp {
172 return Err(ConvertError::KindMismatch {
173 want: crate::value::Kind::String,
174 got: value.kind(),
175 });
176 }
177 match &value.0.kind {
178 Some(prost_types::value::Kind::StringValue(s)) => {
179 let dt = OffsetDateTime::parse(s, &time::format_description::well_known::Rfc3339)
180 .map_err(|e| ConvertError::Convert(Box::new(e)))?;
181 Ok(dt)
182 }
183 Some(prost_types::value::Kind::NullValue(_)) => Err(ConvertError::NotNull),
184 _ => Err(ConvertError::KindMismatch {
185 want: crate::value::Kind::String,
186 got: value.kind(),
187 }),
188 }
189 }
190}
191
192impl FromValue for wkt::Timestamp {
193 fn from_value(value: &Value, type_: &Type) -> Result<Self, ConvertError> {
194 let dt = OffsetDateTime::from_value(value, type_)?;
195 wkt::Timestamp::try_from(dt).map_err(|e| ConvertError::Convert(Box::new(e)))
196 }
197}
198
199impl FromValue for Date {
200 fn from_value(value: &Value, type_: &Type) -> Result<Self, ConvertError> {
201 if type_.code() != TypeCode::Date {
202 return Err(ConvertError::KindMismatch {
203 want: crate::value::Kind::String,
204 got: value.kind(),
205 });
206 }
207 match &value.0.kind {
208 Some(prost_types::value::Kind::StringValue(s)) => {
209 let date = Date::parse(s, crate::value::SPANNER_DATE_FORMAT)
210 .map_err(|e| ConvertError::Convert(Box::new(e)))?;
211 Ok(date)
212 }
213 Some(prost_types::value::Kind::NullValue(_)) => Err(ConvertError::NotNull),
214 _ => Err(ConvertError::KindMismatch {
215 want: crate::value::Kind::String,
216 got: value.kind(),
217 }),
218 }
219 }
220}
221
222impl FromValue for bool {
223 fn from_value(value: &Value, _type: &Type) -> Result<Self, ConvertError> {
224 match &value.0.kind {
225 Some(prost_types::value::Kind::BoolValue(b)) => Ok(*b),
226 Some(prost_types::value::Kind::NullValue(_)) => Err(ConvertError::NotNull),
227 _ => Err(ConvertError::KindMismatch {
228 want: crate::value::Kind::Bool,
229 got: value.kind(),
230 }),
231 }
232 }
233}
234
235impl FromValue for f64 {
236 fn from_value(value: &Value, _type: &Type) -> Result<Self, ConvertError> {
237 match &value.0.kind {
238 Some(prost_types::value::Kind::NumberValue(n)) => Ok(*n),
239 Some(prost_types::value::Kind::StringValue(s)) => {
240 s.parse().map_err(|e| ConvertError::Convert(Box::new(e)))
241 }
242 Some(prost_types::value::Kind::NullValue(_)) => Err(ConvertError::NotNull),
243 _ => Err(ConvertError::KindMismatch {
244 want: crate::value::Kind::Number,
245 got: value.kind(),
246 }),
247 }
248 }
249}
250
251impl FromValue for f32 {
252 fn from_value(value: &Value, _type: &Type) -> Result<Self, ConvertError> {
253 match &value.0.kind {
254 Some(prost_types::value::Kind::NumberValue(n)) => Ok(*n as f32),
255 Some(prost_types::value::Kind::StringValue(s)) => {
256 s.parse().map_err(|e| ConvertError::Convert(Box::new(e)))
257 }
258 Some(prost_types::value::Kind::NullValue(_)) => Err(ConvertError::NotNull),
259 _ => Err(ConvertError::KindMismatch {
260 want: crate::value::Kind::Number,
261 got: value.kind(),
262 }),
263 }
264 }
265}
266
267impl FromValue for Vec<u8> {
268 fn from_value(value: &Value, type_: &Type) -> Result<Self, ConvertError> {
269 if type_.code() != TypeCode::Bytes && type_.code() != TypeCode::Proto {
270 return Err(ConvertError::KindMismatch {
271 want: crate::value::Kind::String,
272 got: value.kind(),
273 });
274 }
275 match &value.0.kind {
276 Some(prost_types::value::Kind::StringValue(s)) => BASE64_STANDARD
277 .decode(s)
278 .map_err(|e| ConvertError::Convert(Box::new(e))),
279 Some(prost_types::value::Kind::NullValue(_)) => Err(ConvertError::NotNull),
280 _ => Err(ConvertError::KindMismatch {
281 want: crate::value::Kind::String,
282 got: value.kind(),
283 }),
284 }
285 }
286}
287
288impl<T> FromValue for Vec<T>
289where
290 T: FromValue,
291{
292 fn from_value(value: &Value, r#type: &Type) -> Result<Self, ConvertError> {
293 if r#type.code() != TypeCode::Array {
294 return Err(ConvertError::KindMismatch {
295 want: crate::value::Kind::List,
296 got: value.kind(),
297 });
298 }
299 let element_type = r#type
300 .array_element_type()
301 .ok_or_else(|| ConvertError::Convert("Array type missing element type".into()))?;
302
303 match &value.0.kind {
304 Some(prost_types::value::Kind::ListValue(list)) => {
305 let mut vec = Vec::with_capacity(list.values.len());
306 for v in &list.values {
307 let val = crate::value::Value::from_ref(v);
310 vec.push(T::from_value(val, &element_type)?);
311 }
312 Ok(vec)
313 }
314 Some(prost_types::value::Kind::NullValue(_)) => Err(ConvertError::NotNull),
315 _ => Err(ConvertError::KindMismatch {
316 want: crate::value::Kind::List,
317 got: value.kind(),
318 }),
319 }
320 }
321}
322
323#[cfg(test)]
324mod tests {
325 use super::*;
326 use crate::to_value::ToValue;
327 use crate::types;
328
329 #[test]
330 fn test_from_value_string() {
331 let v = "hello".to_value();
332 let s = String::from_value(&v, &types::string()).unwrap();
333 assert_eq!(s, "hello");
334 }
335
336 #[test]
337 fn test_from_value_int() {
338 let v = 42i64.to_value();
339 let i = i64::from_value(&v, &types::int64()).unwrap();
340 assert_eq!(i, 42);
341
342 let v = 42i32.to_value();
343 let i = i32::from_value(&v, &types::int64()).unwrap();
344 assert_eq!(i, 42);
345
346 let v = "not an int".to_value();
348 let err = i64::from_value(&v, &types::int64()).unwrap_err();
349 assert!(format!("{}", err).contains("cannot convert value"));
350
351 let v = "not an int".to_value();
352 let err = i32::from_value(&v, &types::int64()).unwrap_err();
353 assert!(format!("{}", err).contains("cannot convert value"));
354 }
355
356 #[test]
357 fn test_from_value_float() {
358 let v = 42.5f64.to_value();
359 let f = f64::from_value(&v, &types::float64()).unwrap();
360 assert_eq!(f, 42.5);
361
362 let v = "Infinity".to_string().to_value();
363 let f = f64::from_value(&v, &types::float64()).unwrap();
364 assert_eq!(f, f64::INFINITY);
365
366 let v = "invalid float".to_string().to_value();
367 let err = f64::from_value(&v, &types::float64()).unwrap_err();
368 assert!(format!("{}", err).contains("invalid float literal"));
369 }
370
371 #[test]
372 fn test_from_value_bool() {
373 let v = true.to_value();
374 let b = bool::from_value(&v, &types::bool()).unwrap();
375 assert!(b);
376 }
377
378 #[test]
379 fn test_from_value_array() {
380 let str_array = vec!["one".to_string(), "two".to_string()];
382 let v = str_array.to_value();
383 let res = Vec::<String>::from_value(&v, &types::array(types::string()))
384 .expect("parsed string array");
385 assert_eq!(res, str_array);
386
387 let int_array = vec![42i64, 100i64];
389 let v = int_array.to_value();
390 let res =
391 Vec::<i64>::from_value(&v, &types::array(types::int64())).expect("parsed int array");
392 assert_eq!(res, int_array);
393
394 let bool_array = vec![true, false];
396 let v = bool_array.to_value();
397 let res =
398 Vec::<bool>::from_value(&v, &types::array(types::bool())).expect("parsed bool array");
399 assert_eq!(res, bool_array);
400
401 let float_array = vec![9.9f64, -2.5f64];
403 let v = float_array.to_value();
404 let res = Vec::<f64>::from_value(&v, &types::array(types::float64()))
405 .expect("parsed float array");
406 assert_eq!(res, float_array);
407
408 let empty_array: Vec<f64> = vec![];
410 let v = empty_array.to_value();
411 let res = Vec::<f64>::from_value(&v, &types::array(types::float64()))
412 .expect("parsed empty array");
413 assert_eq!(res, empty_array);
414
415 let opt_array: Vec<Option<i64>> = vec![Some(42), None, Some(100)];
417 let v = opt_array.to_value();
418 let res = Vec::<Option<i64>>::from_value(&v, &types::array(types::int64()))
419 .expect("parsed optional array");
420 assert_eq!(res, opt_array);
421
422 let null_array: Option<Vec<i64>> = None;
424 let v = null_array.to_value();
425 let res = Option::<Vec<i64>>::from_value(&v, &types::array(types::int64()))
426 .expect("parsed null array");
427 assert_eq!(res, null_array);
428
429 let err = Vec::<i64>::from_value(&int_array.to_value(), &types::int64()).unwrap_err();
431 assert!(format!("{}", err).contains("expected List"));
432
433 let err = Vec::<i64>::from_value(&str_array.to_value(), &types::array(types::int64()))
435 .unwrap_err();
436 assert!(format!("{}", err).contains("cannot convert value, source="));
437 }
438
439 #[test]
440 fn test_from_value_bytes() {
441 let bytes: Vec<u8> = vec![1, 2, 3];
442 let v = bytes.to_value();
443 let b = Vec::<u8>::from_value(&v, &types::bytes()).unwrap();
444 assert_eq!(b, bytes);
445
446 let v = "invalid base64".to_string().to_value();
447 let err = Vec::<u8>::from_value(&v, &types::bytes()).unwrap_err();
448 assert!(format!("{}", err).contains("cannot convert value"));
449 }
450
451 #[test]
452 fn test_from_value_decimal() {
453 let d = Decimal::from_str_exact("123.456").unwrap();
454 let v = d.to_value();
455 let res = Decimal::from_value(&v, &types::numeric()).unwrap();
456 assert_eq!(res, d);
457
458 let v = "invalid decimal".to_string().to_value();
459 let err = Decimal::from_value(&v, &types::numeric()).unwrap_err();
460 assert!(format!("{}", err).contains("cannot convert value"));
461 }
462
463 #[test]
464 fn test_from_value_date() {
465 let d = Date::from_calendar_date(2023, time::Month::October, 27).unwrap();
466 let v = d.to_value();
467 let res = Date::from_value(&v, &types::date()).unwrap();
468 assert_eq!(res, d);
469
470 let v = "invalid date".to_string().to_value();
471 let err = Date::from_value(&v, &types::date()).unwrap_err();
472 assert!(format!("{}", err).contains("cannot convert value"));
473 }
474
475 #[test]
476 fn test_from_value_timestamp() {
477 let dt = OffsetDateTime::parse(
478 "2023-10-27T10:00:00Z",
479 &time::format_description::well_known::Rfc3339,
480 )
481 .unwrap();
482 let v = dt.to_value();
483 let res = OffsetDateTime::from_value(&v, &types::timestamp()).unwrap();
484 assert_eq!(res, dt);
485
486 let v = "invalid timestamp".to_string().to_value();
487 let err = OffsetDateTime::from_value(&v, &types::timestamp()).unwrap_err();
488 assert!(format!("{}", err).contains("cannot convert value"));
489 }
490
491 #[test]
492 fn test_from_value_null() {
493 let v = Option::<i32>::None.to_value();
494 let res = Option::<i32>::from_value(&v, &types::int64()).unwrap();
495 assert_eq!(res, None);
496
497 let v = Option::<i32>::None.to_value();
498 let err = i32::from_value(&v, &types::int64()).unwrap_err();
499 assert!(format!("{}", err).contains("expected non-null value, got null"));
500 }
501 #[test]
502 fn test_from_value_system_time() {
503 let dt = OffsetDateTime::parse(
504 "2023-10-27T10:00:00Z",
505 &time::format_description::well_known::Rfc3339,
506 )
507 .unwrap();
508 let system_time: SystemTime = dt.into();
509 let v = system_time.to_value();
510 let res = SystemTime::from_value(&v, &types::timestamp()).unwrap();
511 let res_dt: OffsetDateTime = res.into();
512 assert_eq!(res_dt, dt);
513
514 let v = "invalid timestamp".to_string().to_value();
515 let err = SystemTime::from_value(&v, &types::timestamp()).unwrap_err();
516 assert!(format!("{}", err).contains("cannot convert value"));
517 }
518
519 #[test]
520 fn test_from_value_wkt_timestamp() {
521 let dt = OffsetDateTime::parse(
522 "2023-10-27T10:00:00Z",
523 &time::format_description::well_known::Rfc3339,
524 )
525 .expect("valid date time parsing");
526 let wkt_ts = wkt::Timestamp::try_from(dt).expect("valid wkt timestamp conversion");
527 let v = dt.to_value();
528 let res = wkt::Timestamp::from_value(&v, &types::timestamp())
529 .expect("valid wkt timestamp decoding");
530 assert_eq!(res, wkt_ts);
531
532 let v = "invalid timestamp".to_string().to_value();
533 let err = wkt::Timestamp::from_value(&v, &types::timestamp()).unwrap_err();
534 assert!(format!("{}", err).contains("cannot convert value"));
535 }
536
537 #[test]
538 fn test_from_value_type_mismatch() {
539 let v = Decimal::from(42).to_value();
540 let err = Decimal::from_value(&v, &types::int64()).unwrap_err();
541 assert!(format!("{}", err).contains("expected String, got String"));
542
543 let v = SystemTime::now().to_value();
544 let err = SystemTime::from_value(&v, &types::string()).unwrap_err();
545 assert!(format!("{}", err).contains("expected String, got String")); let v = OffsetDateTime::now_utc().to_value();
548 let err = OffsetDateTime::from_value(&v, &types::string()).unwrap_err();
549 assert!(format!("{}", err).contains("expected String, got String"));
550
551 let v = Date::from_calendar_date(2023, time::Month::October, 27)
552 .unwrap()
553 .to_value();
554 let err = Date::from_value(&v, &types::string()).unwrap_err();
555 assert!(format!("{}", err).contains("expected String, got String"));
556
557 let v = vec![1u8].to_value();
558 let err = Vec::<u8>::from_value(&v, &types::string()).unwrap_err();
559 assert!(format!("{}", err).contains("expected String, got String"));
560 }
561
562 #[test]
563 fn test_from_value_wrong_kind() {
564 let v_bool = true.to_value();
565 let err = String::from_value(&v_bool, &types::string()).unwrap_err();
566 assert!(format!("{}", err).contains("expected String, got Bool"));
567
568 let v_string = "hello".to_value();
569 let err = i64::from_value(&v_string, &types::int64()).unwrap_err();
570 assert!(format!("{}", err).contains("cannot convert value"));
571
572 let v_struct = crate::value::Value(prost_types::Value {
573 kind: Some(prost_types::value::Kind::StructValue(
574 prost_types::Struct::default(),
575 )),
576 });
577 let err = i64::from_value(&v_struct, &types::int64()).unwrap_err();
578 assert!(format!("{}", err).contains("expected String, got Struct"));
579
580 let err = f64::from_value(&v_bool, &types::float64()).unwrap_err();
581 assert!(format!("{}", err).contains("expected Number, got Bool"));
582
583 let err = bool::from_value(&v_string, &types::bool()).unwrap_err();
584 assert!(format!("{}", err).contains("expected Bool, got String"));
585 }
586
587 #[test]
588 fn test_from_value_null_errors() {
589 let v_null = Option::<i32>::None.to_value();
590
591 let err = String::from_value(&v_null, &types::string()).unwrap_err();
592 assert!(format!("{}", err).contains("expected non-null value, got null"));
593
594 let err = i64::from_value(&v_null, &types::int64()).unwrap_err();
595 assert!(format!("{}", err).contains("expected non-null value, got null"));
596
597 let err = f64::from_value(&v_null, &types::float64()).unwrap_err();
598 assert!(format!("{}", err).contains("expected non-null value, got null"));
599
600 let err = f32::from_value(&v_null, &types::float32()).unwrap_err();
601 assert!(format!("{}", err).contains("expected non-null value, got null"));
602
603 let err = bool::from_value(&v_null, &types::bool()).unwrap_err();
604 assert!(format!("{}", err).contains("expected non-null value, got null"));
605
606 let err = Decimal::from_value(&v_null, &types::numeric()).unwrap_err();
607 assert!(format!("{}", err).contains("expected non-null value, got null"));
608
609 let err = SystemTime::from_value(&v_null, &types::timestamp()).unwrap_err();
610 assert!(format!("{}", err).contains("expected non-null value, got null"));
611
612 let err = OffsetDateTime::from_value(&v_null, &types::timestamp()).unwrap_err();
613 assert!(format!("{}", err).contains("expected non-null value, got null"));
614
615 let err = Date::from_value(&v_null, &types::date()).unwrap_err();
616 assert!(format!("{}", err).contains("expected non-null value, got null"));
617
618 let err = Vec::<u8>::from_value(&v_null, &types::bytes()).unwrap_err();
619 assert!(format!("{}", err).contains("expected non-null value, got null"));
620 }
621
622 #[test]
623 fn test_from_value_option_missing_kind() {
624 let v = crate::value::Value(prost_types::Value { kind: None });
625 let err = Option::<i32>::from_value(&v, &types::int64()).unwrap_err();
626 assert!(format!("{}", err).contains("expected String, got Null"));
627 }
628}