1use std::{
5 error,
6 fmt::{self, Display, Formatter},
7};
8
9use crate::value::{
10 Value,
11 blob::Blob,
12 date::Date,
13 datetime::DateTime,
14 decimal::Decimal,
15 duration::Duration,
16 identity::IdentityId,
17 int::Int,
18 ordered_f32::OrderedF32,
19 ordered_f64::OrderedF64,
20 time::Time,
21 r#type::Type,
22 uint::Uint,
23 uuid::{Uuid4, Uuid7},
24};
25
26#[derive(Debug, Clone, PartialEq)]
28pub enum FromValueError {
29 TypeMismatch {
31 expected: Type,
32 found: Type,
33 },
34 OutOfRange {
36 value: String,
37 target_type: &'static str,
38 },
39}
40
41impl Display for FromValueError {
42 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
43 match self {
44 FromValueError::TypeMismatch {
45 expected,
46 found,
47 } => {
48 write!(f, "type mismatch: expected {:?}, found {:?}", expected, found)
49 }
50 FromValueError::OutOfRange {
51 value,
52 target_type,
53 } => {
54 write!(f, "value {} out of range for type {}", value, target_type)
55 }
56 }
57 }
58}
59
60impl error::Error for FromValueError {}
61
62pub trait TryFromValue: Sized {
70 fn try_from_value(value: &Value) -> Result<Self, FromValueError>;
75
76 fn from_value(value: &Value) -> Option<Self> {
81 match value {
82 Value::None {
83 ..
84 } => None,
85 v => Self::try_from_value(v).ok(),
86 }
87 }
88}
89
90pub trait TryFromValueCoerce: Sized {
97 fn try_from_value_coerce(value: &Value) -> Result<Self, FromValueError>;
99
100 fn from_value_coerce(value: &Value) -> Option<Self> {
102 match value {
103 Value::None {
104 ..
105 } => None,
106 v => Self::try_from_value_coerce(v).ok(),
107 }
108 }
109}
110
111impl TryFromValue for Value {
112 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
113 Ok(value.clone())
114 }
115}
116
117impl TryFromValue for bool {
118 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
119 match value {
120 Value::Boolean(v) => Ok(*v),
121 _ => Err(FromValueError::TypeMismatch {
122 expected: Type::Boolean,
123 found: value.get_type(),
124 }),
125 }
126 }
127}
128
129impl TryFromValue for i8 {
130 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
131 match value {
132 Value::Int1(v) => Ok(*v),
133 _ => Err(FromValueError::TypeMismatch {
134 expected: Type::Int1,
135 found: value.get_type(),
136 }),
137 }
138 }
139}
140
141impl TryFromValue for i16 {
142 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
143 match value {
144 Value::Int2(v) => Ok(*v),
145 _ => Err(FromValueError::TypeMismatch {
146 expected: Type::Int2,
147 found: value.get_type(),
148 }),
149 }
150 }
151}
152
153impl TryFromValue for i32 {
154 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
155 match value {
156 Value::Int4(v) => Ok(*v),
157 _ => Err(FromValueError::TypeMismatch {
158 expected: Type::Int4,
159 found: value.get_type(),
160 }),
161 }
162 }
163}
164
165impl TryFromValue for i64 {
166 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
167 match value {
168 Value::Int8(v) => Ok(*v),
169 _ => Err(FromValueError::TypeMismatch {
170 expected: Type::Int8,
171 found: value.get_type(),
172 }),
173 }
174 }
175}
176
177impl TryFromValue for i128 {
178 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
179 match value {
180 Value::Int16(v) => Ok(*v),
181 _ => Err(FromValueError::TypeMismatch {
182 expected: Type::Int16,
183 found: value.get_type(),
184 }),
185 }
186 }
187}
188
189impl TryFromValue for u8 {
190 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
191 match value {
192 Value::Uint1(v) => Ok(*v),
193 _ => Err(FromValueError::TypeMismatch {
194 expected: Type::Uint1,
195 found: value.get_type(),
196 }),
197 }
198 }
199}
200
201impl TryFromValue for u16 {
202 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
203 match value {
204 Value::Uint2(v) => Ok(*v),
205 _ => Err(FromValueError::TypeMismatch {
206 expected: Type::Uint2,
207 found: value.get_type(),
208 }),
209 }
210 }
211}
212
213impl TryFromValue for u32 {
214 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
215 match value {
216 Value::Uint4(v) => Ok(*v),
217 _ => Err(FromValueError::TypeMismatch {
218 expected: Type::Uint4,
219 found: value.get_type(),
220 }),
221 }
222 }
223}
224
225impl TryFromValue for u64 {
226 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
227 match value {
228 Value::Uint8(v) => Ok(*v),
229 _ => Err(FromValueError::TypeMismatch {
230 expected: Type::Uint8,
231 found: value.get_type(),
232 }),
233 }
234 }
235}
236
237impl TryFromValue for u128 {
238 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
239 match value {
240 Value::Uint16(v) => Ok(*v),
241 _ => Err(FromValueError::TypeMismatch {
242 expected: Type::Uint16,
243 found: value.get_type(),
244 }),
245 }
246 }
247}
248
249impl TryFromValue for f32 {
250 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
251 match value {
252 Value::Float4(v) => Ok(v.value()),
253 _ => Err(FromValueError::TypeMismatch {
254 expected: Type::Float4,
255 found: value.get_type(),
256 }),
257 }
258 }
259}
260
261impl TryFromValue for f64 {
262 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
263 match value {
264 Value::Float8(v) => Ok(v.value()),
265 _ => Err(FromValueError::TypeMismatch {
266 expected: Type::Float8,
267 found: value.get_type(),
268 }),
269 }
270 }
271}
272
273impl TryFromValue for String {
274 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
275 match value {
276 Value::Utf8(v) => Ok(v.clone()),
277 _ => Err(FromValueError::TypeMismatch {
278 expected: Type::Utf8,
279 found: value.get_type(),
280 }),
281 }
282 }
283}
284
285impl TryFromValue for OrderedF32 {
286 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
287 match value {
288 Value::Float4(v) => Ok(*v),
289 _ => Err(FromValueError::TypeMismatch {
290 expected: Type::Float4,
291 found: value.get_type(),
292 }),
293 }
294 }
295}
296
297impl TryFromValue for OrderedF64 {
298 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
299 match value {
300 Value::Float8(v) => Ok(*v),
301 _ => Err(FromValueError::TypeMismatch {
302 expected: Type::Float8,
303 found: value.get_type(),
304 }),
305 }
306 }
307}
308
309impl TryFromValue for Blob {
310 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
311 match value {
312 Value::Blob(v) => Ok(v.clone()),
313 _ => Err(FromValueError::TypeMismatch {
314 expected: Type::Blob,
315 found: value.get_type(),
316 }),
317 }
318 }
319}
320
321impl TryFromValue for Uuid4 {
322 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
323 match value {
324 Value::Uuid4(v) => Ok(v.clone()),
325 _ => Err(FromValueError::TypeMismatch {
326 expected: Type::Uuid4,
327 found: value.get_type(),
328 }),
329 }
330 }
331}
332
333impl TryFromValue for Uuid7 {
334 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
335 match value {
336 Value::Uuid7(v) => Ok(v.clone()),
337 _ => Err(FromValueError::TypeMismatch {
338 expected: Type::Uuid7,
339 found: value.get_type(),
340 }),
341 }
342 }
343}
344
345impl TryFromValue for Date {
346 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
347 match value {
348 Value::Date(v) => Ok(v.clone()),
349 _ => Err(FromValueError::TypeMismatch {
350 expected: Type::Date,
351 found: value.get_type(),
352 }),
353 }
354 }
355}
356
357impl TryFromValue for DateTime {
358 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
359 match value {
360 Value::DateTime(v) => Ok(v.clone()),
361 _ => Err(FromValueError::TypeMismatch {
362 expected: Type::DateTime,
363 found: value.get_type(),
364 }),
365 }
366 }
367}
368
369impl TryFromValue for Time {
370 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
371 match value {
372 Value::Time(v) => Ok(v.clone()),
373 _ => Err(FromValueError::TypeMismatch {
374 expected: Type::Time,
375 found: value.get_type(),
376 }),
377 }
378 }
379}
380
381impl TryFromValue for Duration {
382 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
383 match value {
384 Value::Duration(v) => Ok(v.clone()),
385 _ => Err(FromValueError::TypeMismatch {
386 expected: Type::Duration,
387 found: value.get_type(),
388 }),
389 }
390 }
391}
392
393impl TryFromValue for IdentityId {
394 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
395 match value {
396 Value::IdentityId(v) => Ok(v.clone()),
397 _ => Err(FromValueError::TypeMismatch {
398 expected: Type::IdentityId,
399 found: value.get_type(),
400 }),
401 }
402 }
403}
404
405impl TryFromValue for Int {
406 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
407 match value {
408 Value::Int(v) => Ok(v.clone()),
409 _ => Err(FromValueError::TypeMismatch {
410 expected: Type::Int,
411 found: value.get_type(),
412 }),
413 }
414 }
415}
416
417impl TryFromValue for Uint {
418 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
419 match value {
420 Value::Uint(v) => Ok(v.clone()),
421 _ => Err(FromValueError::TypeMismatch {
422 expected: Type::Uint,
423 found: value.get_type(),
424 }),
425 }
426 }
427}
428
429impl TryFromValue for Decimal {
430 fn try_from_value(value: &Value) -> Result<Self, FromValueError> {
431 match value {
432 Value::Decimal(v) => Ok(v.clone()),
433 _ => Err(FromValueError::TypeMismatch {
434 expected: Type::Decimal,
435 found: value.get_type(),
436 }),
437 }
438 }
439}
440
441impl TryFromValueCoerce for i64 {
442 fn try_from_value_coerce(value: &Value) -> Result<Self, FromValueError> {
443 match value {
444 Value::Int1(v) => Ok(*v as i64),
445 Value::Int2(v) => Ok(*v as i64),
446 Value::Int4(v) => Ok(*v as i64),
447 Value::Int8(v) => Ok(*v),
448 _ => Err(FromValueError::TypeMismatch {
449 expected: Type::Int8,
450 found: value.get_type(),
451 }),
452 }
453 }
454}
455
456impl TryFromValueCoerce for i128 {
457 fn try_from_value_coerce(value: &Value) -> Result<Self, FromValueError> {
458 match value {
459 Value::Int1(v) => Ok(*v as i128),
460 Value::Int2(v) => Ok(*v as i128),
461 Value::Int4(v) => Ok(*v as i128),
462 Value::Int8(v) => Ok(*v as i128),
463 Value::Int16(v) => Ok(*v),
464 _ => Err(FromValueError::TypeMismatch {
465 expected: Type::Int16,
466 found: value.get_type(),
467 }),
468 }
469 }
470}
471
472impl TryFromValueCoerce for u64 {
473 fn try_from_value_coerce(value: &Value) -> Result<Self, FromValueError> {
474 match value {
475 Value::Uint1(v) => Ok(*v as u64),
476 Value::Uint2(v) => Ok(*v as u64),
477 Value::Uint4(v) => Ok(*v as u64),
478 Value::Uint8(v) => Ok(*v),
479 Value::Int1(v) if *v >= 0 => Ok(*v as u64),
481 Value::Int2(v) if *v >= 0 => Ok(*v as u64),
482 Value::Int4(v) if *v >= 0 => Ok(*v as u64),
483 Value::Int8(v) if *v >= 0 => Ok(*v as u64),
484 Value::Int1(v) => Err(FromValueError::OutOfRange {
485 value: v.to_string(),
486 target_type: "u64",
487 }),
488 Value::Int2(v) => Err(FromValueError::OutOfRange {
489 value: v.to_string(),
490 target_type: "u64",
491 }),
492 Value::Int4(v) => Err(FromValueError::OutOfRange {
493 value: v.to_string(),
494 target_type: "u64",
495 }),
496 Value::Int8(v) => Err(FromValueError::OutOfRange {
497 value: v.to_string(),
498 target_type: "u64",
499 }),
500 _ => Err(FromValueError::TypeMismatch {
501 expected: Type::Uint8,
502 found: value.get_type(),
503 }),
504 }
505 }
506}
507
508impl TryFromValueCoerce for u128 {
509 fn try_from_value_coerce(value: &Value) -> Result<Self, FromValueError> {
510 match value {
511 Value::Uint1(v) => Ok(*v as u128),
512 Value::Uint2(v) => Ok(*v as u128),
513 Value::Uint4(v) => Ok(*v as u128),
514 Value::Uint8(v) => Ok(*v as u128),
515 Value::Uint16(v) => Ok(*v),
516 _ => Err(FromValueError::TypeMismatch {
517 expected: Type::Uint16,
518 found: value.get_type(),
519 }),
520 }
521 }
522}
523
524impl TryFromValueCoerce for f64 {
525 fn try_from_value_coerce(value: &Value) -> Result<Self, FromValueError> {
526 match value {
527 Value::Float4(v) => Ok(v.value() as f64),
528 Value::Float8(v) => Ok(v.value()),
529 Value::Int1(v) => Ok(*v as f64),
531 Value::Int2(v) => Ok(*v as f64),
532 Value::Int4(v) => Ok(*v as f64),
533 Value::Int8(v) => Ok(*v as f64),
534 Value::Int16(v) => Ok(*v as f64),
535 Value::Uint1(v) => Ok(*v as f64),
536 Value::Uint2(v) => Ok(*v as f64),
537 Value::Uint4(v) => Ok(*v as f64),
538 Value::Uint8(v) => Ok(*v as f64),
539 Value::Uint16(v) => Ok(*v as f64),
540 _ => Err(FromValueError::TypeMismatch {
541 expected: Type::Float8,
542 found: value.get_type(),
543 }),
544 }
545 }
546}
547
548#[cfg(test)]
549pub mod tests {
550 use super::*;
551 use crate::value::{ordered_f32::OrderedF32, ordered_f64::OrderedF64};
552
553 #[test]
554 fn test_try_from_value_primitives() {
555 assert_eq!(bool::try_from_value(&Value::Boolean(true)), Ok(true));
557 assert_eq!(bool::try_from_value(&Value::Boolean(false)), Ok(false));
558 assert!(bool::try_from_value(&Value::Int4(42)).is_err());
559
560 assert_eq!(i8::try_from_value(&Value::Int1(42)), Ok(42i8));
562 assert_eq!(i16::try_from_value(&Value::Int2(1234)), Ok(1234i16));
563 assert_eq!(i32::try_from_value(&Value::Int4(123456)), Ok(123456i32));
564 assert_eq!(i64::try_from_value(&Value::Int8(1234567890)), Ok(1234567890i64));
565
566 assert_eq!(u8::try_from_value(&Value::Uint1(42)), Ok(42u8));
568 assert_eq!(u16::try_from_value(&Value::Uint2(1234)), Ok(1234u16));
569 assert_eq!(u32::try_from_value(&Value::Uint4(123456)), Ok(123456u32));
570 assert_eq!(u64::try_from_value(&Value::Uint8(1234567890)), Ok(1234567890u64));
571
572 assert_eq!(String::try_from_value(&Value::Utf8("hello".to_string())), Ok("hello".to_string()));
574 }
575
576 #[test]
577 fn test_from_value_undefined() {
578 assert_eq!(bool::from_value(&Value::none()), None);
580 assert_eq!(i32::from_value(&Value::none()), None);
581 assert_eq!(String::from_value(&Value::none()), None);
582
583 assert_eq!(bool::from_value(&Value::Int4(42)), None);
585 assert_eq!(i32::from_value(&Value::Boolean(true)), None);
586 }
587
588 #[test]
589 fn test_try_from_value_coerce_i64() {
590 assert_eq!(i64::try_from_value_coerce(&Value::Int1(42)), Ok(42i64));
592 assert_eq!(i64::try_from_value_coerce(&Value::Int2(1234)), Ok(1234i64));
593 assert_eq!(i64::try_from_value_coerce(&Value::Int4(123456)), Ok(123456i64));
594 assert_eq!(i64::try_from_value_coerce(&Value::Int8(1234567890)), Ok(1234567890i64));
595
596 assert!(i64::try_from_value_coerce(&Value::Uint4(42)).is_err());
598 assert!(i64::try_from_value_coerce(&Value::Boolean(true)).is_err());
599 }
600
601 #[test]
602 fn test_try_from_value_coerce_u64() {
603 assert_eq!(u64::try_from_value_coerce(&Value::Uint1(42)), Ok(42u64));
605 assert_eq!(u64::try_from_value_coerce(&Value::Uint2(1234)), Ok(1234u64));
606 assert_eq!(u64::try_from_value_coerce(&Value::Uint4(123456)), Ok(123456u64));
607 assert_eq!(u64::try_from_value_coerce(&Value::Uint8(1234567890)), Ok(1234567890u64));
608
609 assert_eq!(u64::try_from_value_coerce(&Value::Int4(42)), Ok(42u64));
611
612 assert!(u64::try_from_value_coerce(&Value::Int4(-42)).is_err());
614 }
615
616 #[test]
617 fn test_try_from_value_coerce_f64() {
618 let f4 = OrderedF32::try_from(3.14f32).unwrap();
620 let f8 = OrderedF64::try_from(3.14159f64).unwrap();
621 assert!((f64::try_from_value_coerce(&Value::Float4(f4)).unwrap() - 3.14).abs() < 0.01);
622 assert!((f64::try_from_value_coerce(&Value::Float8(f8)).unwrap() - 3.14159).abs() < 0.00001);
623
624 assert_eq!(f64::try_from_value_coerce(&Value::Int4(42)), Ok(42.0f64));
626 assert_eq!(f64::try_from_value_coerce(&Value::Uint4(42)), Ok(42.0f64));
627 }
628
629 #[test]
630 fn test_from_value_coerce_undefined() {
631 assert_eq!(i64::from_value_coerce(&Value::none()), None);
633 assert_eq!(u64::from_value_coerce(&Value::none()), None);
634 assert_eq!(f64::from_value_coerce(&Value::none()), None);
635 }
636}