1use super::{Entry, EntryPath, Type, TypeUnion, ValueRecord, sparse_record::SparseRecord};
2use std::cmp::Ordering;
3
4#[derive(Debug, Default, Clone, PartialEq)]
34pub enum Value {
35 Bool(bool),
37
38 I8(i8),
40
41 I16(i16),
43
44 I32(i32),
46
47 I64(i64),
49
50 U8(u8),
52
53 U16(u16),
55
56 U32(u32),
58
59 U64(u64),
61
62 F32(f32),
64
65 F64(f64),
67
68 SparseRecord(SparseRecord),
70
71 #[default]
73 Null,
74
75 Record(ValueRecord),
77
78 List(Vec<Value>),
80
81 String(String),
83
84 Bytes(Vec<u8>),
86
87 Uuid(uuid::Uuid),
89
90 #[cfg(feature = "rust_decimal")]
93 Decimal(rust_decimal::Decimal),
94
95 #[cfg(feature = "bigdecimal")]
98 BigDecimal(bigdecimal::BigDecimal),
99
100 #[cfg(feature = "jiff")]
103 Timestamp(jiff::Timestamp),
104
105 #[cfg(feature = "jiff")]
108 Zoned(jiff::Zoned),
109
110 #[cfg(feature = "jiff")]
113 Date(jiff::civil::Date),
114
115 #[cfg(feature = "jiff")]
118 Time(jiff::civil::Time),
119
120 #[cfg(feature = "jiff")]
123 DateTime(jiff::civil::DateTime),
124}
125
126impl Value {
127 pub const fn null() -> Self {
137 Self::Null
138 }
139
140 pub fn checked_add(&self, other: &Self) -> Option<Self> {
144 match (self, other) {
145 (Self::I8(a), Self::I8(b)) => a.checked_add(*b).map(Self::I8),
146 (Self::I16(a), Self::I16(b)) => a.checked_add(*b).map(Self::I16),
147 (Self::I32(a), Self::I32(b)) => a.checked_add(*b).map(Self::I32),
148 (Self::I64(a), Self::I64(b)) => a.checked_add(*b).map(Self::I64),
149 (Self::U8(a), Self::U8(b)) => a.checked_add(*b).map(Self::U8),
150 (Self::U16(a), Self::U16(b)) => a.checked_add(*b).map(Self::U16),
151 (Self::U32(a), Self::U32(b)) => a.checked_add(*b).map(Self::U32),
152 (Self::U64(a), Self::U64(b)) => a.checked_add(*b).map(Self::U64),
153 (Self::F32(a), Self::F32(b)) => Some(Self::F32(a + b)),
154 (Self::F64(a), Self::F64(b)) => Some(Self::F64(a + b)),
155 _ => None,
156 }
157 }
158
159 pub fn checked_sub(&self, other: &Self) -> Option<Self> {
164 match (self, other) {
165 (Self::I8(a), Self::I8(b)) => a.checked_sub(*b).map(Self::I8),
166 (Self::I16(a), Self::I16(b)) => a.checked_sub(*b).map(Self::I16),
167 (Self::I32(a), Self::I32(b)) => a.checked_sub(*b).map(Self::I32),
168 (Self::I64(a), Self::I64(b)) => a.checked_sub(*b).map(Self::I64),
169 (Self::U8(a), Self::U8(b)) => a.checked_sub(*b).map(Self::U8),
170 (Self::U16(a), Self::U16(b)) => a.checked_sub(*b).map(Self::U16),
171 (Self::U32(a), Self::U32(b)) => a.checked_sub(*b).map(Self::U32),
172 (Self::U64(a), Self::U64(b)) => a.checked_sub(*b).map(Self::U64),
173 (Self::F32(a), Self::F32(b)) => Some(Self::F32(a - b)),
174 (Self::F64(a), Self::F64(b)) => Some(Self::F64(a - b)),
175 _ => None,
176 }
177 }
178
179 pub const fn is_null(&self) -> bool {
189 matches!(self, Self::Null)
190 }
191
192 pub const fn is_record(&self) -> bool {
194 matches!(self, Self::Record(_))
195 }
196
197 pub fn record_from_vec(fields: Vec<Self>) -> Self {
207 ValueRecord::from_vec(fields).into()
208 }
209
210 pub const fn from_bool(src: bool) -> Self {
220 Self::Bool(src)
221 }
222
223 pub fn as_str(&self) -> Option<&str> {
226 match self {
227 Self::String(v) => Some(&**v),
228 _ => None,
229 }
230 }
231
232 pub fn as_string_unwrap(&self) -> &str {
239 match self {
240 Self::String(v) => v,
241 _ => todo!(),
242 }
243 }
244
245 pub fn as_record(&self) -> Option<&ValueRecord> {
248 match self {
249 Self::Record(record) => Some(record),
250 _ => None,
251 }
252 }
253
254 pub fn as_record_unwrap(&self) -> &ValueRecord {
261 match self {
262 Self::Record(record) => record,
263 _ => panic!("{self:#?}"),
264 }
265 }
266
267 pub fn as_record_mut_unwrap(&mut self) -> &mut ValueRecord {
274 match self {
275 Self::Record(record) => record,
276 _ => panic!(),
277 }
278 }
279
280 pub fn into_record(self) -> ValueRecord {
287 match self {
288 Self::Record(record) => record,
289 _ => panic!(),
290 }
291 }
292
293 pub fn is_a(&self, ty: &Type) -> bool {
298 if let Type::Union(types) = ty {
299 return types.iter().any(|t| self.is_a(t));
300 }
301 match self {
302 Self::Null => true,
303 Self::Bool(_) => ty.is_bool(),
304 Self::I8(_) => ty.is_i8(),
305 Self::I16(_) => ty.is_i16(),
306 Self::I32(_) => ty.is_i32(),
307 Self::I64(_) => ty.is_i64(),
308 Self::U8(_) => ty.is_u8(),
309 Self::U16(_) => ty.is_u16(),
310 Self::U32(_) => ty.is_u32(),
311 Self::U64(_) => ty.is_u64(),
312 Self::F32(_) => ty.is_f32(),
313 Self::F64(_) => ty.is_f64(),
314 Self::List(value) => match ty {
315 Type::List(ty) => {
316 if value.is_empty() {
317 true
318 } else {
319 value[0].is_a(ty)
320 }
321 }
322 _ => false,
323 },
324 Self::Record(value) => match ty {
325 Type::Record(fields) if value.len() == fields.len() => value
326 .fields
327 .iter()
328 .zip(fields.iter())
329 .all(|(value, ty)| value.is_a(ty)),
330 _ => false,
331 },
332 Self::SparseRecord(value) => match ty {
333 Type::SparseRecord(fields) => value.fields == *fields,
334 _ => false,
335 },
336 Self::String(_) => ty.is_string(),
337 Self::Bytes(_) => ty.is_bytes(),
338 Self::Uuid(_) => ty.is_uuid(),
339 #[cfg(feature = "rust_decimal")]
340 Value::Decimal(_) => *ty == Type::Decimal,
341 #[cfg(feature = "bigdecimal")]
342 Value::BigDecimal(_) => *ty == Type::BigDecimal,
343 #[cfg(feature = "jiff")]
344 Value::Timestamp(_) => *ty == Type::Timestamp,
345 #[cfg(feature = "jiff")]
346 Value::Zoned(_) => *ty == Type::Zoned,
347 #[cfg(feature = "jiff")]
348 Value::Date(_) => *ty == Type::Date,
349 #[cfg(feature = "jiff")]
350 Value::Time(_) => *ty == Type::Time,
351 #[cfg(feature = "jiff")]
352 Value::DateTime(_) => *ty == Type::DateTime,
353 }
354 }
355
356 pub fn infer_ty(&self) -> Type {
367 match self {
368 Value::Bool(_) => Type::Bool,
369 Value::I8(_) => Type::I8,
370 Value::I16(_) => Type::I16,
371 Value::I32(_) => Type::I32,
372 Value::I64(_) => Type::I64,
373 Value::SparseRecord(v) => Type::SparseRecord(v.fields.clone()),
374 Value::Null => Type::Null,
375 Value::Record(v) => Type::Record(v.fields.iter().map(Self::infer_ty).collect()),
376 Value::String(_) => Type::String,
377 Value::List(items) if items.is_empty() => Type::list(Type::Null),
378 Value::List(items) => {
379 let mut union = TypeUnion::new();
380 for item in items {
381 union.insert(item.infer_ty());
382 }
383 Type::list(union.simplify())
384 }
385 Value::U8(_) => Type::U8,
386 Value::U16(_) => Type::U16,
387 Value::U32(_) => Type::U32,
388 Value::U64(_) => Type::U64,
389 Value::F32(_) => Type::F32,
390 Value::F64(_) => Type::F64,
391 Value::Bytes(_) => Type::Bytes,
392 Value::Uuid(_) => Type::Uuid,
393 #[cfg(feature = "rust_decimal")]
394 Value::Decimal(_) => Type::Decimal,
395 #[cfg(feature = "bigdecimal")]
396 Value::BigDecimal(_) => Type::BigDecimal,
397 #[cfg(feature = "jiff")]
398 Value::Timestamp(_) => Type::Timestamp,
399 #[cfg(feature = "jiff")]
400 Value::Zoned(_) => Type::Zoned,
401 #[cfg(feature = "jiff")]
402 Value::Date(_) => Type::Date,
403 #[cfg(feature = "jiff")]
404 Value::Time(_) => Type::Time,
405 #[cfg(feature = "jiff")]
406 Value::DateTime(_) => Type::DateTime,
407 }
408 }
409
410 #[track_caller]
420 pub fn entry(&self, path: impl EntryPath) -> Entry<'_> {
421 let mut ret = Entry::Value(self);
422
423 for step in path.step_iter() {
424 ret = match ret {
425 Entry::Value(Self::Record(record)) => Entry::Value(&record[step]),
426 Entry::Value(Self::List(items)) => Entry::Value(&items[step]),
427 _ => todo!("ret={ret:#?}; base={self:#?}; step={step:#?}"),
428 }
429 }
430
431 ret
432 }
433
434 pub fn take(&mut self) -> Self {
446 std::mem::take(self)
447 }
448}
449
450impl AsRef<Self> for Value {
451 fn as_ref(&self) -> &Self {
452 self
453 }
454}
455
456impl PartialOrd for Value {
457 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
465 match (self, other) {
466 (Value::Null, _) | (_, Value::Null) => None,
468
469 (Value::Bool(a), Value::Bool(b)) => a.partial_cmp(b),
471
472 (Value::I8(a), Value::I8(b)) => a.partial_cmp(b),
474 (Value::I16(a), Value::I16(b)) => a.partial_cmp(b),
475 (Value::I32(a), Value::I32(b)) => a.partial_cmp(b),
476 (Value::I64(a), Value::I64(b)) => a.partial_cmp(b),
477
478 (Value::U8(a), Value::U8(b)) => a.partial_cmp(b),
480 (Value::U16(a), Value::U16(b)) => a.partial_cmp(b),
481 (Value::U32(a), Value::U32(b)) => a.partial_cmp(b),
482 (Value::U64(a), Value::U64(b)) => a.partial_cmp(b),
483
484 (Value::F32(a), Value::F32(b)) => a.partial_cmp(b),
486 (Value::F64(a), Value::F64(b)) => a.partial_cmp(b),
487
488 (Value::String(a), Value::String(b)) => a.partial_cmp(b),
490
491 (Value::Bytes(a), Value::Bytes(b)) => a.partial_cmp(b),
493
494 (Value::Uuid(a), Value::Uuid(b)) => a.partial_cmp(b),
496
497 #[cfg(feature = "rust_decimal")]
499 (Value::Decimal(a), Value::Decimal(b)) => a.partial_cmp(b),
500
501 #[cfg(feature = "bigdecimal")]
503 (Value::BigDecimal(a), Value::BigDecimal(b)) => a.partial_cmp(b),
504
505 #[cfg(feature = "jiff")]
507 (Value::Timestamp(a), Value::Timestamp(b)) => a.partial_cmp(b),
508 #[cfg(feature = "jiff")]
509 (Value::Zoned(a), Value::Zoned(b)) => a.partial_cmp(b),
510 #[cfg(feature = "jiff")]
511 (Value::Date(a), Value::Date(b)) => a.partial_cmp(b),
512 #[cfg(feature = "jiff")]
513 (Value::Time(a), Value::Time(b)) => a.partial_cmp(b),
514 #[cfg(feature = "jiff")]
515 (Value::DateTime(a), Value::DateTime(b)) => a.partial_cmp(b),
516
517 _ => None,
519 }
520 }
521}
522
523impl From<bool> for Value {
524 fn from(src: bool) -> Self {
525 Self::Bool(src)
526 }
527}
528
529impl TryFrom<Value> for bool {
530 type Error = crate::Error;
531
532 fn try_from(value: Value) -> Result<Self, Self::Error> {
533 match value {
534 Value::Bool(v) => Ok(v),
535 _ => Err(crate::Error::type_conversion(value, "bool")),
536 }
537 }
538}
539
540impl From<String> for Value {
541 fn from(src: String) -> Self {
542 Self::String(src)
543 }
544}
545
546impl From<&String> for Value {
547 fn from(src: &String) -> Self {
548 Self::String(src.clone())
549 }
550}
551
552impl From<&str> for Value {
553 fn from(src: &str) -> Self {
554 Self::String(src.to_string())
555 }
556}
557
558impl From<ValueRecord> for Value {
559 fn from(value: ValueRecord) -> Self {
560 Self::Record(value)
561 }
562}
563
564impl<T> From<Option<T>> for Value
565where
566 Self: From<T>,
567{
568 fn from(value: Option<T>) -> Self {
569 match value {
570 Some(value) => Self::from(value),
571 None => Self::Null,
572 }
573 }
574}
575
576impl TryFrom<Value> for String {
577 type Error = crate::Error;
578
579 fn try_from(value: Value) -> Result<Self, Self::Error> {
580 match value {
581 Value::String(v) => Ok(v),
582 _ => Err(crate::Error::type_conversion(value, "String")),
583 }
584 }
585}
586
587impl From<Vec<u8>> for Value {
588 fn from(value: Vec<u8>) -> Self {
589 Self::Bytes(value)
590 }
591}
592
593impl TryFrom<Value> for Vec<u8> {
594 type Error = crate::Error;
595
596 fn try_from(value: Value) -> Result<Self, Self::Error> {
597 match value {
598 Value::Bytes(v) => Ok(v),
599 _ => Err(crate::Error::type_conversion(value, "Bytes")),
600 }
601 }
602}
603
604impl From<uuid::Uuid> for Value {
605 fn from(value: uuid::Uuid) -> Self {
606 Self::Uuid(value)
607 }
608}
609
610impl TryFrom<Value> for uuid::Uuid {
611 type Error = crate::Error;
612
613 fn try_from(value: Value) -> Result<Self, Self::Error> {
614 match value {
615 Value::Uuid(v) => Ok(v),
616 _ => Err(crate::Error::type_conversion(value, "uuid::Uuid")),
617 }
618 }
619}
620
621#[cfg(feature = "rust_decimal")]
622impl From<rust_decimal::Decimal> for Value {
623 fn from(value: rust_decimal::Decimal) -> Self {
624 Self::Decimal(value)
625 }
626}
627
628#[cfg(feature = "rust_decimal")]
629impl TryFrom<Value> for rust_decimal::Decimal {
630 type Error = crate::Error;
631
632 fn try_from(value: Value) -> Result<Self, Self::Error> {
633 match value {
634 Value::Decimal(v) => Ok(v),
635 _ => Err(crate::Error::type_conversion(
636 value,
637 "rust_decimal::Decimal",
638 )),
639 }
640 }
641}
642
643#[cfg(feature = "bigdecimal")]
644impl From<bigdecimal::BigDecimal> for Value {
645 fn from(value: bigdecimal::BigDecimal) -> Self {
646 Self::BigDecimal(value)
647 }
648}
649
650#[cfg(feature = "bigdecimal")]
651impl TryFrom<Value> for bigdecimal::BigDecimal {
652 type Error = crate::Error;
653
654 fn try_from(value: Value) -> Result<Self, Self::Error> {
655 match value {
656 Value::BigDecimal(v) => Ok(v),
657 _ => Err(crate::Error::type_conversion(
658 value,
659 "bigdecimal::BigDecimal",
660 )),
661 }
662 }
663}