@@ -437,7 +437,7 @@ pub struct SubmissionFeedbackQuestion {
437437 pub kind : SubmissionFeedbackKind ,
438438}
439439
440- #[ derive( Debug , PartialEq , Eq , JsonSchema ) ]
440+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , JsonSchema ) ]
441441#[ cfg_attr( feature = "ts-rs" , derive( ts_rs:: TS ) ) ]
442442pub enum SubmissionFeedbackKind {
443443 Text ,
@@ -449,7 +449,22 @@ impl<'de> Deserialize<'de> for SubmissionFeedbackKind {
449449 where
450450 D : Deserializer < ' de > ,
451451 {
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)
453468 }
454469}
455470
@@ -458,19 +473,53 @@ impl Serialize for SubmissionFeedbackKind {
458473 where
459474 S : Serializer ,
460475 {
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+ } ,
464482 } ;
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 { } )
466515 }
467516}
468517
469- struct SubmissionFeedbackKindVisitor { }
518+ struct SubmissionFeedbackKindStringVisitor { }
470519
471520// 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 ;
474523
475524 fn expecting ( & self , formatter : & mut fmt:: Formatter ) -> fmt:: Result {
476525 formatter. write_str ( "\" text\" or \" intrange[x..y]\" " )
@@ -485,7 +534,7 @@ impl<'de> Visitor<'de> for SubmissionFeedbackKindVisitor {
485534 Lazy :: new ( || Regex :: new ( r#"intrange\[(\d+)\.\.(\d+)\]"# ) . unwrap ( ) ) ;
486535
487536 if value == "text" {
488- Ok ( SubmissionFeedbackKind :: Text )
537+ Ok ( SubmissionFeedbackKindString :: Text )
489538 } else if let Some ( captures) = RANGE . captures ( value) {
490539 let lower = & captures[ 1 ] ;
491540 let lower = u32:: from_str ( lower) . map_err ( |e| {
@@ -495,7 +544,7 @@ impl<'de> Visitor<'de> for SubmissionFeedbackKindVisitor {
495544 let upper = u32:: from_str ( upper) . map_err ( |e| {
496545 E :: custom ( format ! ( "error parsing intrange upper bound {upper}: {e}" ) )
497546 } ) ?;
498- Ok ( SubmissionFeedbackKind :: IntRange { lower, upper } )
547+ Ok ( SubmissionFeedbackKindString :: IntRange { lower, upper } )
499548 } else {
500549 Err ( E :: custom ( "expected \" text\" or \" intrange[x..y]\" " ) )
501550 }
@@ -601,7 +650,7 @@ mod test {
601650 }
602651
603652 #[ test]
604- fn feedback_kind_de ( ) {
653+ fn feedback_kind_de_server ( ) {
605654 init ( ) ;
606655
607656 let text = serde_json:: json!( "text" ) ;
@@ -619,17 +668,31 @@ mod test {
619668 }
620669 }
621670
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+
622686 #[ test]
623687 fn feedback_kind_se ( ) {
624688 init ( ) ;
625- use serde_json:: Value ;
626689
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""# ) ;
630693
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}}"# ) ;
634697 }
635698}
0 commit comments