11using System ;
2+ using System . Collections . Generic ;
23using System . Diagnostics ;
34using System . Formats . Cbor ;
45using EdjCase . ICP . Agent . Models ;
@@ -9,35 +10,63 @@ namespace EdjCase.ICP.Agent.Responses
910 /// <summary>
1011 /// Model for a reponse to a read state request
1112 /// </summary>
12- public class V3CallResponse
13+ internal class V3CallResponse
1314 {
15+ public enum StatusType
16+ {
17+ /// <summary>
18+ /// The request has been processed and it has reply data
19+ /// </summary>
20+ Replied ,
21+ NonReplicatedRejection
22+ }
23+
24+
1425 /// <summary>
15- /// The status of the call ('replied', 'rejected', 'done )
26+ /// The status of the call ('replied', 'non_replicated_rejection' )
1627 /// </summary>
17- public string Status { get ; }
28+ public StatusType Status { get ; }
29+
30+ private object ? value { get ; }
31+
32+ /// <param name="status">The status of the call ('replied', 'non_replicated_rejection')</param>
33+ /// <param name="value">The certificate data of the current canister state</param>
34+ private V3CallResponse ( StatusType status , object ? value )
35+ {
36+ this . Status = status ;
37+ this . value = value ;
38+ }
39+
1840 /// <summary>
19- /// The certificate data of the current canister state
41+ /// Returns the 'replied' certificate IF the status is 'replied', otherwise throws exception
2042 /// </summary>
21- public Certificate Certificate { get ; }
43+ public Certificate AsReplied ( )
44+ {
45+ this . ValidateType ( StatusType . Replied ) ;
46+ return ( Certificate ) this . value ! ;
47+ }
2248
23- /// <param name="status">The status of the call ('replied', 'rejected', 'done)</param>
24- /// <param name="certificate">The certificate data of the current canister state</param>
25- /// <exception cref="ArgumentNullException"></exception>
26- public V3CallResponse ( string status , Certificate certificate )
49+ public CallRejectedResponse AsNonReplicatedRejection ( )
2750 {
28- this . Status = status ?? throw new ArgumentNullException ( nameof ( status ) ) ;
29- this . Certificate = certificate ?? throw new ArgumentNullException ( nameof ( certificate ) ) ;
51+ this . ValidateType ( StatusType . NonReplicatedRejection ) ;
52+ return ( CallRejectedResponse ) this . value ! ;
3053 }
3154
55+ private void ValidateType ( StatusType type )
56+ {
57+ if ( this . Status != type )
58+ {
59+ throw new InvalidOperationException ( $ "Expected status '{ type } ' but was '{ this . Status } '") ;
60+ }
61+ }
3262
3363 internal static V3CallResponse ReadCbor ( CborReader reader )
3464 {
3565 if ( reader . ReadTag ( ) != CborTag . SelfDescribeCbor )
3666 {
3767 throw new CborContentException ( "Expected self describe tag" ) ;
3868 }
39- Certificate ? certificate = null ;
40- string ? status = null ;
69+ Dictionary < string , object > map = new ( ) ;
4170 reader . ReadStartMap ( ) ;
4271 while ( reader . PeekState ( ) != CborReaderState . EndMap )
4372 {
@@ -46,10 +75,19 @@ internal static V3CallResponse ReadCbor(CborReader reader)
4675 {
4776 case "certificate" :
4877 var certReader = new CborReader ( reader . ReadByteString ( ) ) ;
49- certificate = Certificate . FromCbor ( certReader ) ;
78+ map [ " certificate" ] = Certificate . FromCbor ( certReader ) ;
5079 break ;
5180 case "status" :
52- status = reader . ReadTextString ( ) ;
81+ map [ "status" ] = reader . ReadTextString ( ) ;
82+ break ;
83+ case "reject_code" :
84+ map [ "reject_code" ] = ( RejectCode ) reader . ReadUInt64 ( ) ;
85+ break ;
86+ case "reject_message" :
87+ map [ "reject_message" ] = reader . ReadTextString ( ) ;
88+ break ;
89+ case "error_code" :
90+ map [ "error_code" ] = reader . ReadTextString ( ) ;
5391 break ;
5492 default :
5593 Debug . WriteLine ( $ "Unknown field '{ field } ' in v3 call response") ;
@@ -59,17 +97,30 @@ internal static V3CallResponse ReadCbor(CborReader reader)
5997 }
6098 reader . ReadEndMap ( ) ;
6199
62- if ( status == null )
100+ if ( map [ " status" ] == null )
63101 {
64102 throw new CborContentException ( "Missing field: status" ) ;
65103 }
104+ StatusType status = Enum . Parse < StatusType > ( ( string ) map [ "status" ] , true ) ;
66105
67- if ( certificate == null )
106+ switch ( status )
68107 {
69- throw new CborContentException ( "Missing field: certificate" ) ;
108+ case StatusType . Replied :
109+ Certificate ? certificate = map [ "certificate" ] as Certificate ;
110+ if ( certificate == null )
111+ {
112+ throw new CborContentException ( "Missing field: certificate" ) ;
113+ }
114+ return new V3CallResponse ( status , certificate ) ;
115+ case StatusType . NonReplicatedRejection :
116+ RejectCode rejectCode = ( RejectCode ) ( map [ "reject_code" ] ?? throw new CborContentException ( "Missing field: reject_code" ) ) ;
117+ string message = ( string ) ( map [ "reject_message" ] ?? throw new CborContentException ( "Missing field: reject_message" ) ) ;
118+ string ? errorCode = ( string ? ) map [ "error_code" ] ;
119+ CallRejectedResponse ? rejectedResponse = new CallRejectedResponse ( rejectCode , message , errorCode ) ;
120+ return new V3CallResponse ( status , rejectedResponse ) ;
121+ default :
122+ throw new NotImplementedException ( $ "Unknown status '{ status } ' in v3 call response") ;
70123 }
71-
72- return new V3CallResponse ( status , certificate ) ;
73124 }
74125 }
75- }
126+ }
0 commit comments