1use std::{
14 cmp::Ordering,
15 fmt::{Display, Formatter},
16};
17
18use num_traits::ToPrimitive;
19use serde::{Deserialize, Serialize};
20pub mod as_string;
21pub mod blob;
22pub mod boolean;
23pub mod constraint;
24pub mod container;
25pub mod date;
26pub mod datetime;
27pub mod decimal;
28pub mod dictionary;
29pub mod duration;
30pub mod frame;
31pub mod identity;
32pub mod int;
33pub mod into;
34pub mod is;
35pub mod json;
36pub mod number;
37pub mod ordered_f32;
38pub mod ordered_f64;
39pub mod row_number;
40pub mod sumtype;
41pub mod temporal;
42pub mod time;
43pub mod to_value;
44pub mod try_from;
45pub mod r#type;
46pub mod uint;
47pub mod uuid;
48
49use std::{fmt, hash, mem};
50
51use blob::Blob;
52use date::Date;
53use datetime::DateTime;
54use decimal::Decimal;
55use dictionary::DictionaryEntryId;
56use duration::Duration;
57use identity::IdentityId;
58use int::Int;
59use ordered_f32::OrderedF32;
60use ordered_f64::OrderedF64;
61use time::Time;
62use r#type::Type;
63use uint::Uint;
64use uuid::{Uuid4, Uuid7};
65
66#[derive(Clone, Debug, Serialize, Deserialize)]
67pub enum Value {
68 None {
69 #[serde(skip, default = "default_none_inner")]
70 inner: Type,
71 },
72
73 Boolean(bool),
74
75 Float4(OrderedF32),
76
77 Float8(OrderedF64),
78
79 Int1(i8),
80
81 Int2(i16),
82
83 Int4(i32),
84
85 Int8(i64),
86
87 Int16(i128),
88
89 Utf8(String),
90
91 Uint1(u8),
92
93 Uint2(u16),
94
95 Uint4(u32),
96
97 Uint8(u64),
98
99 Uint16(u128),
100
101 Date(Date),
102
103 DateTime(DateTime),
104
105 Time(Time),
106
107 Duration(Duration),
108
109 IdentityId(IdentityId),
110
111 Uuid4(Uuid4),
112
113 Uuid7(Uuid7),
114
115 Blob(Blob),
116
117 Int(Int),
118
119 Uint(Uint),
120
121 Decimal(Decimal),
122
123 Any(Box<Value>),
124
125 DictionaryId(DictionaryEntryId),
126
127 Type(Type),
128
129 List(Vec<Value>),
130
131 Record(Vec<(String, Value)>),
132
133 Tuple(Vec<Value>),
134}
135
136fn default_none_inner() -> Type {
137 Type::Any
138}
139
140impl Value {
141 pub fn none() -> Self {
142 Value::None {
143 inner: Type::Any,
144 }
145 }
146
147 pub fn none_of(ty: Type) -> Self {
148 Value::None {
149 inner: ty,
150 }
151 }
152
153 pub fn bool(v: impl Into<bool>) -> Self {
154 Value::Boolean(v.into())
155 }
156
157 pub fn float4(v: impl Into<f32>) -> Self {
158 OrderedF32::try_from(v.into()).map(Value::Float4).unwrap_or(Value::None {
159 inner: Type::Float4,
160 })
161 }
162
163 pub fn float8(v: impl Into<f64>) -> Self {
164 OrderedF64::try_from(v.into()).map(Value::Float8).unwrap_or(Value::None {
165 inner: Type::Float8,
166 })
167 }
168
169 pub fn int1(v: impl Into<i8>) -> Self {
170 Value::Int1(v.into())
171 }
172
173 pub fn int2(v: impl Into<i16>) -> Self {
174 Value::Int2(v.into())
175 }
176
177 pub fn int4(v: impl Into<i32>) -> Self {
178 Value::Int4(v.into())
179 }
180
181 pub fn int8(v: impl Into<i64>) -> Self {
182 Value::Int8(v.into())
183 }
184
185 pub fn int16(v: impl Into<i128>) -> Self {
186 Value::Int16(v.into())
187 }
188
189 pub fn utf8(v: impl Into<String>) -> Self {
190 Value::Utf8(v.into())
191 }
192
193 pub fn uint1(v: impl Into<u8>) -> Self {
194 Value::Uint1(v.into())
195 }
196
197 pub fn uint2(v: impl Into<u16>) -> Self {
198 Value::Uint2(v.into())
199 }
200
201 pub fn uint4(v: impl Into<u32>) -> Self {
202 Value::Uint4(v.into())
203 }
204
205 pub fn uint8(v: impl Into<u64>) -> Self {
206 Value::Uint8(v.into())
207 }
208
209 pub fn uint16(v: impl Into<u128>) -> Self {
210 Value::Uint16(v.into())
211 }
212
213 pub fn date(v: impl Into<Date>) -> Self {
214 Value::Date(v.into())
215 }
216
217 pub fn datetime(v: impl Into<DateTime>) -> Self {
218 Value::DateTime(v.into())
219 }
220
221 pub fn time(v: impl Into<Time>) -> Self {
222 Value::Time(v.into())
223 }
224
225 pub fn duration(v: impl Into<Duration>) -> Self {
226 Value::Duration(v.into())
227 }
228
229 pub fn identity_id(v: impl Into<IdentityId>) -> Self {
230 Value::IdentityId(v.into())
231 }
232
233 pub fn uuid4(v: impl Into<Uuid4>) -> Self {
234 Value::Uuid4(v.into())
235 }
236
237 pub fn uuid7(v: impl Into<Uuid7>) -> Self {
238 Value::Uuid7(v.into())
239 }
240
241 pub fn blob(v: impl Into<Blob>) -> Self {
242 Value::Blob(v.into())
243 }
244
245 pub fn any(v: impl Into<Value>) -> Self {
246 Value::Any(Box::new(v.into()))
247 }
248
249 pub fn list(items: Vec<Value>) -> Self {
250 Value::List(items)
251 }
252
253 pub fn record(fields: Vec<(String, Value)>) -> Self {
254 Value::Record(fields)
255 }
256
257 pub fn to_usize(&self) -> Option<usize> {
258 match self {
259 Value::Uint1(v) => Some(*v as usize),
260 Value::Uint2(v) => Some(*v as usize),
261 Value::Uint4(v) => Some(*v as usize),
262 Value::Uint8(v) => usize::try_from(*v).ok(),
263 Value::Uint16(v) => usize::try_from(*v).ok(),
264 Value::Int1(v) => usize::try_from(*v).ok(),
265 Value::Int2(v) => usize::try_from(*v).ok(),
266 Value::Int4(v) => usize::try_from(*v).ok(),
267 Value::Int8(v) => usize::try_from(*v).ok(),
268 Value::Int16(v) => usize::try_from(*v).ok(),
269 Value::Float4(v) => {
270 let f = v.value();
271 if f >= 0.0 {
272 Some(f as usize)
273 } else {
274 None
275 }
276 }
277 Value::Float8(v) => {
278 let f = v.value();
279 if f >= 0.0 {
280 Some(f as usize)
281 } else {
282 None
283 }
284 }
285 Value::Int(v) => v.0.to_u64().and_then(|n| usize::try_from(n).ok()),
286 Value::Uint(v) => v.0.to_u64().and_then(|n| usize::try_from(n).ok()),
287 Value::Decimal(v) => v.0.to_u64().and_then(|n| usize::try_from(n).ok()),
288 Value::Utf8(s) => {
289 let s = s.trim();
290 if let Ok(n) = s.parse::<u64>() {
291 usize::try_from(n).ok()
292 } else if let Ok(f) = s.parse::<f64>() {
293 if f >= 0.0 {
294 Some(f as usize)
295 } else {
296 None
297 }
298 } else {
299 None
300 }
301 }
302 _ => None,
303 }
304 }
305}
306
307impl PartialEq for Value {
308 fn eq(&self, other: &Self) -> bool {
309 match (self, other) {
310 (
311 Value::None {
312 ..
313 },
314 Value::None {
315 ..
316 },
317 ) => true,
318 (Value::Boolean(l), Value::Boolean(r)) => l == r,
319 (Value::Float4(l), Value::Float4(r)) => l == r,
320 (Value::Float8(l), Value::Float8(r)) => l == r,
321 (Value::Int1(l), Value::Int1(r)) => l == r,
322 (Value::Int2(l), Value::Int2(r)) => l == r,
323 (Value::Int4(l), Value::Int4(r)) => l == r,
324 (Value::Int8(l), Value::Int8(r)) => l == r,
325 (Value::Int16(l), Value::Int16(r)) => l == r,
326 (Value::Utf8(l), Value::Utf8(r)) => l == r,
327 (Value::Uint1(l), Value::Uint1(r)) => l == r,
328 (Value::Uint2(l), Value::Uint2(r)) => l == r,
329 (Value::Uint4(l), Value::Uint4(r)) => l == r,
330 (Value::Uint8(l), Value::Uint8(r)) => l == r,
331 (Value::Uint16(l), Value::Uint16(r)) => l == r,
332 (Value::Date(l), Value::Date(r)) => l == r,
333 (Value::DateTime(l), Value::DateTime(r)) => l == r,
334 (Value::Time(l), Value::Time(r)) => l == r,
335 (Value::Duration(l), Value::Duration(r)) => l == r,
336 (Value::IdentityId(l), Value::IdentityId(r)) => l == r,
337 (Value::Uuid4(l), Value::Uuid4(r)) => l == r,
338 (Value::Uuid7(l), Value::Uuid7(r)) => l == r,
339 (Value::Blob(l), Value::Blob(r)) => l == r,
340 (Value::Int(l), Value::Int(r)) => l == r,
341 (Value::Uint(l), Value::Uint(r)) => l == r,
342 (Value::Decimal(l), Value::Decimal(r)) => l == r,
343 (Value::Any(l), Value::Any(r)) => l == r,
344 (Value::DictionaryId(l), Value::DictionaryId(r)) => l == r,
345 (Value::Type(l), Value::Type(r)) => l == r,
346 (Value::List(l), Value::List(r)) => l == r,
347 (Value::Record(l), Value::Record(r)) => l == r,
348 (Value::Tuple(l), Value::Tuple(r)) => l == r,
349 _ => false,
350 }
351 }
352}
353
354impl Eq for Value {}
355
356impl hash::Hash for Value {
357 fn hash<H: hash::Hasher>(&self, state: &mut H) {
358 mem::discriminant(self).hash(state);
359 match self {
360 Value::None {
361 ..
362 } => {}
363 Value::Boolean(v) => v.hash(state),
364 Value::Float4(v) => v.hash(state),
365 Value::Float8(v) => v.hash(state),
366 Value::Int1(v) => v.hash(state),
367 Value::Int2(v) => v.hash(state),
368 Value::Int4(v) => v.hash(state),
369 Value::Int8(v) => v.hash(state),
370 Value::Int16(v) => v.hash(state),
371 Value::Utf8(v) => v.hash(state),
372 Value::Uint1(v) => v.hash(state),
373 Value::Uint2(v) => v.hash(state),
374 Value::Uint4(v) => v.hash(state),
375 Value::Uint8(v) => v.hash(state),
376 Value::Uint16(v) => v.hash(state),
377 Value::Date(v) => v.hash(state),
378 Value::DateTime(v) => v.hash(state),
379 Value::Time(v) => v.hash(state),
380 Value::Duration(v) => v.hash(state),
381 Value::IdentityId(v) => v.hash(state),
382 Value::Uuid4(v) => v.hash(state),
383 Value::Uuid7(v) => v.hash(state),
384 Value::Blob(v) => v.hash(state),
385 Value::Int(v) => v.hash(state),
386 Value::Uint(v) => v.hash(state),
387 Value::Decimal(v) => v.hash(state),
388 Value::Any(v) => v.hash(state),
389 Value::DictionaryId(v) => v.hash(state),
390 Value::Type(v) => v.hash(state),
391 Value::List(v) => v.hash(state),
392 Value::Record(fields) => {
393 for (k, v) in fields {
394 k.hash(state);
395 v.hash(state);
396 }
397 }
398 Value::Tuple(v) => v.hash(state),
399 }
400 }
401}
402
403impl PartialOrd for Value {
404 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
405 Some(self.cmp(other))
406 }
407}
408
409impl Ord for Value {
410 fn cmp(&self, other: &Self) -> Ordering {
411 match (self, other) {
412 (
413 Value::None {
414 ..
415 },
416 Value::None {
417 ..
418 },
419 ) => Ordering::Equal,
420 (
421 Value::None {
422 ..
423 },
424 _,
425 ) => Ordering::Greater,
426 (
427 _,
428 Value::None {
429 ..
430 },
431 ) => Ordering::Less,
432 (Value::Boolean(l), Value::Boolean(r)) => l.cmp(r),
433 (Value::Float4(l), Value::Float4(r)) => l.cmp(r),
434 (Value::Float8(l), Value::Float8(r)) => l.cmp(r),
435 (Value::Int1(l), Value::Int1(r)) => l.cmp(r),
436 (Value::Int2(l), Value::Int2(r)) => l.cmp(r),
437 (Value::Int4(l), Value::Int4(r)) => l.cmp(r),
438 (Value::Int8(l), Value::Int8(r)) => l.cmp(r),
439 (Value::Int16(l), Value::Int16(r)) => l.cmp(r),
440 (Value::Utf8(l), Value::Utf8(r)) => l.cmp(r),
441 (Value::Uint1(l), Value::Uint1(r)) => l.cmp(r),
442 (Value::Uint2(l), Value::Uint2(r)) => l.cmp(r),
443 (Value::Uint4(l), Value::Uint4(r)) => l.cmp(r),
444 (Value::Uint8(l), Value::Uint8(r)) => l.cmp(r),
445 (Value::Uint16(l), Value::Uint16(r)) => l.cmp(r),
446 (Value::Date(l), Value::Date(r)) => l.cmp(r),
447 (Value::DateTime(l), Value::DateTime(r)) => l.cmp(r),
448 (Value::Time(l), Value::Time(r)) => l.cmp(r),
449 (Value::Duration(l), Value::Duration(r)) => l.cmp(r),
450 (Value::IdentityId(l), Value::IdentityId(r)) => l.cmp(r),
451 (Value::Uuid4(l), Value::Uuid4(r)) => l.cmp(r),
452 (Value::Uuid7(l), Value::Uuid7(r)) => l.cmp(r),
453 (Value::Blob(l), Value::Blob(r)) => l.cmp(r),
454 (Value::Int(l), Value::Int(r)) => l.cmp(r),
455 (Value::Uint(l), Value::Uint(r)) => l.cmp(r),
456 (Value::Decimal(l), Value::Decimal(r)) => l.cmp(r),
457 (Value::DictionaryId(l), Value::DictionaryId(r)) => l.to_u128().cmp(&r.to_u128()),
458 (Value::Type(l), Value::Type(r)) => l.cmp(r),
459 (Value::List(_), Value::List(_)) => unreachable!("List values are not orderable"),
460 (Value::Record(_), Value::Record(_)) => unreachable!("Record values are not orderable"),
461 (Value::Tuple(_), Value::Tuple(_)) => unreachable!("Tuple values are not orderable"),
462 (Value::Any(_), Value::Any(_)) => unreachable!("Any values are not orderable"),
463 _ => unimplemented!(),
464 }
465 }
466}
467
468impl Display for Value {
469 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
470 match self {
471 Value::Boolean(true) => f.write_str("true"),
472 Value::Boolean(false) => f.write_str("false"),
473 Value::Float4(value) => Display::fmt(value, f),
474 Value::Float8(value) => Display::fmt(value, f),
475 Value::Int1(value) => Display::fmt(value, f),
476 Value::Int2(value) => Display::fmt(value, f),
477 Value::Int4(value) => Display::fmt(value, f),
478 Value::Int8(value) => Display::fmt(value, f),
479 Value::Int16(value) => Display::fmt(value, f),
480 Value::Utf8(value) => Display::fmt(value, f),
481 Value::Uint1(value) => Display::fmt(value, f),
482 Value::Uint2(value) => Display::fmt(value, f),
483 Value::Uint4(value) => Display::fmt(value, f),
484 Value::Uint8(value) => Display::fmt(value, f),
485 Value::Uint16(value) => Display::fmt(value, f),
486 Value::Date(value) => Display::fmt(value, f),
487 Value::DateTime(value) => Display::fmt(value, f),
488 Value::Time(value) => Display::fmt(value, f),
489 Value::Duration(value) => Display::fmt(value, f),
490 Value::IdentityId(value) => Display::fmt(value, f),
491 Value::Uuid4(value) => Display::fmt(value, f),
492 Value::Uuid7(value) => Display::fmt(value, f),
493 Value::Blob(value) => Display::fmt(value, f),
494 Value::Int(value) => Display::fmt(value, f),
495 Value::Uint(value) => Display::fmt(value, f),
496 Value::Decimal(value) => Display::fmt(value, f),
497 Value::Any(value) => Display::fmt(value, f),
498 Value::DictionaryId(value) => Display::fmt(value, f),
499 Value::Type(value) => Display::fmt(value, f),
500 Value::List(items) => {
501 f.write_str("[")?;
502 for (i, item) in items.iter().enumerate() {
503 if i > 0 {
504 f.write_str(", ")?;
505 }
506 Display::fmt(item, f)?;
507 }
508 f.write_str("]")
509 }
510 Value::Record(fields) => {
511 f.write_str("{")?;
512 for (i, (key, value)) in fields.iter().enumerate() {
513 if i > 0 {
514 f.write_str(", ")?;
515 }
516 write!(f, "{}: {}", key, value)?;
517 }
518 f.write_str("}")
519 }
520 Value::Tuple(items) => {
521 f.write_str("(")?;
522 for (i, item) in items.iter().enumerate() {
523 if i > 0 {
524 f.write_str(", ")?;
525 }
526 Display::fmt(item, f)?;
527 }
528 f.write_str(")")
529 }
530 Value::None {
531 ..
532 } => f.write_str("none"),
533 }
534 }
535}
536
537impl Value {
538 pub fn get_type(&self) -> Type {
539 match self {
540 Value::None {
541 inner,
542 } => Type::Option(Box::new(inner.clone())),
543 Value::Boolean(_) => Type::Boolean,
544 Value::Float4(_) => Type::Float4,
545 Value::Float8(_) => Type::Float8,
546 Value::Int1(_) => Type::Int1,
547 Value::Int2(_) => Type::Int2,
548 Value::Int4(_) => Type::Int4,
549 Value::Int8(_) => Type::Int8,
550 Value::Int16(_) => Type::Int16,
551 Value::Utf8(_) => Type::Utf8,
552 Value::Uint1(_) => Type::Uint1,
553 Value::Uint2(_) => Type::Uint2,
554 Value::Uint4(_) => Type::Uint4,
555 Value::Uint8(_) => Type::Uint8,
556 Value::Uint16(_) => Type::Uint16,
557 Value::Date(_) => Type::Date,
558 Value::DateTime(_) => Type::DateTime,
559 Value::Time(_) => Type::Time,
560 Value::Duration(_) => Type::Duration,
561 Value::IdentityId(_) => Type::IdentityId,
562 Value::Uuid4(_) => Type::Uuid4,
563 Value::Uuid7(_) => Type::Uuid7,
564 Value::Blob(_) => Type::Blob,
565 Value::Int(_) => Type::Int,
566 Value::Uint(_) => Type::Uint,
567 Value::Decimal(_) => Type::Decimal,
568 Value::Any(_) => Type::Any,
569 Value::DictionaryId(_) => Type::DictionaryId,
570 Value::Type(t) => t.clone(),
571 Value::List(items) => {
572 let element_type = items.first().map(|v| v.get_type()).unwrap_or(Type::Any);
573 Type::list_of(element_type)
574 }
575 Value::Record(fields) => {
576 Type::Record(fields.iter().map(|(k, v)| (k.clone(), v.get_type())).collect())
577 }
578 Value::Tuple(items) => Type::Tuple(items.iter().map(|v| v.get_type()).collect()),
579 }
580 }
581}
582
583#[cfg(test)]
584mod tests {
585 use std::str::FromStr;
586
587 use super::*;
588
589 #[test]
592 fn to_usize_uint1() {
593 assert_eq!(Value::uint1(42u8).to_usize(), Some(42));
594 }
595
596 #[test]
597 fn to_usize_uint2() {
598 assert_eq!(Value::uint2(1000u16).to_usize(), Some(1000));
599 }
600
601 #[test]
602 fn to_usize_uint4() {
603 assert_eq!(Value::uint4(100_000u32).to_usize(), Some(100_000));
604 }
605
606 #[test]
607 fn to_usize_uint8() {
608 assert_eq!(Value::uint8(1_000_000u64).to_usize(), Some(1_000_000));
609 }
610
611 #[test]
612 fn to_usize_uint16() {
613 assert_eq!(Value::Uint16(500u128).to_usize(), Some(500));
614 }
615
616 #[test]
617 fn to_usize_int1() {
618 assert_eq!(Value::int1(100i8).to_usize(), Some(100));
619 }
620
621 #[test]
622 fn to_usize_int2() {
623 assert_eq!(Value::int2(5000i16).to_usize(), Some(5000));
624 }
625
626 #[test]
627 fn to_usize_int4() {
628 assert_eq!(Value::int4(50_000i32).to_usize(), Some(50_000));
629 }
630
631 #[test]
632 fn to_usize_int8() {
633 assert_eq!(Value::int8(1_000_000i64).to_usize(), Some(1_000_000));
634 }
635
636 #[test]
637 fn to_usize_int16() {
638 assert_eq!(Value::Int16(999i128).to_usize(), Some(999));
639 }
640
641 #[test]
642 fn to_usize_float4() {
643 assert_eq!(Value::float4(42.0f32).to_usize(), Some(42));
644 }
645
646 #[test]
647 fn to_usize_float8() {
648 assert_eq!(Value::float8(42.0f64).to_usize(), Some(42));
649 }
650
651 #[test]
652 fn to_usize_int_bigint() {
653 assert_eq!(Value::Int(Int::from_i64(42)).to_usize(), Some(42));
654 }
655
656 #[test]
657 fn to_usize_uint_bigint() {
658 assert_eq!(Value::Uint(Uint::from_u64(42)).to_usize(), Some(42));
659 }
660
661 #[test]
662 fn to_usize_decimal() {
663 assert_eq!(Value::Decimal(Decimal::from_i64(42)).to_usize(), Some(42));
664 }
665
666 #[test]
669 fn to_usize_int1_negative() {
670 assert_eq!(Value::int1(-1i8).to_usize(), None);
671 }
672
673 #[test]
674 fn to_usize_int2_negative() {
675 assert_eq!(Value::int2(-100i16).to_usize(), None);
676 }
677
678 #[test]
679 fn to_usize_int4_negative() {
680 assert_eq!(Value::int4(-1i32).to_usize(), None);
681 }
682
683 #[test]
684 fn to_usize_int8_negative() {
685 assert_eq!(Value::int8(-1i64).to_usize(), None);
686 }
687
688 #[test]
689 fn to_usize_int16_negative() {
690 assert_eq!(Value::Int16(-1i128).to_usize(), None);
691 }
692
693 #[test]
694 fn to_usize_float4_negative() {
695 assert_eq!(Value::float4(-1.0f32).to_usize(), None);
696 }
697
698 #[test]
699 fn to_usize_float8_negative() {
700 assert_eq!(Value::float8(-1.0f64).to_usize(), None);
701 }
702
703 #[test]
704 fn to_usize_int_bigint_negative() {
705 assert_eq!(Value::Int(Int::from_i64(-5)).to_usize(), None);
706 }
707
708 #[test]
711 fn to_usize_zero() {
712 assert_eq!(Value::uint1(0u8).to_usize(), Some(0));
713 }
714
715 #[test]
716 fn to_usize_int1_zero() {
717 assert_eq!(Value::int1(0i8).to_usize(), Some(0));
718 }
719
720 #[test]
721 fn to_usize_float4_zero() {
722 assert_eq!(Value::float4(0.0f32).to_usize(), Some(0));
723 }
724
725 #[test]
728 fn to_usize_boolean_none() {
729 assert_eq!(Value::bool(true).to_usize(), None);
730 }
731
732 #[test]
733 fn to_usize_utf8_integer() {
734 assert_eq!(Value::utf8("42").to_usize(), Some(42));
735 }
736
737 #[test]
738 fn to_usize_utf8_float() {
739 assert_eq!(Value::utf8("3.7").to_usize(), Some(3));
740 }
741
742 #[test]
743 fn to_usize_utf8_negative() {
744 assert_eq!(Value::utf8("-5").to_usize(), None);
745 }
746
747 #[test]
748 fn to_usize_utf8_negative_float() {
749 assert_eq!(Value::utf8("-1.5").to_usize(), None);
750 }
751
752 #[test]
753 fn to_usize_utf8_whitespace() {
754 assert_eq!(Value::utf8(" 42 ").to_usize(), Some(42));
755 }
756
757 #[test]
758 fn to_usize_utf8_zero() {
759 assert_eq!(Value::utf8("0").to_usize(), Some(0));
760 }
761
762 #[test]
763 fn to_usize_utf8_non_numeric() {
764 assert_eq!(Value::utf8("hello").to_usize(), None);
765 }
766
767 #[test]
768 fn to_usize_utf8_empty() {
769 assert_eq!(Value::utf8("").to_usize(), None);
770 }
771
772 #[test]
773 fn to_usize_none_none() {
774 assert_eq!(Value::none().to_usize(), None);
775 }
776
777 #[test]
780 fn to_usize_float8_fractional() {
781 assert_eq!(Value::float8(3.7f64).to_usize(), Some(3));
782 }
783
784 #[test]
785 fn to_usize_decimal_fractional() {
786 assert_eq!(Value::Decimal(Decimal::from_str("3.7").unwrap()).to_usize(), Some(3));
787 }
788}