1
1
use crate :: util:: { PartiqlValueTarget , ToPartiqlValue } ;
2
2
use ion_rs:: {
3
- AnyEncoding , Element , ElementReader , IonResult , IonType , OwnedSequenceIterator , Reader ,
4
- Sequence ,
3
+ AnyEncoding , Element , ElementReader , IonData , IonResult , IonType , OwnedSequenceIterator ,
4
+ Reader , Sequence , Struct , Symbol ,
5
5
} ;
6
+ use itertools:: Itertools ;
6
7
use partiql_value:: boxed_variant:: {
7
8
BoxedVariant , BoxedVariantResult , BoxedVariantType , BoxedVariantTypeTag ,
8
9
BoxedVariantValueIntoIterator , DynBoxedVariant ,
@@ -12,14 +13,14 @@ use partiql_value::datum::{
12
13
DatumSeqRef , DatumTupleOwned , DatumTupleRef , DatumValueOwned , DatumValueRef , OwnedSequenceView ,
13
14
OwnedTupleView , RefSequenceView , RefTupleView , SequenceDatum , TupleDatum ,
14
15
} ;
15
- use partiql_value:: { Bag , BindingsName , List , Tuple , Value , Variant } ;
16
+ use partiql_value:: { Bag , BindingsName , List , NullableEq , Tuple , Value , Variant } ;
16
17
use peekmore:: { PeekMore , PeekMoreIterator } ;
17
18
#[ cfg( feature = "serde" ) ]
18
19
use serde:: { Deserialize , Deserializer , Serialize , Serializer } ;
19
20
use std:: any:: Any ;
20
21
use std:: borrow:: Cow ;
21
22
use std:: cell:: RefCell ;
22
- use std:: cmp :: Ordering ;
23
+ use std:: collections :: HashMap ;
23
24
use std:: fmt:: { Debug , Display , Formatter } ;
24
25
use std:: hash:: { Hash , Hasher } ;
25
26
use std:: ops:: DerefMut ;
@@ -40,16 +41,33 @@ impl BoxedVariantType for BoxedIonType {
40
41
}
41
42
42
43
fn value_eq ( & self , l : & DynBoxedVariant , r : & DynBoxedVariant ) -> bool {
43
- let ( l, r) = get_values ( l, r) ;
44
-
45
- l. eq ( r)
44
+ wrap_eq :: < true , false > ( l, r) == Value :: Boolean ( true )
45
+ }
46
+
47
+ fn value_eq_param (
48
+ & self ,
49
+ l : & DynBoxedVariant ,
50
+ r : & DynBoxedVariant ,
51
+ nulls_eq : bool ,
52
+ nans_eq : bool ,
53
+ ) -> bool {
54
+ let res = match ( nulls_eq, nans_eq) {
55
+ ( true , true ) => wrap_eq :: < true , true > ( l, r) ,
56
+ ( true , false ) => wrap_eq :: < true , false > ( l, r) ,
57
+ ( false , true ) => wrap_eq :: < false , true > ( l, r) ,
58
+ ( false , false ) => wrap_eq :: < false , false > ( l, r) ,
59
+ } ;
60
+ res == Value :: Boolean ( true )
46
61
}
62
+ }
47
63
48
- fn value_cmp ( & self , l : & DynBoxedVariant , r : & DynBoxedVariant ) -> Ordering {
49
- let ( l, r) = get_values ( l, r) ;
50
-
51
- l. cmp ( r)
52
- }
64
+ fn wrap_eq < const NULLS_EQUAL : bool , const NAN_EQUAL : bool > (
65
+ l : & DynBoxedVariant ,
66
+ r : & DynBoxedVariant ,
67
+ ) -> Value {
68
+ let ( l, r) = get_values ( l, r) ;
69
+ let wrap = IonEqualityValue :: < ' _ , { NULLS_EQUAL } , { NAN_EQUAL } , _ > ;
70
+ NullableEq :: eq ( & wrap ( l) , & wrap ( r) )
53
71
}
54
72
55
73
#[ inline]
@@ -139,8 +157,8 @@ impl<'de> Deserialize<'de> for BoxedIon {
139
157
}
140
158
141
159
impl Hash for BoxedIon {
142
- fn hash < H : Hasher > ( & self , _ : & mut H ) {
143
- todo ! ( "BoxedIon. hash" )
160
+ fn hash < H : Hasher > ( & self , state : & mut H ) {
161
+ self . doc . hash ( state ) ;
144
162
}
145
163
}
146
164
@@ -206,23 +224,21 @@ impl BoxedVariant for BoxedIon {
206
224
}
207
225
}
208
226
209
- impl PartialEq < Self > for BoxedIon {
210
- fn eq ( & self , other : & Self ) -> bool {
211
- self . doc . eq ( & other. doc )
212
- }
213
- }
214
-
215
- impl Eq for BoxedIon { }
227
+ /// A wrapper on [`T`] that specifies if missing and null values should be equal.
228
+ #[ derive( Eq , PartialEq ) ]
229
+ pub struct IonEqualityValue < ' a , const NULLS_EQUAL : bool , const NAN_EQUAL : bool , T > ( pub & ' a T ) ;
216
230
217
- impl PartialOrd for BoxedIon {
218
- fn partial_cmp ( & self , other : & Self ) -> Option < Ordering > {
219
- Some ( self . cmp ( other) )
231
+ impl < ' a , const NULLS_EQUAL : bool , const NAN_EQUAL : bool > NullableEq
232
+ for IonEqualityValue < ' a , NULLS_EQUAL , NAN_EQUAL , BoxedIon >
233
+ {
234
+ fn eq ( & self , rhs : & Self ) -> Value {
235
+ let wrap = IonEqualityValue :: < ' a , { NULLS_EQUAL } , { NAN_EQUAL } , _ > ;
236
+ NullableEq :: eq ( & wrap ( & self . 0 . doc ) , & wrap ( & rhs. 0 . doc ) )
220
237
}
221
- }
222
- impl Ord for BoxedIon {
223
- fn cmp ( & self , other : & Self ) -> Ordering {
224
- // TODO lowering just to compare is costly... Either find a better way, or lift this out of the extension
225
- self . lower ( ) . unwrap ( ) . cmp ( & other. lower ( ) . unwrap ( ) )
238
+ #[ inline( always) ]
239
+ fn eqg ( & self , rhs : & Self ) -> Value {
240
+ let wrap = IonEqualityValue :: < ' _ , true , { NAN_EQUAL } , _ > ;
241
+ NullableEq :: eq ( & wrap ( self . 0 ) , & wrap ( rhs. 0 ) )
226
242
}
227
243
}
228
244
@@ -531,17 +547,153 @@ enum BoxedIonValue {
531
547
Sequence ( Sequence ) ,
532
548
}
533
549
534
- impl PartialEq < Self > for BoxedIonValue {
535
- fn eq ( & self , other : & Self ) -> bool {
536
- match ( self , other) {
537
- ( BoxedIonValue :: Value ( l) , BoxedIonValue :: Value ( r) ) => l == r,
538
- ( BoxedIonValue :: Sequence ( l) , BoxedIonValue :: Sequence ( r) ) => l == r,
539
- _ => false ,
550
+ impl Hash for BoxedIonValue {
551
+ fn hash < H : Hasher > ( & self , state : & mut H ) {
552
+ match self {
553
+ BoxedIonValue :: Stream ( ) => {
554
+ todo ! ( "stream not hashable? " )
555
+ }
556
+ BoxedIonValue :: Value ( val) => {
557
+ let sha = ion_rs:: ion_hash:: sha256 ( val) . expect ( "ion hash" ) ;
558
+ state. write ( & sha) ;
559
+ }
560
+ BoxedIonValue :: Sequence ( _) => todo ! ( "ion seq hash" ) ,
540
561
}
541
562
}
542
563
}
543
564
544
- impl Eq for BoxedIonValue { }
565
+ impl < ' a , const NULLS_EQUAL : bool , const NAN_EQUAL : bool > NullableEq
566
+ for IonEqualityValue < ' a , NULLS_EQUAL , NAN_EQUAL , BoxedIonValue >
567
+ {
568
+ #[ inline( always) ]
569
+ fn eq ( & self , other : & Self ) -> Value {
570
+ let wrap = IonEqualityValue :: < ' a , { NULLS_EQUAL } , { NAN_EQUAL } , Element > ;
571
+ let wrap_seq = IonEqualityValue :: < ' a , { NULLS_EQUAL } , { NAN_EQUAL } , Sequence > ;
572
+ match ( self . 0 , other. 0 ) {
573
+ ( BoxedIonValue :: Value ( l) , BoxedIonValue :: Value ( r) ) => {
574
+ NullableEq :: eq ( & wrap ( l) , & wrap ( r) )
575
+ }
576
+ ( BoxedIonValue :: Sequence ( l) , BoxedIonValue :: Sequence ( r) ) => {
577
+ NullableEq :: eq ( & wrap_seq ( l) , & wrap_seq ( r) )
578
+ }
579
+ _ => Value :: Boolean ( false ) ,
580
+ }
581
+ }
582
+
583
+ #[ inline( always) ]
584
+ fn eqg ( & self , rhs : & Self ) -> Value {
585
+ let wrap = IonEqualityValue :: < ' _ , true , { NAN_EQUAL } , _ > ;
586
+ NullableEq :: eq ( & wrap ( self . 0 ) , & wrap ( rhs. 0 ) )
587
+ }
588
+ }
589
+
590
+ impl < ' a , const NULLS_EQUAL : bool , const NAN_EQUAL : bool > NullableEq
591
+ for IonEqualityValue < ' a , NULLS_EQUAL , NAN_EQUAL , Element >
592
+ {
593
+ fn eq ( & self , other : & Self ) -> Value {
594
+ let wrap_seq = IonEqualityValue :: < ' a , { NULLS_EQUAL } , { NAN_EQUAL } , Sequence > ;
595
+ let wrap_struct = IonEqualityValue :: < ' a , { NULLS_EQUAL } , { NAN_EQUAL } , Struct > ;
596
+ let ( l, r) = ( self . 0 , other. 0 ) ;
597
+ let ( lty, rty) = ( l. ion_type ( ) , r. ion_type ( ) ) ;
598
+
599
+ let result = if l. is_null ( ) && r. is_null ( ) {
600
+ NULLS_EQUAL && l. annotations ( ) . eq ( r. annotations ( ) )
601
+ } else {
602
+ match ( lty, rty) {
603
+ ( IonType :: Float , IonType :: Float ) => {
604
+ let ( lf, rf) = ( l. as_float ( ) . unwrap ( ) , r. as_float ( ) . unwrap ( ) ) ;
605
+ if lf. is_nan ( ) && rf. is_nan ( ) {
606
+ NAN_EQUAL && l. annotations ( ) . eq ( r. annotations ( ) )
607
+ } else {
608
+ lf == rf
609
+ }
610
+ }
611
+
612
+ ( IonType :: List , IonType :: List ) => {
613
+ let ( ls, rs) = ( l. as_list ( ) . unwrap ( ) , r. as_list ( ) . unwrap ( ) ) ;
614
+ l. annotations ( ) . eq ( r. annotations ( ) )
615
+ && NullableEq :: eq ( & wrap_seq ( ls) , & wrap_seq ( rs) ) == Value :: Boolean ( true )
616
+ }
617
+ ( IonType :: SExp , IonType :: SExp ) => {
618
+ let ( ls, rs) = ( l. as_sexp ( ) . unwrap ( ) , r. as_sexp ( ) . unwrap ( ) ) ;
619
+ l. annotations ( ) . eq ( r. annotations ( ) )
620
+ && NullableEq :: eq ( & wrap_seq ( ls) , & wrap_seq ( rs) ) == Value :: Boolean ( true )
621
+ }
622
+
623
+ ( IonType :: Struct , IonType :: Struct ) => {
624
+ let ( ls, rs) = ( l. as_struct ( ) . unwrap ( ) , r. as_struct ( ) . unwrap ( ) ) ;
625
+ l. annotations ( ) . eq ( r. annotations ( ) )
626
+ && NullableEq :: eq ( & wrap_struct ( ls) , & wrap_struct ( rs) )
627
+ == Value :: Boolean ( true )
628
+ }
629
+
630
+ _ => l == r,
631
+ }
632
+ } ;
633
+
634
+ Value :: Boolean ( result)
635
+ }
636
+
637
+ #[ inline( always) ]
638
+ fn eqg ( & self , rhs : & Self ) -> Value {
639
+ let wrap = IonEqualityValue :: < ' _ , true , { NAN_EQUAL } , _ > ;
640
+ NullableEq :: eq ( & wrap ( self . 0 ) , & wrap ( rhs. 0 ) )
641
+ }
642
+ }
643
+
644
+ impl < ' a , const NULLS_EQUAL : bool , const NAN_EQUAL : bool > NullableEq
645
+ for IonEqualityValue < ' a , NULLS_EQUAL , NAN_EQUAL , Sequence >
646
+ {
647
+ fn eq ( & self , other : & Self ) -> Value {
648
+ let wrap = IonEqualityValue :: < ' a , { NULLS_EQUAL } , { NAN_EQUAL } , _ > ;
649
+ let ( l, r) = ( self . 0 , other. 0 ) ;
650
+ let l = l. iter ( ) . map ( wrap) ;
651
+ let r = r. iter ( ) . map ( wrap) ;
652
+ let res = l. zip ( r) . all ( |( l, r) | l. eqg ( & r) == Value :: Boolean ( true ) ) ;
653
+ Value :: Boolean ( res)
654
+ }
655
+
656
+ #[ inline( always) ]
657
+ fn eqg ( & self , rhs : & Self ) -> Value {
658
+ let wrap = IonEqualityValue :: < ' _ , true , { NAN_EQUAL } , _ > ;
659
+ NullableEq :: eq ( & wrap ( self . 0 ) , & wrap ( rhs. 0 ) )
660
+ }
661
+ }
662
+
663
+ impl < ' a , const NULLS_EQUAL : bool , const NAN_EQUAL : bool > NullableEq
664
+ for IonEqualityValue < ' a , NULLS_EQUAL , NAN_EQUAL , Struct >
665
+ {
666
+ fn eq ( & self , other : & Self ) -> Value {
667
+ if self . 0 . len ( ) != other. 0 . len ( ) {
668
+ return Value :: Boolean ( false ) ;
669
+ }
670
+
671
+ let ( l, r) = ( self . 0 , other. 0 ) ;
672
+ let l = l. iter ( ) ;
673
+ let r = r. iter ( ) ;
674
+
675
+ let sort_fn = |( ls, le) : & ( & Symbol , & Element ) , ( rs, re) : & ( & Symbol , & Element ) | {
676
+ ls. cmp ( rs) . then ( IonData :: from ( le) . cmp ( & IonData :: from ( re) ) )
677
+ } ;
678
+ for ( ( ls, lv) , ( rs, rv) ) in l. sorted_by ( sort_fn) . zip ( r. sorted_by ( sort_fn) ) {
679
+ if ls != rs {
680
+ return Value :: Boolean ( false ) ;
681
+ }
682
+
683
+ let wrap = IonEqualityValue :: < ' a , { NULLS_EQUAL } , { NAN_EQUAL } , _ > ;
684
+ if NullableEq :: eqg ( & wrap ( lv) , & wrap ( rv) ) != Value :: Boolean ( true ) {
685
+ return Value :: Boolean ( false ) ;
686
+ }
687
+ }
688
+ Value :: Boolean ( true )
689
+ }
690
+
691
+ #[ inline( always) ]
692
+ fn eqg ( & self , rhs : & Self ) -> Value {
693
+ let wrap = IonEqualityValue :: < ' _ , true , { NAN_EQUAL } , _ > ;
694
+ NullableEq :: eq ( & wrap ( self . 0 ) , & wrap ( rhs. 0 ) )
695
+ }
696
+ }
545
697
546
698
impl From < Element > for BoxedIonValue {
547
699
fn from ( value : Element ) -> Self {
0 commit comments