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