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