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