@@ -65,4 +65,74 @@ public async Task ErrorState2_Tests()
6565 await Assert . That ( JsonSerializer . Deserialize < ErrorState < string > > ( success , options ) ) . IsSuccess ( ) ;
6666 await Assert . That ( JsonSerializer . Deserialize < ErrorState < string > > ( error , options ) ) . IsError ( "custom error message" ) ;
6767 }
68+
69+ private sealed class Holder
70+ {
71+ public Option < int > Option { get ; set ; }
72+ public Result < int > Result { get ; set ; }
73+ public Result < int , string > Result2 { get ; set ; }
74+ public ErrorState ErrorState { get ; set ; }
75+ public ErrorState < string > ErrorState2 { get ; set ; }
76+ public int After { get ; set ; }
77+ }
78+
79+ [ Test ]
80+ public async Task Nested_AllSuccess_PreservesTrailingProperty ( )
81+ {
82+ var holder = new Holder
83+ {
84+ Option = Option . Success ( 1 ) ,
85+ Result = Result . Success ( 2 ) ,
86+ Result2 = Result . Success < int , string > ( 3 ) ,
87+ ErrorState = ErrorState . Success ( ) ,
88+ ErrorState2 = ErrorState . Success < string > ( ) ,
89+ After = 42 ,
90+ } ;
91+
92+ var json = JsonSerializer . Serialize ( holder , options ) ;
93+ var back = JsonSerializer . Deserialize < Holder > ( json , options ) ! ;
94+
95+ await Assert . That ( back . Option ) . IsSuccess ( 1 ) ;
96+ await Assert . That ( back . Result ) . IsSuccess ( 2 ) ;
97+ await Assert . That ( back . Result2 ) . IsSuccess ( 3 ) ;
98+ await Assert . That ( back . ErrorState ) . IsSuccess ( ) ;
99+ await Assert . That ( back . ErrorState2 ) . IsSuccess ( ) ;
100+ await Assert . That ( back . After ) . IsEqualTo ( 42 ) ;
101+ }
102+
103+ [ Test ]
104+ public async Task Nested_AllError_PreservesTrailingProperty ( )
105+ {
106+ var holder = new Holder
107+ {
108+ Option = Option . Error < int > ( ) ,
109+ Result = Result . Error < int > ( new InvalidOperationException ( "r" ) ) ,
110+ Result2 = Result . Error < int , string > ( "r2" ) ,
111+ ErrorState = ErrorState . Error ( new InvalidOperationException ( "e" ) ) ,
112+ ErrorState2 = ErrorState . Error ( "e2" ) ,
113+ After = 99 ,
114+ } ;
115+
116+ var json = JsonSerializer . Serialize ( holder , options ) ;
117+ var back = JsonSerializer . Deserialize < Holder > ( json , options ) ! ;
118+
119+ await Assert . That ( back . Option ) . IsError ( ) ;
120+ await Assert . That ( back . Result ) . IsError ( e => e is InvalidOperationException { Message : "r" } ) ;
121+ await Assert . That ( back . Result2 ) . IsError ( "r2" ) ;
122+ await Assert . That ( back . ErrorState ) . IsError ( e => e is InvalidOperationException { Message : "e" } ) ;
123+ await Assert . That ( back . ErrorState2 ) . IsError ( "e2" ) ;
124+ await Assert . That ( back . After ) . IsEqualTo ( 99 ) ;
125+ }
126+
127+ [ Test ]
128+ public async Task Nested_Option_Null_PreservesTrailingProperty ( )
129+ {
130+ // regression: an error-state Option<int> (serialized as null) used to over-advance
131+ // the reader and skip the following property.
132+ var json = """{"Option":null,"After":7}""" ;
133+ var back = JsonSerializer . Deserialize < Holder > ( json , options ) ! ;
134+
135+ await Assert . That ( back . Option ) . IsError ( ) ;
136+ await Assert . That ( back . After ) . IsEqualTo ( 7 ) ;
137+ }
68138}
0 commit comments