1
+ use std:: borrow:: Cow ;
1
2
use std:: collections:: BTreeMap ;
2
3
use std:: fmt;
3
4
use std:: marker:: PhantomData ;
@@ -6,9 +7,10 @@ use std::path::Path;
6
7
use indexmap:: IndexMap ;
7
8
use rari_utils:: concat_strs;
8
9
use rari_utils:: io:: read_to_string;
9
- use schemars:: JsonSchema ;
10
+ use schemars:: schema:: Schema ;
11
+ use schemars:: { JsonSchema , SchemaGenerator } ;
10
12
use serde:: de:: { self , value, SeqAccess , Visitor } ;
11
- use serde:: { Deserialize , Deserializer , Serialize } ;
13
+ use serde:: { Deserialize , Deserializer , Serialize , Serializer } ;
12
14
use serde_json:: Value ;
13
15
use url:: Url ;
14
16
@@ -141,7 +143,7 @@ impl WebFeatures {
141
143
} ) ;
142
144
}
143
145
match status. baseline {
144
- Some ( BaselineHighLow :: False ( false ) ) => {
146
+ Some ( BaselineHighLow :: False ) => {
145
147
let Support {
146
148
chrome,
147
149
chrome_android,
@@ -301,13 +303,63 @@ pub struct Support {
301
303
#[ serde( default , skip_serializing_if = "Option::is_none" ) ]
302
304
safari_ios : Option < String > ,
303
305
}
304
- #[ derive( Deserialize , Serialize , Clone , Copy , Debug , PartialEq , Eq , JsonSchema ) ]
306
+ #[ derive( Deserialize , Serialize , Clone , Copy , Debug , PartialEq , Eq ) ]
305
307
#[ serde( rename_all = "snake_case" ) ]
306
308
pub enum BaselineHighLow {
307
309
High ,
308
310
Low ,
309
- #[ serde( untagged) ]
310
- False ( bool ) ,
311
+ #[ serde(
312
+ untagged,
313
+ serialize_with = "serialize_false" ,
314
+ deserialize_with = "deserialize_false"
315
+ ) ]
316
+ False ,
317
+ }
318
+
319
+ // Deriving JsonSchema fails to type the false case. So we do it manually.
320
+ impl JsonSchema for BaselineHighLow {
321
+ fn schema_name ( ) -> String {
322
+ "BaselineHighLow" . into ( )
323
+ }
324
+
325
+ fn schema_id ( ) -> Cow < ' static , str > {
326
+ concat ! ( module_path!( ) , "::BaselineHighLow" ) . into ( )
327
+ }
328
+
329
+ fn json_schema ( _gen : & mut SchemaGenerator ) -> Schema {
330
+ serde_json:: from_str (
331
+ r#"{"oneOf": [
332
+ {
333
+ "type": "string",
334
+ "enum": ["high", "low"]
335
+ },
336
+ {
337
+ "type": "boolean",
338
+ "enum": [false]
339
+ }
340
+ ]}"# ,
341
+ )
342
+ . unwrap ( )
343
+ }
344
+ }
345
+
346
+ fn serialize_false < S > ( serializer : S ) -> Result < S :: Ok , S :: Error >
347
+ where
348
+ S : Serializer ,
349
+ {
350
+ serializer. serialize_bool ( false )
351
+ }
352
+
353
+ fn deserialize_false < ' de , D > ( deserializer : D ) -> Result < ( ) , D :: Error >
354
+ where
355
+ D : Deserializer < ' de > ,
356
+ {
357
+ let value = bool:: deserialize ( deserializer) ?;
358
+ if !value {
359
+ Ok ( ( ) )
360
+ } else {
361
+ Err ( serde:: de:: Error :: custom ( "expected false" ) )
362
+ }
311
363
}
312
364
313
365
#[ derive( Deserialize , Serialize , Clone , Debug , JsonSchema ) ]
@@ -378,3 +430,18 @@ where
378
430
379
431
deserializer. deserialize_any ( TOrVec :: < T > ( PhantomData ) )
380
432
}
433
+
434
+ #[ cfg( test) ]
435
+ mod test {
436
+ use super :: * ;
437
+
438
+ #[ test]
439
+ fn test_baseline_high_low ( ) {
440
+ let json = r#"false"# ;
441
+ let bl = serde_json:: from_str :: < BaselineHighLow > ( json) ;
442
+ assert ! ( matches!( bl, Ok ( BaselineHighLow :: False ) ) ) ;
443
+ let json = r#""high""# ;
444
+ let bl = serde_json:: from_str :: < BaselineHighLow > ( json) ;
445
+ assert ! ( matches!( bl, Ok ( BaselineHighLow :: High ) ) ) ;
446
+ }
447
+ }
0 commit comments