1pub mod array;
3pub mod bytes;
5pub mod datetime;
7pub mod duration;
9pub mod file;
11mod format;
12pub mod geometry;
14pub mod into_json;
16pub mod number;
18pub mod object;
20pub mod range;
22pub mod record_id;
24pub mod regex;
26pub mod set;
28pub mod table;
30pub mod uuid;
32
33use std::cmp::Ordering;
34use std::ops::Index;
35
36pub use rust_decimal::Decimal;
37use serde::{Deserialize, Serialize};
38
39pub use self::array::Array;
40pub use self::bytes::Bytes;
41pub use self::datetime::Datetime;
42pub use self::duration::Duration;
43pub use self::file::File;
44pub use self::geometry::Geometry;
45pub use self::number::Number;
46pub use self::object::Object;
47pub use self::range::Range;
48pub use self::record_id::{RecordId, RecordIdKey, RecordIdKeyRange};
49pub use self::regex::Regex;
50pub use self::set::Set;
51pub use self::table::Table;
52pub use self::uuid::Uuid;
53use crate::sql::{SqlFormat, ToSql};
54use crate::utils::escape::QuoteStr;
55use crate::{Kind, SurrealValue};
56
57#[derive(
62 Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize,
63)]
64#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
65pub struct SurrealNone;
66
67#[derive(
72 Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize,
73)]
74#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
75pub struct SurrealNull;
76
77#[derive(Clone, Debug, Default, Hash, PartialEq, Serialize, Deserialize)]
83#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
84pub enum Value {
85 #[default]
87 None,
88 Null,
90 Bool(bool),
92 Number(Number),
94 String(String),
96 Bytes(Bytes),
98 Duration(Duration),
100 Datetime(Datetime),
102 Uuid(Uuid),
104 Geometry(Geometry),
106 Table(Table),
108 RecordId(RecordId),
110 File(File),
112 Range(Box<Range>),
114 Regex(Regex),
116 Array(Array),
118 Object(Object),
120 Set(Set),
122}
123
124impl Eq for Value {}
125
126impl PartialOrd for Value {
127 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
128 Some(self.cmp(other))
129 }
130}
131
132impl Ord for Value {
133 fn cmp(&self, other: &Self) -> Ordering {
134 match (self, other) {
135 (Value::None, Value::None) => Ordering::Equal,
137 (Value::Null, Value::Null) => Ordering::Equal,
138 (Value::Bool(a), Value::Bool(b)) => a.cmp(b),
139 (Value::Number(a), Value::Number(b)) => a.cmp(b),
140 (Value::String(a), Value::String(b)) => a.cmp(b),
141 (Value::Duration(a), Value::Duration(b)) => a.cmp(b),
142 (Value::Datetime(a), Value::Datetime(b)) => a.cmp(b),
143 (Value::Uuid(a), Value::Uuid(b)) => a.cmp(b),
144 (Value::Array(a), Value::Array(b)) => a.cmp(b),
145 (Value::Set(a), Value::Set(b)) => a.cmp(b),
146 (Value::Object(a), Value::Object(b)) => a.cmp(b),
147 (Value::Geometry(a), Value::Geometry(b)) => a.partial_cmp(b).unwrap_or(Ordering::Equal),
148 (Value::Bytes(a), Value::Bytes(b)) => a.cmp(b),
149 (Value::Table(a), Value::Table(b)) => a.cmp(b),
150 (Value::RecordId(a), Value::RecordId(b)) => a.cmp(b),
151 (Value::File(a), Value::File(b)) => a.cmp(b),
152 (Value::Range(a), Value::Range(b)) => a.cmp(b),
153 (Value::Regex(a), Value::Regex(b)) => a.cmp(b),
154
155 (Value::None, _) => Ordering::Less,
159 (_, Value::None) => Ordering::Greater,
160
161 (Value::Null, _) => Ordering::Less,
162 (_, Value::Null) => Ordering::Greater,
163
164 (
165 Value::Bool(_),
166 Value::Number(_)
167 | Value::String(_)
168 | Value::Duration(_)
169 | Value::Datetime(_)
170 | Value::Uuid(_)
171 | Value::Array(_)
172 | Value::Set(_)
173 | Value::Object(_)
174 | Value::Geometry(_)
175 | Value::Bytes(_)
176 | Value::Table(_)
177 | Value::RecordId(_)
178 | Value::File(_)
179 | Value::Range(_)
180 | Value::Regex(_),
181 ) => Ordering::Less,
182 (
183 Value::Number(_)
184 | Value::String(_)
185 | Value::Duration(_)
186 | Value::Datetime(_)
187 | Value::Uuid(_)
188 | Value::Array(_)
189 | Value::Set(_)
190 | Value::Object(_)
191 | Value::Geometry(_)
192 | Value::Bytes(_)
193 | Value::Table(_)
194 | Value::RecordId(_)
195 | Value::File(_)
196 | Value::Range(_)
197 | Value::Regex(_),
198 Value::Bool(_),
199 ) => Ordering::Greater,
200
201 (
202 Value::Number(_),
203 Value::String(_)
204 | Value::Duration(_)
205 | Value::Datetime(_)
206 | Value::Uuid(_)
207 | Value::Array(_)
208 | Value::Set(_)
209 | Value::Object(_)
210 | Value::Geometry(_)
211 | Value::Bytes(_)
212 | Value::Table(_)
213 | Value::RecordId(_)
214 | Value::File(_)
215 | Value::Range(_)
216 | Value::Regex(_),
217 ) => Ordering::Less,
218 (
219 Value::String(_)
220 | Value::Duration(_)
221 | Value::Datetime(_)
222 | Value::Uuid(_)
223 | Value::Array(_)
224 | Value::Set(_)
225 | Value::Object(_)
226 | Value::Geometry(_)
227 | Value::Bytes(_)
228 | Value::Table(_)
229 | Value::RecordId(_)
230 | Value::File(_)
231 | Value::Range(_)
232 | Value::Regex(_),
233 Value::Number(_),
234 ) => Ordering::Greater,
235
236 (
237 Value::String(_),
238 Value::Duration(_)
239 | Value::Datetime(_)
240 | Value::Uuid(_)
241 | Value::Array(_)
242 | Value::Set(_)
243 | Value::Object(_)
244 | Value::Geometry(_)
245 | Value::Bytes(_)
246 | Value::Table(_)
247 | Value::RecordId(_)
248 | Value::File(_)
249 | Value::Range(_)
250 | Value::Regex(_),
251 ) => Ordering::Less,
252 (
253 Value::Duration(_)
254 | Value::Datetime(_)
255 | Value::Uuid(_)
256 | Value::Array(_)
257 | Value::Set(_)
258 | Value::Object(_)
259 | Value::Geometry(_)
260 | Value::Bytes(_)
261 | Value::Table(_)
262 | Value::RecordId(_)
263 | Value::File(_)
264 | Value::Range(_)
265 | Value::Regex(_),
266 Value::String(_),
267 ) => Ordering::Greater,
268
269 (
270 Value::Duration(_),
271 Value::Datetime(_)
272 | Value::Uuid(_)
273 | Value::Array(_)
274 | Value::Set(_)
275 | Value::Object(_)
276 | Value::Geometry(_)
277 | Value::Bytes(_)
278 | Value::Table(_)
279 | Value::RecordId(_)
280 | Value::File(_)
281 | Value::Range(_)
282 | Value::Regex(_),
283 ) => Ordering::Less,
284 (
285 Value::Datetime(_)
286 | Value::Uuid(_)
287 | Value::Array(_)
288 | Value::Set(_)
289 | Value::Object(_)
290 | Value::Geometry(_)
291 | Value::Bytes(_)
292 | Value::Table(_)
293 | Value::RecordId(_)
294 | Value::File(_)
295 | Value::Range(_)
296 | Value::Regex(_),
297 Value::Duration(_),
298 ) => Ordering::Greater,
299
300 (
301 Value::Datetime(_),
302 Value::Uuid(_)
303 | Value::Array(_)
304 | Value::Set(_)
305 | Value::Object(_)
306 | Value::Geometry(_)
307 | Value::Bytes(_)
308 | Value::Table(_)
309 | Value::RecordId(_)
310 | Value::File(_)
311 | Value::Range(_)
312 | Value::Regex(_),
313 ) => Ordering::Less,
314 (
315 Value::Uuid(_)
316 | Value::Array(_)
317 | Value::Set(_)
318 | Value::Object(_)
319 | Value::Geometry(_)
320 | Value::Bytes(_)
321 | Value::Table(_)
322 | Value::RecordId(_)
323 | Value::File(_)
324 | Value::Range(_)
325 | Value::Regex(_),
326 Value::Datetime(_),
327 ) => Ordering::Greater,
328
329 (
330 Value::Uuid(_),
331 Value::Array(_)
332 | Value::Set(_)
333 | Value::Object(_)
334 | Value::Geometry(_)
335 | Value::Bytes(_)
336 | Value::Table(_)
337 | Value::RecordId(_)
338 | Value::File(_)
339 | Value::Range(_)
340 | Value::Regex(_),
341 ) => Ordering::Less,
342 (
343 Value::Array(_)
344 | Value::Set(_)
345 | Value::Object(_)
346 | Value::Geometry(_)
347 | Value::Bytes(_)
348 | Value::Table(_)
349 | Value::RecordId(_)
350 | Value::File(_)
351 | Value::Range(_)
352 | Value::Regex(_),
353 Value::Uuid(_),
354 ) => Ordering::Greater,
355
356 (
357 Value::Array(_),
358 Value::Object(_)
359 | Value::Geometry(_)
360 | Value::Bytes(_)
361 | Value::Table(_)
362 | Value::RecordId(_)
363 | Value::File(_)
364 | Value::Range(_)
365 | Value::Regex(_)
366 | Value::Set(_),
367 ) => Ordering::Less,
368 (
369 Value::Object(_)
370 | Value::Geometry(_)
371 | Value::Bytes(_)
372 | Value::Table(_)
373 | Value::RecordId(_)
374 | Value::File(_)
375 | Value::Range(_)
376 | Value::Regex(_)
377 | Value::Set(_),
378 Value::Array(_),
379 ) => Ordering::Greater,
380
381 (
382 Value::Set(_),
383 Value::Object(_)
384 | Value::Geometry(_)
385 | Value::Bytes(_)
386 | Value::Table(_)
387 | Value::RecordId(_)
388 | Value::File(_)
389 | Value::Range(_)
390 | Value::Regex(_),
391 ) => Ordering::Less,
392 (
393 Value::Object(_)
394 | Value::Geometry(_)
395 | Value::Bytes(_)
396 | Value::Table(_)
397 | Value::RecordId(_)
398 | Value::File(_)
399 | Value::Range(_)
400 | Value::Regex(_),
401 Value::Set(_),
402 ) => Ordering::Greater,
403
404 (
405 Value::Object(_),
406 Value::Geometry(_)
407 | Value::Bytes(_)
408 | Value::Table(_)
409 | Value::RecordId(_)
410 | Value::File(_)
411 | Value::Range(_)
412 | Value::Regex(_),
413 ) => Ordering::Less,
414 (
415 Value::Geometry(_)
416 | Value::Bytes(_)
417 | Value::Table(_)
418 | Value::RecordId(_)
419 | Value::File(_)
420 | Value::Range(_)
421 | Value::Regex(_),
422 Value::Object(_),
423 ) => Ordering::Greater,
424
425 (
426 Value::Geometry(_),
427 Value::Bytes(_)
428 | Value::Table(_)
429 | Value::RecordId(_)
430 | Value::File(_)
431 | Value::Range(_)
432 | Value::Regex(_),
433 ) => Ordering::Less,
434 (
435 Value::Bytes(_)
436 | Value::Table(_)
437 | Value::RecordId(_)
438 | Value::File(_)
439 | Value::Range(_)
440 | Value::Regex(_),
441 Value::Geometry(_),
442 ) => Ordering::Greater,
443
444 (
445 Value::Bytes(_),
446 Value::Table(_)
447 | Value::RecordId(_)
448 | Value::File(_)
449 | Value::Range(_)
450 | Value::Regex(_),
451 ) => Ordering::Less,
452 (
453 Value::Table(_)
454 | Value::RecordId(_)
455 | Value::File(_)
456 | Value::Range(_)
457 | Value::Regex(_),
458 Value::Bytes(_),
459 ) => Ordering::Greater,
460
461 (Value::Table(t), Value::RecordId(record_id)) => t.cmp(&record_id.table),
462 (Value::RecordId(record_id), Value::Table(t)) => record_id.table.cmp(t),
463
464 (Value::Table(_), Value::File(_) | Value::Range(_) | Value::Regex(_)) => Ordering::Less,
465 (Value::File(_) | Value::Range(_) | Value::Regex(_), Value::Table(_)) => {
466 Ordering::Greater
467 }
468
469 (Value::RecordId(_), Value::File(_) | Value::Range(_) | Value::Regex(_)) => {
470 Ordering::Less
471 }
472 (Value::File(_) | Value::Range(_) | Value::Regex(_), Value::RecordId(_)) => {
473 Ordering::Greater
474 }
475
476 (Value::File(_), Value::Range(_) | Value::Regex(_)) => Ordering::Less,
477 (Value::Range(_) | Value::Regex(_), Value::File(_)) => Ordering::Greater,
478
479 (Value::Range(_), Value::Regex(_)) => Ordering::Less,
480 (Value::Regex(_), Value::Range(_)) => Ordering::Greater,
481 }
482 }
483}
484
485impl Value {
486 pub fn kind(&self) -> Kind {
490 match self {
491 Value::None => Kind::None,
492 Value::Null => Kind::Null,
493 Value::Bool(_) => Kind::Bool,
494 Value::Number(_) => Kind::Number,
495 Value::String(_) => Kind::String,
496 Value::Duration(_) => Kind::Duration,
497 Value::Datetime(_) => Kind::Datetime,
498 Value::Uuid(_) => Kind::Uuid,
499 Value::Array(_) => Kind::Array(Box::new(Kind::Any), None),
500 Value::Set(_) => Kind::Set(Box::new(Kind::Any), None),
501 Value::Object(_) => Kind::Object,
502 Value::Geometry(_) => Kind::Geometry(Vec::new()),
503 Value::Bytes(_) => Kind::Bytes,
504 Value::Table(_) => Kind::Table(Vec::new()),
505 Value::RecordId(_) => Kind::Record(Vec::new()),
506 Value::File(_) => Kind::File(Vec::new()),
507 Value::Range(_) => Kind::Range,
508 Value::Regex(_) => Kind::Regex,
509 }
510 }
511
512 pub fn first(&self) -> Option<Value> {
516 match self {
517 Value::Array(arr) => arr.first().cloned(),
518 _ => None,
519 }
520 }
521
522 pub fn is_nullish(&self) -> bool {
524 matches!(self, Value::None | Value::Null)
525 }
526
527 pub fn is_empty(&self) -> bool {
529 match self {
530 Value::None => true,
531 Value::Null => true,
532 Value::String(s) => s.is_empty(),
533 Value::Bytes(b) => b.is_empty(),
534 Value::Object(obj) => obj.is_empty(),
535 Value::Array(arr) => arr.is_empty(),
536 Value::Set(set) => set.is_empty(),
537 _ => false,
538 }
539 }
540
541 pub fn get<Idx>(&self, index: Idx) -> &Value
548 where
549 Value: Indexable<Idx>,
550 {
551 Indexable::get(self, index)
552 }
553
554 pub fn remove<Idx>(&mut self, index: Idx) -> Value
558 where
559 Value: Indexable<Idx>,
560 {
561 Indexable::remove(self, index)
562 }
563
564 pub fn is<T: SurrealValue>(&self) -> bool {
568 T::is_value(self)
569 }
570
571 pub fn into_t<T: SurrealValue>(self) -> Result<T, crate::Error> {
575 T::from_value(self)
576 }
577
578 pub fn from_t<T: SurrealValue>(value: T) -> Value {
582 value.into_value()
583 }
584
585 pub fn is_kind(&self, kind: &Kind) -> bool {
590 match kind {
591 Kind::Any => true,
592 Kind::None => self.is_none(),
593 Kind::Null => self.is_null(),
594 Kind::Bool => self.is_bool(),
595 Kind::Bytes => self.is_bytes(),
596 Kind::Datetime => self.is_datetime(),
597 Kind::Decimal => self.is_decimal(),
598 Kind::Duration => self.is_duration(),
599 Kind::Float => self.is_float(),
600 Kind::Int => self.is_int(),
601 Kind::Number => self.is_number(),
602 Kind::Object => self.is_object(),
603 Kind::String => self.is_string(),
604 Kind::Uuid => self.is_uuid(),
605 Kind::Regex => matches!(self, Value::Regex(_)),
606 Kind::Table(table) => self.is_table_and(|t| table.is_empty() || table.contains(t)),
607 Kind::Record(table) => self.is_record_and(|r| r.is_table_type(table)),
608 Kind::Geometry(kinds) => {
609 self.is_geometry_and(|g| kinds.is_empty() || kinds.contains(&g.kind()))
610 }
611 Kind::Either(kinds) => kinds.iter().any(|k| self.is_kind(k)),
612 Kind::Set(kind, max) => {
613 self.is_set_and(|set| {
614 if let Some(max_len) = max
616 && set.len() > *max_len as usize
617 {
618 return false;
619 }
620 set.iter().all(|v| v.is_kind(kind))
622 })
623 }
624 Kind::Array(kind, max) => {
625 self.is_array_and(|arr| {
626 if let Some(max_len) = max
628 && arr.len() > *max_len as usize
629 {
630 return false;
631 }
632 arr.iter().all(|v| v.is_kind(kind))
634 })
635 }
636 Kind::Range => self.is_range(),
637 Kind::Literal(literal) => literal.matches(self),
638 Kind::File(bucket) => {
639 self.is_file_and(|f| bucket.is_empty() || bucket.contains(&f.bucket().to_string()))
640 }
641 Kind::Function(_, _) => {
642 false
644 }
645 }
646 }
647}
648
649impl Index<usize> for Value {
650 type Output = Self;
651
652 fn index(&self, index: usize) -> &Self::Output {
653 match &self {
654 Value::Array(map) => map.0.get(index).unwrap_or(&Value::None),
655 _ => &Value::None,
656 }
657 }
658}
659
660impl Index<&str> for Value {
661 type Output = Self;
662
663 fn index(&self, index: &str) -> &Self::Output {
664 match &self {
665 Value::Object(map) => map.0.get(index).unwrap_or(&Value::None),
666 _ => &Value::None,
667 }
668 }
669}
670
671impl PartialEq<&Value> for Value {
672 fn eq(&self, other: &&Value) -> bool {
673 self == *other
674 }
675}
676
677impl PartialEq<Value> for &Value {
678 fn eq(&self, other: &Value) -> bool {
679 **self == *other
680 }
681}
682
683pub trait Indexable<Idx> {
685 fn get(&self, index: Idx) -> &Value;
687 fn remove(&mut self, index: Idx) -> Value;
689}
690
691impl Indexable<usize> for Value {
692 fn get(&self, index: usize) -> &Value {
693 match self {
694 Value::Array(arr) => arr.index(index),
695 _ => &Value::None,
696 }
697 }
698 fn remove(&mut self, index: usize) -> Value {
699 match self {
700 Value::Array(arr) => arr.remove(index),
701 _ => Value::None,
702 }
703 }
704}
705
706impl Indexable<&str> for Value {
707 fn get(&self, index: &str) -> &Value {
708 match self {
709 Value::Object(obj) => match obj.get(index) {
710 Some(v) => v,
711 None => &Value::None,
712 },
713 _ => &Value::None,
714 }
715 }
716
717 fn remove(&mut self, index: &str) -> Value {
718 match self {
719 Value::Object(obj) => match obj.remove(index) {
720 Some(v) => v,
721 None => Value::None,
722 },
723 _ => Value::None,
724 }
725 }
726}
727
728impl FromIterator<Value> for Value {
729 fn from_iter<I: IntoIterator<Item = Value>>(iter: I) -> Self {
730 Value::Array(Array::from_iter(iter))
731 }
732}
733
734impl From<Object> for Value {
735 fn from(o: Object) -> Self {
736 Value::Object(o)
737 }
738}
739
740impl ToSql for Value {
741 fn fmt_sql(&self, f: &mut String, fmt: SqlFormat) {
742 match self {
743 Value::None => f.push_str("NONE"),
744 Value::Null => f.push_str("NULL"),
745 Value::Bool(v) => v.fmt_sql(f, fmt),
746 Value::Number(v) => v.fmt_sql(f, fmt),
747 Value::String(v) => {
748 QuoteStr(v.as_str()).fmt_sql(f, fmt);
749 }
750 Value::Duration(v) => v.fmt_sql(f, fmt),
751 Value::Datetime(v) => v.fmt_sql(f, fmt),
752 Value::Uuid(v) => v.fmt_sql(f, fmt),
753 Value::Array(v) => v.fmt_sql(f, fmt),
754 Value::Object(v) => v.fmt_sql(f, fmt),
755 Value::Geometry(v) => v.fmt_sql(f, fmt),
756 Value::Bytes(v) => v.fmt_sql(f, fmt),
757 Value::Table(v) => v.fmt_sql(f, fmt),
758 Value::RecordId(v) => v.fmt_sql(f, fmt),
759 Value::File(v) => v.fmt_sql(f, fmt),
760 Value::Range(v) => v.fmt_sql(f, fmt),
761 Value::Regex(v) => v.fmt_sql(f, fmt),
762 Value::Set(v) => v.fmt_sql(f, fmt),
763 }
764 }
765}
766
767#[cfg(test)]
768mod tests {
769 use std::collections::BTreeMap;
770
771 use rstest::rstest;
772
773 use super::*;
774 use crate::{GeometryKind, Kind, KindLiteral, object};
775
776 #[rstest]
777 #[case::none(Value::None, true)]
778 #[case::null(Value::Null, true)]
779 #[case::string(Value::String("".to_string()), true)]
780 #[case::string(Value::String("hello".to_string()), false)]
781 #[case::bytes(Value::Bytes(Bytes::default()), true)]
782 #[case::bytes(Value::Bytes(Bytes::from(::bytes::Bytes::from(vec![1_u8, 2, 3]))), false)]
783 #[case::object(Value::Object(Object::default()), true)]
784 #[case::object(Value::Object(Object::from_iter([("key".to_string(), Value::String("value".to_string()))])), false)]
785 #[case::array(Value::Array(Array::new()), true)]
786 #[case::array(Value::Array(Array::from(vec![Value::String("hello".to_string())])), false)]
787 #[case::geometry(Value::Geometry(Geometry::Point(geo::Point::new(1.0, 2.0))), false)]
788 #[case::record_id(Value::RecordId(RecordId::new("test", "key")), false)]
789 #[case::file(Value::File(File::default()), false)]
790 #[case::range(Value::Range(Box::new(Range::unbounded())), false)]
791 #[case::regex(Value::Regex("hello".parse().unwrap()), false)]
792 #[case::duration(Value::Duration(Duration::new(1, 0)), false)]
793 #[case::datetime(Value::Datetime(Datetime::from_timestamp(1, 0).unwrap()), false)]
794 #[case::uuid(Value::Uuid(Uuid::new_v4()), false)]
795 #[case::bool(Value::Bool(true), false)]
796 #[case::bool(Value::Bool(false), false)]
797 #[case::number(Value::Number(Number::Int(1)), false)]
798 #[case::number(Value::Number(Number::Float(1.0)), false)]
799 #[case::number(Value::Number(Number::Decimal(Decimal::new(1, 0))), false)]
800 fn test_is_empty(#[case] value: Value, #[case] expected: bool) {
801 assert_eq!(value.is_empty(), expected);
802 }
803
804 #[rstest]
806 #[case::none_eq_none(Value::None, Value::None, Ordering::Equal)]
807 #[case::null_eq_null(Value::Null, Value::Null, Ordering::Equal)]
808 #[case::bool_false_lt_true(Value::Bool(false), Value::Bool(true), Ordering::Less)]
809 #[case::bool_true_gt_false(Value::Bool(true), Value::Bool(false), Ordering::Greater)]
810 #[case::bool_true_eq_true(Value::Bool(true), Value::Bool(true), Ordering::Equal)]
811 #[case::string_a_lt_b(Value::String("a".to_string()), Value::String("b".to_string()), Ordering::Less)]
812 #[case::string_b_gt_a(Value::String("b".to_string()), Value::String("a".to_string()), Ordering::Greater)]
813 #[case::string_a_eq_a(Value::String("a".to_string()), Value::String("a".to_string()), Ordering::Equal)]
814 fn test_value_ordering_same_variant(
815 #[case] left: Value,
816 #[case] right: Value,
817 #[case] expected: Ordering,
818 ) {
819 assert_eq!(left.cmp(&right), expected);
820 assert_eq!(left.partial_cmp(&right), Some(expected));
821 }
822
823 #[rstest]
825 #[case::int_0_lt_int_1(
826 Value::Number(Number::Int(0)),
827 Value::Number(Number::Int(1)),
828 Ordering::Less
829 )]
830 #[case::int_1_gt_int_0(
831 Value::Number(Number::Int(1)),
832 Value::Number(Number::Int(0)),
833 Ordering::Greater
834 )]
835 #[case::int_5_eq_int_5(
836 Value::Number(Number::Int(5)),
837 Value::Number(Number::Int(5)),
838 Ordering::Equal
839 )]
840 #[case::float_0_lt_float_1(
841 Value::Number(Number::Float(0.0)),
842 Value::Number(Number::Float(1.0)),
843 Ordering::Less
844 )]
845 #[case::int_5_lt_float_5_5(
846 Value::Number(Number::Int(5)),
847 Value::Number(Number::Float(5.5)),
848 Ordering::Less
849 )]
850 #[case::int_5_eq_float_5(
851 Value::Number(Number::Int(5)),
852 Value::Number(Number::Float(5.0)),
853 Ordering::Equal
854 )]
855 #[case::float_5_eq_int_5(
856 Value::Number(Number::Float(5.0)),
857 Value::Number(Number::Int(5)),
858 Ordering::Equal
859 )]
860 #[case::int_10_gt_float_9_9(
861 Value::Number(Number::Int(10)),
862 Value::Number(Number::Float(9.9)),
863 Ordering::Greater
864 )]
865 #[case::decimal_5_eq_int_5(
866 Value::Number(Number::Decimal(Decimal::new(5, 0))),
867 Value::Number(Number::Int(5)),
868 Ordering::Equal
869 )]
870 #[case::int_5_eq_decimal_5(
871 Value::Number(Number::Int(5)),
872 Value::Number(Number::Decimal(Decimal::new(5, 0))),
873 Ordering::Equal
874 )]
875 #[case::decimal_5_5_gt_int_5(
876 Value::Number(Number::Decimal(Decimal::new(55, 1))), Value::Number(Number::Int(5)),
878 Ordering::Greater
879 )]
880 fn test_value_ordering_numbers(
881 #[case] left: Value,
882 #[case] right: Value,
883 #[case] expected: Ordering,
884 ) {
885 assert_eq!(left.cmp(&right), expected);
886 assert_eq!(left.partial_cmp(&right), Some(expected));
887 }
888
889 #[rstest]
893 #[case::none_lt_null(Value::None, Value::Null, Ordering::Less)]
894 #[case::null_gt_none(Value::Null, Value::None, Ordering::Greater)]
895 #[case::null_lt_bool(Value::Null, Value::Bool(false), Ordering::Less)]
896 #[case::bool_gt_null(Value::Bool(true), Value::Null, Ordering::Greater)]
897 #[case::bool_lt_number(Value::Bool(true), Value::Number(Number::Int(0)), Ordering::Less)]
898 #[case::number_gt_bool(Value::Number(Number::Int(100)), Value::Bool(true), Ordering::Greater)]
899 #[case::number_lt_string(
900 Value::Number(Number::Int(100)),
901 Value::String("a".to_string()),
902 Ordering::Less
903 )]
904 #[case::string_gt_number(
905 Value::String("a".to_string()),
906 Value::Number(Number::Int(100)),
907 Ordering::Greater
908 )]
909 #[case::string_lt_duration(
910 Value::String("z".to_string()),
911 Value::Duration(Duration::new(1, 0)),
912 Ordering::Less
913 )]
914 #[case::duration_gt_string(
915 Value::Duration(Duration::new(1, 0)),
916 Value::String("z".to_string()),
917 Ordering::Greater
918 )]
919 #[case::duration_lt_datetime(
920 Value::Duration(Duration::new(100, 0)),
921 Value::Datetime(Datetime::from_timestamp(1, 0).unwrap()),
922 Ordering::Less
923 )]
924 #[case::datetime_gt_duration(
925 Value::Datetime(Datetime::from_timestamp(1, 0).unwrap()),
926 Value::Duration(Duration::new(100, 0)),
927 Ordering::Greater
928 )]
929 #[case::datetime_lt_uuid(
930 Value::Datetime(Datetime::from_timestamp(1000000, 0).unwrap()),
931 Value::Uuid(Uuid::new_v4()),
932 Ordering::Less
933 )]
934 #[case::uuid_gt_datetime(
935 Value::Uuid(Uuid::new_v4()),
936 Value::Datetime(Datetime::from_timestamp(1000000, 0).unwrap()),
937 Ordering::Greater
938 )]
939 #[case::uuid_lt_array(Value::Uuid(Uuid::new_v4()), Value::Array(Array::new()), Ordering::Less)]
940 #[case::array_gt_uuid(
941 Value::Array(Array::new()),
942 Value::Uuid(Uuid::new_v4()),
943 Ordering::Greater
944 )]
945 #[case::array_lt_object(
946 Value::Array(Array::new()),
947 Value::Object(Object::default()),
948 Ordering::Less
949 )]
950 #[case::object_gt_array(
951 Value::Object(Object::default()),
952 Value::Array(Array::new()),
953 Ordering::Greater
954 )]
955 #[case::object_lt_geometry(
956 Value::Object(Object::default()),
957 Value::Geometry(Geometry::Point(geo::Point::new(1.0, 2.0))),
958 Ordering::Less
959 )]
960 #[case::geometry_gt_object(
961 Value::Geometry(Geometry::Point(geo::Point::new(1.0, 2.0))),
962 Value::Object(Object::default()),
963 Ordering::Greater
964 )]
965 #[case::geometry_lt_bytes(
966 Value::Geometry(Geometry::Point(geo::Point::new(1.0, 2.0))),
967 Value::Bytes(Bytes::default()),
968 Ordering::Less
969 )]
970 #[case::bytes_gt_geometry(
971 Value::Bytes(Bytes::default()),
972 Value::Geometry(Geometry::Point(geo::Point::new(1.0, 2.0))),
973 Ordering::Greater
974 )]
975 #[case::bytes_lt_record(
976 Value::Bytes(Bytes::default()),
977 Value::RecordId(RecordId::new("test", "key")),
978 Ordering::Less
979 )]
980 #[case::record_gt_bytes(
981 Value::RecordId(RecordId::new("test", "key")),
982 Value::Bytes(Bytes::default()),
983 Ordering::Greater
984 )]
985 #[case::record_lt_file(
986 Value::RecordId(RecordId::new("test", "key")),
987 Value::File(File::default()),
988 Ordering::Less
989 )]
990 #[case::file_gt_record(
991 Value::File(File::default()),
992 Value::RecordId(RecordId::new("test", "key")),
993 Ordering::Greater
994 )]
995 #[case::file_lt_range(
996 Value::File(File::default()),
997 Value::Range(Box::new(Range::unbounded())),
998 Ordering::Less
999 )]
1000 #[case::range_gt_file(
1001 Value::Range(Box::new(Range::unbounded())),
1002 Value::File(File::default()),
1003 Ordering::Greater
1004 )]
1005 #[case::range_lt_regex(
1006 Value::Range(Box::new(Range::unbounded())),
1007 Value::Regex("test".parse().unwrap()),
1008 Ordering::Less
1009 )]
1010 #[case::regex_gt_range(
1011 Value::Regex("test".parse().unwrap()),
1012 Value::Range(Box::new(Range::unbounded())),
1013 Ordering::Greater
1014 )]
1015 fn test_value_ordering_cross_variant(
1016 #[case] left: Value,
1017 #[case] right: Value,
1018 #[case] expected: Ordering,
1019 ) {
1020 assert_eq!(left.cmp(&right), expected);
1021 assert_eq!(left.partial_cmp(&right), Some(expected));
1022 }
1023
1024 #[rstest]
1026 #[case::int_eq_float(Value::Number(Number::Int(5)), Value::Number(Number::Float(5.0)))]
1027 #[case::float_eq_int(Value::Number(Number::Float(5.0)), Value::Number(Number::Int(5)))]
1028 #[case::int_eq_decimal(
1029 Value::Number(Number::Int(5)),
1030 Value::Number(Number::Decimal(Decimal::new(5, 0)))
1031 )]
1032 #[case::decimal_eq_int(
1033 Value::Number(Number::Decimal(Decimal::new(5, 0))),
1034 Value::Number(Number::Int(5))
1035 )]
1036 #[case::none_eq_none(Value::None, Value::None)]
1037 #[case::null_eq_null(Value::Null, Value::Null)]
1038 fn test_value_equality(#[case] left: Value, #[case] right: Value) {
1039 assert_eq!(left, right);
1040 assert_eq!(right, left);
1041 assert_eq!(left.cmp(&right), Ordering::Equal);
1042 }
1043
1044 #[rstest]
1046 #[case::none_ne_null(Value::None, Value::Null)]
1047 #[case::int_ne_float(Value::Number(Number::Int(5)), Value::Number(Number::Float(5.5)))]
1048 #[case::bool_ne_number(Value::Bool(true), Value::Number(Number::Int(1)))]
1049 #[case::string_ne_number(Value::String("5".to_string()), Value::Number(Number::Int(5)))]
1050 fn test_value_inequality(#[case] left: Value, #[case] right: Value) {
1051 assert_ne!(left, right);
1052 assert_ne!(right, left);
1053 assert_ne!(left.cmp(&right), Ordering::Equal);
1054 }
1055
1056 #[test]
1058 fn test_value_sorting() {
1059 let mut values = vec![
1060 Value::String("b".to_string()),
1061 Value::None,
1062 Value::Number(Number::Int(10)),
1063 Value::Null,
1064 Value::Bool(true),
1065 Value::Number(Number::Int(5)),
1066 Value::String("a".to_string()),
1067 Value::Bool(false),
1068 Value::Number(Number::Float(7.5)),
1069 Value::Table("test".into()),
1070 Value::RecordId(RecordId::new("test", "key")),
1071 ];
1072
1073 values.sort();
1074
1075 assert_eq!(values[0], Value::None);
1076 assert_eq!(values[1], Value::Null);
1077 assert_eq!(values[2], Value::Bool(false));
1078 assert_eq!(values[3], Value::Bool(true));
1079 assert_eq!(values[4], Value::Number(Number::Int(5)));
1080 assert_eq!(values[5], Value::Number(Number::Float(7.5)));
1081 assert_eq!(values[6], Value::Number(Number::Int(10)));
1082 assert_eq!(values[7], Value::String("a".to_string()));
1083 assert_eq!(values[8], Value::String("b".to_string()));
1084 }
1085
1086 #[rstest]
1087 #[case::none(Value::None, "NONE")]
1089 #[case::null(Value::Null, "NULL")]
1090 #[case::bool(Value::Bool(true), "true")]
1092 #[case::bool(Value::Bool(false), "false")]
1093 #[case::number(Value::Number(Number::Int(0)), "0")]
1095 #[case::number(Value::Number(Number::Int(5)), "5")]
1096 #[case::number(Value::Number(Number::Int(-5)), "-5")]
1097 #[case::number(Value::Number(Number::Int(i64::MAX)), "9223372036854775807")]
1098 #[case::number(Value::Number(Number::Int(i64::MIN)), "-9223372036854775808")]
1099 #[case::number(Value::Number(Number::Float(0.0)), "0f")]
1101 #[case::number(Value::Number(Number::Float(5.0)), "5f")]
1102 #[case::number(Value::Number(Number::Float(-5.5)), "-5.5f")]
1103 #[case::number(Value::Number(Number::Float(3.12345)), "3.12345f")]
1104 #[case::number(Value::Number(Number::Decimal(Decimal::new(0, 0))), "0dec")]
1106 #[case::number(Value::Number(Number::Decimal(Decimal::new(5, 0))), "5dec")]
1107 #[case::number(Value::Number(Number::Decimal(Decimal::new(-5, 0))), "-5dec")]
1108 #[case::number(Value::Number(Number::Decimal(Decimal::new(12345, 2))), "123.45dec")]
1109 #[case::string(Value::String("".to_string()), "''")]
1111 #[case::string(Value::String("hello".to_string()), "'hello'")]
1112 #[case::string(Value::String("hello world".to_string()), "'hello world'")]
1113 #[case::string(Value::String("escap'd".to_string()), "\"escap'd\"")]
1115 #[case::string(Value::String("\"escaped\"".to_string()), "'\"escaped\"'")]
1116 #[case::string(Value::String("mix'd \"quotes\"".to_string()), "\"mix'd \\\"quotes\\\"\"")]
1117 #[case::string(Value::String("tab\there".to_string()), "'tab\\there'")]
1118 #[case::string(Value::String("new\nline".to_string()), "'new\\nline'")]
1119 #[case::string(Value::String("你好".to_string()), "'你好'")]
1121 #[case::string(Value::String("emoji 🎉".to_string()), "'emoji 🎉'")]
1122 #[case::duration(Value::Duration(Duration::new(0, 0)), "0ns")]
1124 #[case::duration(Value::Duration(Duration::new(1, 0)), "1s")]
1125 #[case::duration(Value::Duration(Duration::new(60, 0)), "1m")]
1126 #[case::duration(Value::Duration(Duration::new(3600, 0)), "1h")]
1127 #[case::duration(Value::Duration(Duration::new(90, 0)), "1m30s")]
1128 #[case::datetime(Value::Datetime(Datetime::from_timestamp(0, 0).unwrap()), "d'1970-01-01T00:00:00Z'")]
1130 #[case::datetime(Value::Datetime(Datetime::from_timestamp(1, 0).unwrap()), "d'1970-01-01T00:00:01Z'")]
1131 #[case::datetime(Value::Datetime(Datetime::from_timestamp(1234567890, 0).unwrap()), "d'2009-02-13T23:31:30Z'")]
1132 #[case::uuid(Value::Uuid(Uuid::nil()), "u'00000000-0000-0000-0000-000000000000'")]
1134 #[case::array(Value::Array(Array::new()), "[]")]
1136 #[case::array(Value::Array(vec![Value::Number(Number::Int(1))].into()), "[1]")]
1137 #[case::array(Value::Array(vec![Value::Number(Number::Int(1)), Value::Number(Number::Int(2)), Value::Number(Number::Int(3))].into()), "[1, 2, 3]")]
1138 #[case::array(Value::Array(vec![Value::String("hello".to_string()), Value::Number(Number::Int(42)), Value::Bool(true)].into()), "['hello', 42, true]")]
1140 #[case::array(Value::Array(vec![Value::Array(vec![Value::Number(Number::Int(1))].into())].into()), "[[1]]")]
1142 #[case::array(Value::Array(vec![Value::Array(vec![Value::Number(Number::Int(1)), Value::Number(Number::Int(2))].into()), Value::Array(vec![Value::Number(Number::Int(3))].into())].into()), "[[1, 2], [3]]")]
1143 #[case::object(Value::Object(Object::default()), "{ }")]
1145 #[case::object(Value::Object(object! {
1146 "hello": "world".to_string(),
1147 }), "{ hello: 'world' }")]
1148 #[case::object(Value::Object(object! {
1150 "name": "John".to_string(),
1151 "age": 30,
1152 }), "{ age: 30, name: 'John' }")]
1153 #[case::object(Value::Object(object! {
1155 "user": object! {
1156 "name": "Jane".to_string(),
1157 }
1158 }), "{ user: { name: 'Jane' } }")]
1159 #[case::object(Value::Object(object! {
1161 "items": vec![Value::Number(Number::Int(1)), Value::Number(Number::Int(2))],
1162 }), "{ items: [1, 2] }")]
1163 #[case::geometry(Value::Geometry(Geometry::Point(geo::Point::new(0.0, 0.0))), "(0f, 0f)")]
1165 #[case::geometry(Value::Geometry(Geometry::Point(geo::Point::new(1.0, 2.0))), "(1f, 2f)")]
1166 #[case::geometry(Value::Geometry(Geometry::Point(geo::Point::new(-123.45, 67.89))), "(-123.45f, 67.89f)")]
1167 #[case::bytes(Value::Bytes(Bytes::default()), "b\"\"")]
1169 #[case::bytes(Value::Bytes(Bytes::from(::bytes::Bytes::from(vec![1_u8, 2, 3]))), "b\"010203\"")]
1170 #[case::bytes(Value::Bytes(Bytes::from(::bytes::Bytes::from(vec![255_u8, 0, 128]))), "b\"FF0080\"")]
1171 #[case::table(Value::Table("test".into()), "test")]
1173 #[case::table(Value::Table("escap'd".into()), "`escap'd`")]
1174 #[case::record_id(Value::RecordId(RecordId::new("test", "key")), "test:key")]
1176 #[case::record_id(Value::RecordId(RecordId::new("user", 123)), "user:123")]
1177 #[case::record_id(Value::RecordId(RecordId::new("table", "complex_id")), "table:complex_id")]
1178 #[case::range(Value::Range(Box::new(Range::unbounded())), "..")]
1180 #[case::range(
1181 Value::Range(Box::new(Range::new(
1182 std::ops::Bound::Included(Value::Number(Number::Int(1))),
1183 std::ops::Bound::Excluded(Value::Number(Number::Int(10)))
1184 ))),
1185 "1..10"
1186 )]
1187 #[case::range(
1188 Value::Range(Box::new(Range::new(
1189 std::ops::Bound::Included(Value::Number(Number::Int(0))),
1190 std::ops::Bound::Included(Value::Number(Number::Int(100)))
1191 ))),
1192 "0..=100"
1193 )]
1194 #[case::range(
1195 Value::Range(Box::new(Range::new(
1196 std::ops::Bound::Unbounded,
1197 std::ops::Bound::Excluded(Value::Number(Number::Int(50)))
1198 ))),
1199 "..50"
1200 )]
1201 #[case::range(
1202 Value::Range(Box::new(Range::new(
1203 std::ops::Bound::Included(Value::Number(Number::Int(10))),
1204 std::ops::Bound::Unbounded
1205 ))),
1206 "10.."
1207 )]
1208 #[case::regex(Value::Regex("hello".parse().unwrap()), "/hello/")]
1210 #[case::regex(Value::Regex("[a-z]+".parse().unwrap()), "/[a-z]+/")]
1211 #[case::regex(Value::Regex("^test$".parse().unwrap()), "/^test$/")]
1212 fn test_to_sql(#[case] value: Value, #[case] expected_sql: &str) {
1213 assert_eq!(&value.to_sql(), expected_sql);
1214 }
1215
1216 #[rstest]
1217 #[case::none(Value::None, vec![Kind::None, Kind::Any], vec![Kind::Null])]
1218 #[case::null(Value::Null, vec![Kind::Null, Kind::Any], vec![Kind::None])]
1219 #[case::bool(
1220 Value::Bool(true),
1221 vec![Kind::Bool, Kind::Any, Kind::Literal(KindLiteral::Bool(true))],
1222 vec![Kind::None, Kind::Null, Kind::Literal(KindLiteral::Bool(false))]
1223 )]
1224 #[case::bool_false(
1225 Value::Bool(false),
1226 vec![Kind::Bool, Kind::Any, Kind::Literal(KindLiteral::Bool(false))],
1227 vec![Kind::None, Kind::Null, Kind::Literal(KindLiteral::Bool(true))]
1228 )]
1229 #[case::bytes(Value::Bytes(Bytes::default()), vec![Kind::Bytes, Kind::Any], vec![Kind::None, Kind::Null])]
1230 #[case::datetime(
1231 Value::Datetime(Datetime::default()),
1232 vec![Kind::Datetime, Kind::Any],
1233 vec![Kind::None, Kind::Null]
1234 )]
1235 #[case::duration(
1236 Value::Duration(Duration::default()),
1237 vec![
1238 Kind::Duration,
1239 Kind::Any,
1240 Kind::Literal(KindLiteral::Duration(Duration::default()))
1241 ],
1242 vec![Kind::None, Kind::Null, Kind::Literal(KindLiteral::Duration(Duration::new(1, 0)))]
1243 )]
1244 #[case::int(
1245 Value::Number(Number::Int(0)),
1246 vec![Kind::Int, Kind::Number, Kind::Any, Kind::Literal(KindLiteral::Integer(0))],
1247 vec![Kind::None, Kind::Null, Kind::Literal(KindLiteral::Integer(1))]
1248 )]
1249 #[case::float(
1250 Value::Number(Number::Float(0.0)),
1251 vec![Kind::Float, Kind::Number, Kind::Any, Kind::Literal(KindLiteral::Float(0.0))],
1252 vec![Kind::None, Kind::Null, Kind::Literal(KindLiteral::Float(1.0))]
1253 )]
1254 #[case::decimal(
1255 Value::Number(Number::Decimal(Decimal::default())),
1256 vec![
1257 Kind::Decimal,
1258 Kind::Number,
1259 Kind::Any,
1260 Kind::Literal(KindLiteral::Decimal(Decimal::default()))
1261 ],
1262 vec![Kind::None, Kind::Null]
1263 )]
1264 #[case::string(
1265 Value::String("".to_string()),
1266 vec![Kind::String, Kind::Any, Kind::Literal(KindLiteral::String("".to_string()))],
1267 vec![Kind::None, Kind::Null, Kind::Literal(KindLiteral::String("foo".to_string()))]
1268 )]
1269 #[case::string(
1270 Value::String("foo".to_string()),
1271 vec![Kind::String, Kind::Any, Kind::Literal(KindLiteral::String("foo".to_string()))],
1272 vec![Kind::None, Kind::Null, Kind::Literal(KindLiteral::String("bar".to_string()))]
1273 )]
1274 #[case::uuid(Value::Uuid(Uuid::new_v4()), vec![Kind::Uuid, Kind::Any], vec![Kind::None, Kind::Null])]
1275 #[case::regex(
1276 Value::Regex("hello".parse().unwrap()),
1277 vec![Kind::Regex, Kind::Any],
1278 vec![Kind::None, Kind::Null]
1279 )]
1280 #[case::table(
1281 Value::Table("test".into()),
1282 vec![Kind::Table(vec!["test".into()]), Kind::Table(vec![]), Kind::Any],
1283 vec![Kind::None, Kind::Null]
1284 )]
1285 #[case::record(
1286 Value::RecordId(RecordId::new("test", "key")),
1287 vec![Kind::Record(vec!["test".into()]), Kind::Record(vec![]), Kind::Any],
1288 vec![Kind::None, Kind::Null, Kind::Record(vec!["other".into()])]
1289 )]
1290 #[case::record_multi_table(
1291 Value::RecordId(RecordId::new("user", "id")),
1292 vec![Kind::Record(vec!["user".into(), "admin".into()]), Kind::Any],
1293 vec![Kind::Record(vec!["post".into(), "comment".into()])]
1294 )]
1295 #[case::geometry_point(
1296 Value::Geometry(Geometry::Point(geo::Point::new(1.0, 2.0))),
1297 vec![Kind::Geometry(vec![GeometryKind::Point]), Kind::Geometry(vec![]), Kind::Any],
1298 vec![Kind::None, Kind::Null, Kind::Geometry(vec![GeometryKind::Line])]
1299 )]
1300 #[case::geometry_line(
1301 Value::Geometry(Geometry::Line(geo::LineString::from(vec![(0.0, 0.0), (1.0, 1.0)]))),
1302 vec![Kind::Geometry(vec![GeometryKind::Line]), Kind::Geometry(vec![]), Kind::Any],
1303 vec![Kind::Geometry(vec![GeometryKind::Point])]
1304 )]
1305 #[case::geometry_polygon(
1306 Value::Geometry(Geometry::Polygon(geo::Polygon::new(
1307 geo::LineString::from(vec![
1308 (0.0, 0.0),
1309 (1.0, 0.0),
1310 (1.0, 1.0),
1311 (0.0, 1.0),
1312 (0.0, 0.0)
1313 ]),
1314 vec![]
1315 ))),
1316 vec![Kind::Geometry(vec![GeometryKind::Polygon]), Kind::Geometry(vec![]), Kind::Any],
1317 vec![Kind::Geometry(vec![GeometryKind::Point])]
1318 )]
1319 #[case::geometry_multi(
1320 Value::Geometry(Geometry::Point(geo::Point::new(1.0, 2.0))),
1321 vec![Kind::Geometry(vec![GeometryKind::Point, GeometryKind::Line]), Kind::Any],
1322 vec![Kind::Geometry(vec![GeometryKind::Line, GeometryKind::Polygon])]
1323 )]
1324 #[case::array_empty(
1325 Value::Array(Array::new()),
1326 vec![
1327 Kind::Array(Box::new(Kind::Any), None),
1328 Kind::Array(Box::new(Kind::String), None),
1329 Kind::Any
1330 ],
1331 vec![Kind::None, Kind::Null]
1332 )]
1333 #[case::array_strings(
1334 Value::Array(Array::from(vec![
1335 Value::String("a".to_string()),
1336 Value::String("b".to_string())
1337 ])),
1338 vec![
1339 Kind::Array(Box::new(Kind::String), None),
1340 Kind::Array(Box::new(Kind::String), Some(5)),
1341 Kind::Any
1342 ],
1343 vec![Kind::Array(Box::new(Kind::Int), None), Kind::Array(Box::new(Kind::String), Some(1))]
1344 )]
1345 #[case::array_mixed_fails(
1346 Value::Array(Array::from(vec![
1347 Value::String("a".to_string()),
1348 Value::Number(Number::Int(1))
1349 ])),
1350 vec![Kind::Array(Box::new(Kind::Any), None), Kind::Any],
1351 vec![Kind::Array(Box::new(Kind::String), None), Kind::Array(Box::new(Kind::Int), None)]
1352 )]
1353 #[case::array_with_max(
1354 Value::Array(Array::from(vec![
1355 Value::Number(Number::Int(1)),
1356 Value::Number(Number::Int(2)),
1357 Value::Number(Number::Int(3))
1358 ])),
1359 vec![
1360 Kind::Array(Box::new(Kind::Int), Some(3)),
1361 Kind::Array(Box::new(Kind::Int), Some(10)),
1362 Kind::Any
1363 ],
1364 vec![Kind::Array(Box::new(Kind::Int), Some(2))]
1365 )]
1366 #[case::range(
1367 Value::Range(Box::new(Range::unbounded())),
1368 vec![Kind::Range, Kind::Any],
1369 vec![Kind::None, Kind::Null]
1370 )]
1371 #[case::file_empty_bucket(
1372 Value::File(File::default()),
1373 vec![Kind::File(vec!["".to_string()]), Kind::File(vec![]), Kind::Any],
1374 vec![Kind::None, Kind::Null]
1375 )]
1376 #[case::file_specific_bucket(
1377 Value::File(File::new("mybucket", "file.txt")),
1378 vec![Kind::File(vec!["mybucket".to_string()]), Kind::File(vec![]), Kind::Any],
1379 vec![Kind::File(vec!["other".to_string()])]
1380 )]
1381 #[case::object_empty(
1382 Value::Object(Object::default()),
1383 vec![Kind::Object, Kind::Any, Kind::Literal(KindLiteral::Object(BTreeMap::new()))],
1384 vec![Kind::None, Kind::Null]
1385 )]
1386 #[case::object_with_fields(
1387 Value::Object(object! { key: "value".to_string() }),
1388 vec![
1389 Kind::Object,
1390 Kind::Any,
1391 Kind::Literal(KindLiteral::Object(BTreeMap::from([(
1392 "key".to_string(),
1393 Kind::String
1394 )])))
1395 ],
1396 vec![Kind::None, Kind::Null, Kind::Literal(KindLiteral::Object(BTreeMap::new()))]
1397 )]
1398 #[case::literal_array(
1399 Value::Array(Array::from(vec![
1400 Value::Number(Number::Int(1)),
1401 Value::String("test".to_string())
1402 ])),
1403 vec![Kind::Literal(KindLiteral::Array(vec![Kind::Int, Kind::String])), Kind::Any],
1404 vec![
1405 Kind::Literal(KindLiteral::Array(vec![Kind::String, Kind::Int])),
1406 Kind::Literal(KindLiteral::Array(vec![Kind::Int]))
1407 ]
1408 )]
1409 #[case::either_string_or_int(
1410 Value::String("test".to_string()),
1411 vec![Kind::Either(vec![Kind::String, Kind::Int]), Kind::Any],
1412 vec![Kind::Either(vec![Kind::Int, Kind::Bool])]
1413 )]
1414 #[case::either_int_matches(
1415 Value::Number(Number::Int(42)),
1416 vec![Kind::Either(vec![Kind::String, Kind::Int]), Kind::Any],
1417 vec![Kind::Either(vec![Kind::String, Kind::Bool])]
1418 )]
1419 #[case::option_kind_none(
1420 Value::None,
1421 vec![Kind::option(Kind::String), Kind::Any],
1422 vec![Kind::String]
1423 )]
1424 #[case::option_kind_value(
1425 Value::String("test".to_string()),
1426 vec![Kind::option(Kind::String), Kind::Any],
1427 vec![Kind::Int]
1428 )]
1429 fn test_is_kind(#[case] value: Value, #[case] kinds: Vec<Kind>, #[case] not_kinds: Vec<Kind>) {
1430 for kind in kinds {
1431 assert!(value.is_kind(&kind), "{value:?} is not a {kind}");
1432 }
1433 for kind in not_kinds {
1434 assert!(!value.is_kind(&kind), "{value:?} is a {kind} but should not be");
1435 }
1436 }
1437}