@@ -6,6 +6,8 @@ use strum_macros::Display;
6
6
use url:: Url ;
7
7
use validator:: { Validate , ValidationError } ;
8
8
9
+ use crate :: types:: { DValue , Missing } ;
10
+
9
11
/// Supported numerical data types
10
12
#[ derive( Clone , Copy , Debug , Deserialize , Display , PartialEq ) ]
11
13
#[ serde( rename_all = "lowercase" ) ]
@@ -14,11 +16,11 @@ pub enum DType {
14
16
Int32 ,
15
17
/// [i64]
16
18
Int64 ,
17
- /// [u64 ]
19
+ /// [u32 ]
18
20
Uint32 ,
19
21
/// [u64]
20
22
Uint64 ,
21
- /// [f64 ]
23
+ /// [f32 ]
22
24
Float32 ,
23
25
/// [f64]
24
26
Float64 ,
@@ -142,6 +144,8 @@ pub struct RequestData {
142
144
pub compression : Option < Compression > ,
143
145
/// List of filter algorithms
144
146
pub filters : Option < Vec < Filter > > ,
147
+ /// Missing data
148
+ pub missing : Option < Missing < DValue > > ,
145
149
}
146
150
147
151
/// Validate an array shape
@@ -230,6 +234,9 @@ fn validate_request_data(request_data: &RequestData) -> Result<(), ValidationErr
230
234
}
231
235
_ => ( ) ,
232
236
} ;
237
+ if let Some ( missing) = & request_data. missing {
238
+ missing. validate ( request_data. dtype ) ?;
239
+ } ;
233
240
Ok ( ( ) )
234
241
}
235
242
@@ -359,6 +366,11 @@ mod tests {
359
366
Token :: U32 ( 4 ) ,
360
367
Token :: MapEnd ,
361
368
Token :: SeqEnd ,
369
+ Token :: Str ( "missing" ) ,
370
+ Token :: Some ,
371
+ Token :: Enum { name : "Missing" } ,
372
+ Token :: Str ( "missing_value" ) ,
373
+ Token :: I32 ( 42 ) ,
362
374
Token :: StructEnd ,
363
375
] ,
364
376
) ;
@@ -664,14 +676,40 @@ mod tests {
664
676
)
665
677
}
666
678
679
+ #[ test]
680
+ fn test_invalid_missing ( ) {
681
+ assert_de_tokens_error :: < RequestData > (
682
+ & [
683
+ Token :: Struct {
684
+ name : "RequestData" ,
685
+ len : 2 ,
686
+ } ,
687
+ Token :: Str ( "missing" ) ,
688
+ Token :: Some ,
689
+ Token :: Enum { name : "Missing" } ,
690
+ Token :: Str ( "foo" ) ,
691
+ Token :: StructEnd
692
+ ] ,
693
+ "unknown variant `foo`, expected one of `missing_value`, `missing_values`, `valid_min`, `valid_max`, `valid_range`" ,
694
+ )
695
+ }
696
+
697
+ #[ test]
698
+ #[ should_panic( expected = "Incompatible value 9223372036854775807 for missing" ) ]
699
+ fn test_missing_invalid_value_for_dtype ( ) {
700
+ let mut request_data = test_utils:: get_test_request_data ( ) ;
701
+ request_data. missing = Some ( Missing :: MissingValue ( i64:: max_value ( ) . into ( ) ) ) ;
702
+ request_data. validate ( ) . unwrap ( )
703
+ }
704
+
667
705
#[ test]
668
706
fn test_unknown_field ( ) {
669
707
assert_de_tokens_error :: < RequestData > ( & [
670
708
Token :: Struct { name : "RequestData" , len : 2 } ,
671
709
Token :: Str ( "foo" ) ,
672
710
Token :: StructEnd
673
711
] ,
674
- "unknown field `foo`, expected one of `source`, `bucket`, `object`, `dtype`, `offset`, `size`, `shape`, `order`, `selection`, `compression`, `filters`"
712
+ "unknown field `foo`, expected one of `source`, `bucket`, `object`, `dtype`, `offset`, `size`, `shape`, `order`, `selection`, `compression`, `filters`, `missing` "
675
713
)
676
714
}
677
715
@@ -686,8 +724,82 @@ mod tests {
686
724
687
725
#[ test]
688
726
fn test_json_optional_fields ( ) {
689
- let json = r#"{"source": "http://example.com", "bucket": "bar", "object": "baz", "dtype": "int32", "offset": 4, "size": 8, "shape": [2, 5], "order": "C", "selection": [[1, 2, 3], [4, 5, 6]], "compression": {"id": "gzip"}, "filters": [{"id": "shuffle", "element_size": 4}]}"# ;
727
+ let json = r#"{
728
+ "source": "http://example.com",
729
+ "bucket": "bar",
730
+ "object": "baz",
731
+ "dtype": "int32",
732
+ "offset": 4,
733
+ "size": 8,
734
+ "shape": [2, 5],
735
+ "order": "C",
736
+ "selection": [[1, 2, 3], [4, 5, 6]],
737
+ "compression": {"id": "gzip"},
738
+ "filters": [{"id": "shuffle", "element_size": 4}],
739
+ "missing": {"missing_value": 42}
740
+ }"# ;
690
741
let request_data = serde_json:: from_str :: < RequestData > ( json) . unwrap ( ) ;
691
742
assert_eq ! ( request_data, test_utils:: get_test_request_data_optional( ) ) ;
692
743
}
744
+
745
+ #[ test]
746
+ fn test_json_optional_fields2 ( ) {
747
+ let json = r#"{
748
+ "source": "http://example.com",
749
+ "bucket": "bar",
750
+ "object": "baz",
751
+ "dtype": "float64",
752
+ "offset": 4,
753
+ "size": 8,
754
+ "shape": [2, 5, 10],
755
+ "order": "F",
756
+ "selection": [[1, 2, 3], [4, 5, 6], [7, 8, 9]],
757
+ "compression": {"id": "zlib"},
758
+ "filters": [{"id": "shuffle", "element_size": 8}],
759
+ "missing": {"valid_range": [-1.0, 999.0]}
760
+ }"# ;
761
+ let request_data = serde_json:: from_str :: < RequestData > ( json) . unwrap ( ) ;
762
+ let mut expected = test_utils:: get_test_request_data_optional ( ) ;
763
+ expected. dtype = DType :: Float64 ;
764
+ expected. shape = Some ( vec ! [ 2 , 5 , 10 ] ) ;
765
+ expected. order = Some ( Order :: F ) ;
766
+ expected. selection = Some ( vec ! [
767
+ Slice :: new( 1 , 2 , 3 ) ,
768
+ Slice :: new( 4 , 5 , 6 ) ,
769
+ Slice :: new( 7 , 8 , 9 ) ,
770
+ ] ) ;
771
+ expected. compression = Some ( Compression :: Zlib ) ;
772
+ expected. filters = Some ( vec ! [ Filter :: Shuffle { element_size: 8 } ] ) ;
773
+ expected. missing = Some ( Missing :: ValidRange (
774
+ DValue :: from_f64 ( -1.0 ) . unwrap ( ) ,
775
+ DValue :: from_f64 ( 999.0 ) . unwrap ( ) ,
776
+ ) ) ;
777
+ assert_eq ! ( request_data, expected) ;
778
+ }
779
+
780
+ #[ test]
781
+ fn test_json_optional_fields3 ( ) {
782
+ let json = format ! (
783
+ r#"{{
784
+ "source": "http://example.com",
785
+ "bucket": "bar",
786
+ "object": "baz",
787
+ "dtype": "int32",
788
+ "missing": {{"missing_values": [{}, -1, 0, 1, {}]}}
789
+ }}"# ,
790
+ i64 :: min_value( ) ,
791
+ u64 :: max_value( )
792
+ ) ;
793
+ let request_data = serde_json:: from_str :: < RequestData > ( & json) . unwrap ( ) ;
794
+ let mut expected = test_utils:: get_test_request_data ( ) ;
795
+ expected. dtype = DType :: Int32 ;
796
+ expected. missing = Some ( Missing :: MissingValues ( vec ! [
797
+ i64 :: min_value( ) . into( ) ,
798
+ ( -1 ) . into( ) ,
799
+ 0 . into( ) ,
800
+ 1 . into( ) ,
801
+ u64 :: max_value( ) . into( ) ,
802
+ ] ) ) ;
803
+ assert_eq ! ( request_data, expected) ;
804
+ }
693
805
}
0 commit comments