Line data Source code
1 : #include "fd_stub_to_json.h"
2 : #include "../../ballet/base58/fd_base58.h"
3 :
4 : /* STATE_{...} identify the state of the JSON writer. This is used
5 : because assembling the JSON stream requires different combinations
6 : of print operations depending on the sequence of AST nodes. */
7 :
8 0 : #define STATE_NULL (0) /* Sentinel value */
9 0 : #define STATE_OBJECT_BEGIN (2) /* Writing object, ==0 elems so far */
10 0 : #define STATE_OBJECT (3) /* Writing object, >0 elems so far */
11 0 : #define STATE_ARRAY_BEGIN (4) /* Writing array, ==0 elems so far */
12 : #define STATE_ARRAY (5) /* Writing array, >0 elems so far */
13 0 : #define STATE_ENUM_BEGIN (6) /* Writing enum, ==0 elems so far */
14 0 : #define STATE_ENUM (7) /* Writing enum, >0 elems so far */
15 : #define STATE_OPTION_BEGIN (8) /* Writing nullable, waiting for elem */
16 :
17 0 : #define STACK_HEIGHT 64U
18 : struct fd_rpc_json {
19 : fd_webserver_t * ws;
20 : int stack[ STACK_HEIGHT ];
21 : };
22 :
23 :
24 : ulong
25 0 : fd_rpc_json_align( void ) {
26 0 : return alignof(fd_rpc_json_t);
27 0 : }
28 :
29 : ulong
30 0 : fd_rpc_json_footprint( void ) {
31 0 : return sizeof(fd_rpc_json_t);
32 0 : }
33 :
34 : fd_rpc_json_t *
35 0 : fd_rpc_json_new( void * mem ) {
36 :
37 0 : if( FD_UNLIKELY( !mem ) ) {
38 0 : FD_LOG_WARNING(( "NULL mem" ));
39 0 : return NULL;
40 0 : }
41 :
42 0 : fd_rpc_json_t * json = (fd_rpc_json_t *)mem;
43 0 : memset( json, 0, sizeof(*json) );
44 0 : return (fd_rpc_json_t *)mem;
45 0 : }
46 :
47 : void *
48 0 : fd_rpc_json_delete( fd_rpc_json_t * json ) {
49 0 : return json;
50 0 : }
51 :
52 : fd_rpc_json_t *
53 0 : fd_rpc_json_init( fd_rpc_json_t * self, fd_webserver_t * ws ) {
54 :
55 0 : if( FD_UNLIKELY( !self ) ) {
56 0 : FD_LOG_WARNING(( "NULL self" ));
57 0 : return NULL;
58 0 : }
59 0 : self->ws = ws;
60 :
61 0 : return self;
62 0 : }
63 :
64 : void
65 : fd_rpc_json_walk( void * _self,
66 : void const * arg,
67 : char const * name,
68 : int type,
69 : char const * type_name,
70 : uint level,
71 0 : uint varint ) {
72 0 : (void)type_name;
73 0 : (void)varint;
74 :
75 0 : if( level>=STACK_HEIGHT-1 ) {
76 0 : FD_LOG_WARNING(( "level %u exceeds max %u", level, STACK_HEIGHT));
77 0 : return;
78 0 : }
79 :
80 : /* Check if we are at the beginning of a collection */
81 0 : fd_rpc_json_t * self = (fd_rpc_json_t *)_self;
82 0 : if( (self->stack[ level ] & 1)==0 ) {
83 :
84 : /* Collection is empty -- print inline */
85 0 : if( fd_flamenco_type_is_collection_end( type ) ) {
86 0 : if( name )
87 0 : fd_web_reply_sprintf( self->ws, "\"%s\":", name );
88 0 : switch( type ) {
89 0 : case FD_FLAMENCO_TYPE_MAP_END:
90 0 : case FD_FLAMENCO_TYPE_ENUM_END:
91 0 : fd_web_reply_sprintf( self->ws, "{}" );
92 0 : break;
93 0 : case FD_FLAMENCO_TYPE_ARR_END:
94 0 : fd_web_reply_sprintf( self->ws, "[]" );
95 0 : break;
96 0 : }
97 0 : self->stack[ level ] = STATE_NULL;
98 0 : return;
99 0 : }
100 :
101 0 : } else {
102 0 : if( fd_flamenco_type_is_collection_end( type ) ) {
103 0 : switch( type ) {
104 0 : case FD_FLAMENCO_TYPE_MAP_END:
105 0 : fd_web_reply_sprintf( self->ws, "}" );
106 0 : break;
107 0 : case FD_FLAMENCO_TYPE_ENUM_END:
108 0 : fd_web_reply_sprintf( self->ws, "}" );
109 0 : break;
110 0 : case FD_FLAMENCO_TYPE_ARR_END:
111 0 : fd_web_reply_sprintf( self->ws, "]" );
112 0 : break;
113 0 : }
114 0 : self->stack[ level ] = STATE_NULL;
115 0 : return;
116 0 : }
117 0 : fd_web_reply_sprintf( self->ws, "," );
118 0 : }
119 :
120 : /* Print node tag */
121 0 : switch( self->stack[ level ] ) {
122 0 : case STATE_OBJECT_BEGIN:
123 0 : case STATE_OBJECT:
124 0 : if( name ) {
125 0 : fd_web_reply_sprintf( self->ws, "\"%s\":", name );
126 0 : }
127 0 : break;
128 :
129 0 : case STATE_ENUM_BEGIN:
130 0 : case STATE_ENUM:
131 0 : if( type == FD_FLAMENCO_TYPE_ENUM_DISC ) break;
132 0 : if( type != FD_FLAMENCO_TYPE_MAP ) {
133 0 : if( name ) {
134 0 : fd_web_reply_sprintf( self->ws, "\"%s\":", name );
135 0 : }
136 0 : } else {
137 0 : fd_web_reply_sprintf( self->ws, "\"info\":" );
138 0 : }
139 0 : break;
140 0 : }
141 :
142 : /* Print node value */
143 0 : switch( type ) {
144 0 : case FD_FLAMENCO_TYPE_MAP:
145 0 : self->stack[ level+1 ] = STATE_OBJECT_BEGIN;
146 0 : fd_web_reply_sprintf( self->ws, "{" );
147 0 : break;
148 0 : case FD_FLAMENCO_TYPE_ENUM:
149 0 : self->stack[ level+1 ] = STATE_ENUM_BEGIN;
150 0 : fd_web_reply_sprintf( self->ws, "{" );
151 0 : break;
152 0 : case FD_FLAMENCO_TYPE_ARR:
153 0 : self->stack[ level+1 ] = STATE_ARRAY_BEGIN;
154 0 : fd_web_reply_sprintf( self->ws, "[" );
155 0 : break;
156 :
157 0 : case FD_FLAMENCO_TYPE_NULL:
158 0 : fd_web_reply_sprintf( self->ws, "null" );
159 0 : break;
160 0 : case FD_FLAMENCO_TYPE_BOOL:
161 0 : fd_web_reply_sprintf( self->ws, "%s", (*(uchar const *)arg) ? "true" : "false" );
162 0 : break;
163 0 : case FD_FLAMENCO_TYPE_UCHAR:
164 0 : fd_web_reply_sprintf( self->ws, "%u", *(uchar const *)arg );
165 0 : break;
166 0 : case FD_FLAMENCO_TYPE_SCHAR:
167 0 : fd_web_reply_sprintf( self->ws, "%d", *(schar const *)arg );
168 0 : break;
169 0 : case FD_FLAMENCO_TYPE_USHORT:
170 0 : fd_web_reply_sprintf( self->ws, "%u", *(ushort const *)arg );
171 0 : break;
172 0 : case FD_FLAMENCO_TYPE_SSHORT:
173 0 : fd_web_reply_sprintf( self->ws, "%d", *(short const *)arg );
174 0 : break;
175 0 : case FD_FLAMENCO_TYPE_UINT:
176 0 : fd_web_reply_sprintf( self->ws, "%u", *(uint const *)arg );
177 0 : break;
178 0 : case FD_FLAMENCO_TYPE_SINT:
179 0 : fd_web_reply_sprintf( self->ws, "%d", *(int const *)arg );
180 0 : break;
181 0 : case FD_FLAMENCO_TYPE_ULONG:
182 0 : fd_web_reply_sprintf( self->ws, "%lu", *(ulong const *)arg );
183 0 : break;
184 0 : case FD_FLAMENCO_TYPE_SLONG:
185 0 : fd_web_reply_sprintf( self->ws, "%ld", *(long const *)arg );
186 0 : break;
187 0 : # if FD_HAS_INT128
188 0 : case FD_FLAMENCO_TYPE_UINT128:
189 0 : case FD_FLAMENCO_TYPE_SINT128: {
190 0 : uint128 v = *(uint128 const *)arg;
191 0 : fd_web_reply_sprintf( self->ws, "%s: 0x%016lx%016lx", name,
192 0 : (ulong)(v>>64), (ulong)v );
193 0 : break;
194 0 : }
195 0 : # endif
196 0 : case FD_FLAMENCO_TYPE_FLOAT:
197 0 : fd_web_reply_sprintf( self->ws, "%f", (double)( *(float const *)arg ) );
198 0 : break;
199 0 : case FD_FLAMENCO_TYPE_DOUBLE:
200 0 : fd_web_reply_sprintf( self->ws, "%f", *(double const *)arg );
201 0 : break;
202 0 : case FD_FLAMENCO_TYPE_HASH256: {
203 0 : char buf[ FD_BASE58_ENCODED_32_SZ ];
204 0 : fd_base58_encode_32( arg, NULL, buf );
205 0 : fd_web_reply_sprintf( self->ws, "\"%s\"", buf );
206 0 : break;
207 0 : }
208 0 : case FD_FLAMENCO_TYPE_SIG512: {
209 0 : char buf[ FD_BASE58_ENCODED_64_SZ ];
210 0 : fd_base58_encode_64( arg, NULL, buf );
211 0 : fd_web_reply_sprintf( self->ws, "\"%s\"", buf );
212 0 : break;
213 0 : }
214 0 : case FD_FLAMENCO_TYPE_CSTR:
215 0 : fd_web_reply_sprintf( self->ws, "\"%s\"", (char const *)arg );
216 0 : break;
217 :
218 0 : case FD_FLAMENCO_TYPE_ENUM_DISC:
219 0 : fd_web_reply_sprintf( self->ws, "\"type\":\"%s\"", name );
220 0 : break;
221 :
222 0 : default:
223 0 : FD_LOG_CRIT(( "unknown type %#x", (uint)type ));
224 0 : break;
225 0 : }
226 :
227 : /* Remember that we processed an element in the current level */
228 0 : self->stack[ level ] |= 1;
229 0 : }
|