@@ -437,7 +437,7 @@ pub struct SubmissionFeedbackQuestion {
437
437
pub kind : SubmissionFeedbackKind ,
438
438
}
439
439
440
- #[ derive( Debug , PartialEq , Eq , JsonSchema ) ]
440
+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , JsonSchema ) ]
441
441
#[ cfg_attr( feature = "ts-rs" , derive( ts_rs:: TS ) ) ]
442
442
pub enum SubmissionFeedbackKind {
443
443
Text ,
@@ -449,7 +449,22 @@ impl<'de> Deserialize<'de> for SubmissionFeedbackKind {
449
449
where
450
450
D : Deserializer < ' de > ,
451
451
{
452
- deserializer. deserialize_string ( SubmissionFeedbackKindVisitor { } )
452
+ let wrapper = SubmissionFeedbackKindWrapper :: deserialize ( deserializer) ?;
453
+ let kind = match wrapper {
454
+ SubmissionFeedbackKindWrapper :: String ( string) => match string {
455
+ SubmissionFeedbackKindString :: Text => Self :: Text ,
456
+ SubmissionFeedbackKindString :: IntRange { lower, upper } => {
457
+ Self :: IntRange { lower, upper }
458
+ }
459
+ } ,
460
+ SubmissionFeedbackKindWrapper :: Derived ( derived) => match derived {
461
+ SubmissionFeedbackKindDerived :: Text => Self :: Text ,
462
+ SubmissionFeedbackKindDerived :: IntRange { lower, upper } => {
463
+ Self :: IntRange { lower, upper }
464
+ }
465
+ } ,
466
+ } ;
467
+ Ok ( kind)
453
468
}
454
469
}
455
470
@@ -458,19 +473,53 @@ impl Serialize for SubmissionFeedbackKind {
458
473
where
459
474
S : Serializer ,
460
475
{
461
- let s = match self {
462
- Self :: Text => "text" . to_string ( ) ,
463
- Self :: IntRange { lower, upper } => format ! ( "intrange[{lower}..{upper}]" ) ,
476
+ let derived = match self {
477
+ Self :: Text => SubmissionFeedbackKindDerived :: Text ,
478
+ Self :: IntRange { lower, upper } => SubmissionFeedbackKindDerived :: IntRange {
479
+ lower : * lower,
480
+ upper : * upper,
481
+ } ,
464
482
} ;
465
- serializer. serialize_str ( & s)
483
+ derived. serialize ( serializer)
484
+ }
485
+ }
486
+
487
+ // wraps the two stringly typed and rusty versions of the kind
488
+ #[ derive( Debug , Clone , Copy , Deserialize ) ]
489
+ #[ serde( untagged) ]
490
+ enum SubmissionFeedbackKindWrapper {
491
+ Derived ( SubmissionFeedbackKindDerived ) ,
492
+ String ( SubmissionFeedbackKindString ) ,
493
+ }
494
+
495
+ // uses derived serde impls
496
+ #[ derive( Debug , Clone , Copy , Deserialize , Serialize ) ]
497
+ enum SubmissionFeedbackKindDerived {
498
+ Text ,
499
+ IntRange { lower : u32 , upper : u32 } ,
500
+ }
501
+
502
+ // the stringly typed "text" or "intrange" that comes from the server
503
+ #[ derive( Debug , Clone , Copy ) ]
504
+ enum SubmissionFeedbackKindString {
505
+ Text ,
506
+ IntRange { lower : u32 , upper : u32 } ,
507
+ }
508
+
509
+ impl < ' de > Deserialize < ' de > for SubmissionFeedbackKindString {
510
+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
511
+ where
512
+ D : Deserializer < ' de > ,
513
+ {
514
+ deserializer. deserialize_string ( SubmissionFeedbackKindStringVisitor { } )
466
515
}
467
516
}
468
517
469
- struct SubmissionFeedbackKindVisitor { }
518
+ struct SubmissionFeedbackKindStringVisitor { }
470
519
471
520
// parses "text" into Text, and "intrange[x..y]" into IntRange {lower: x, upper: y}
472
- impl < ' de > Visitor < ' de > for SubmissionFeedbackKindVisitor {
473
- type Value = SubmissionFeedbackKind ;
521
+ impl < ' de > Visitor < ' de > for SubmissionFeedbackKindStringVisitor {
522
+ type Value = SubmissionFeedbackKindString ;
474
523
475
524
fn expecting ( & self , formatter : & mut fmt:: Formatter ) -> fmt:: Result {
476
525
formatter. write_str ( "\" text\" or \" intrange[x..y]\" " )
@@ -485,7 +534,7 @@ impl<'de> Visitor<'de> for SubmissionFeedbackKindVisitor {
485
534
Lazy :: new ( || Regex :: new ( r#"intrange\[(\d+)\.\.(\d+)\]"# ) . unwrap ( ) ) ;
486
535
487
536
if value == "text" {
488
- Ok ( SubmissionFeedbackKind :: Text )
537
+ Ok ( SubmissionFeedbackKindString :: Text )
489
538
} else if let Some ( captures) = RANGE . captures ( value) {
490
539
let lower = & captures[ 1 ] ;
491
540
let lower = u32:: from_str ( lower) . map_err ( |e| {
@@ -495,7 +544,7 @@ impl<'de> Visitor<'de> for SubmissionFeedbackKindVisitor {
495
544
let upper = u32:: from_str ( upper) . map_err ( |e| {
496
545
E :: custom ( format ! ( "error parsing intrange upper bound {upper}: {e}" ) )
497
546
} ) ?;
498
- Ok ( SubmissionFeedbackKind :: IntRange { lower, upper } )
547
+ Ok ( SubmissionFeedbackKindString :: IntRange { lower, upper } )
499
548
} else {
500
549
Err ( E :: custom ( "expected \" text\" or \" intrange[x..y]\" " ) )
501
550
}
@@ -601,7 +650,7 @@ mod test {
601
650
}
602
651
603
652
#[ test]
604
- fn feedback_kind_de ( ) {
653
+ fn feedback_kind_de_server ( ) {
605
654
init ( ) ;
606
655
607
656
let text = serde_json:: json!( "text" ) ;
@@ -619,17 +668,31 @@ mod test {
619
668
}
620
669
}
621
670
671
+ #[ test]
672
+ fn feedback_kind_de_rust ( ) {
673
+ init ( ) ;
674
+
675
+ let original = SubmissionFeedbackKind :: Text ;
676
+ let json = serde_json:: to_string ( & original) . unwrap ( ) ;
677
+ let deserialized: SubmissionFeedbackKind = deserialize:: json_from_str ( & json) . unwrap ( ) ;
678
+ assert_eq ! ( deserialized, original) ;
679
+
680
+ let original = SubmissionFeedbackKind :: IntRange { lower : 1 , upper : 5 } ;
681
+ let json = serde_json:: to_string ( & original) . unwrap ( ) ;
682
+ let deserialized: SubmissionFeedbackKind = deserialize:: json_from_str ( & json) . unwrap ( ) ;
683
+ assert_eq ! ( deserialized, original) ;
684
+ }
685
+
622
686
#[ test]
623
687
fn feedback_kind_se ( ) {
624
688
init ( ) ;
625
- use serde_json:: Value ;
626
689
627
- let text = SubmissionFeedbackKind :: Text ;
628
- let text = serde_json:: to_value ( & text ) . unwrap ( ) ;
629
- assert_eq ! ( text , Value :: String ( "text" . to_string ( ) ) ) ;
690
+ let original = SubmissionFeedbackKind :: Text ;
691
+ let json = serde_json:: to_string ( & original ) . unwrap ( ) ;
692
+ assert_eq ! ( json , r#""Text""# ) ;
630
693
631
- let range = SubmissionFeedbackKind :: IntRange { lower : 1 , upper : 5 } ;
632
- let range = serde_json:: to_value ( & range ) . unwrap ( ) ;
633
- assert_eq ! ( range , Value :: String ( "intrange[1..5]" . to_string ( ) ) ) ;
694
+ let original = SubmissionFeedbackKind :: IntRange { lower : 1 , upper : 5 } ;
695
+ let json = serde_json:: to_string ( & original ) . unwrap ( ) ;
696
+ assert_eq ! ( json , r#"{"IntRange":{"lower":1,"upper":5}}"# ) ;
634
697
}
635
698
}
0 commit comments