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