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