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 0 : uint level ) {
71 0 : (void)type_name;
72 :
73 0 : if( level>=STACK_HEIGHT-1 ) {
74 0 : FD_LOG_WARNING(( "level %u exceeds max %u", level, STACK_HEIGHT));
75 0 : return;
76 0 : }
77 :
78 : /* Check if we are at the beginning of a collection */
79 0 : fd_rpc_json_t * self = (fd_rpc_json_t *)_self;
80 0 : if( (self->stack[ level ] & 1)==0 ) {
81 :
82 : /* Collection is empty -- print inline */
83 0 : if( fd_flamenco_type_is_collection_end( type ) ) {
84 0 : if( name )
85 0 : fd_web_reply_sprintf( self->ws, "\"%s\":", name );
86 0 : switch( type ) {
87 0 : case FD_FLAMENCO_TYPE_MAP_END:
88 0 : case FD_FLAMENCO_TYPE_ENUM_END:
89 0 : fd_web_reply_sprintf( self->ws, "{}" );
90 0 : break;
91 0 : case FD_FLAMENCO_TYPE_ARR_END:
92 0 : fd_web_reply_sprintf( self->ws, "[]" );
93 0 : break;
94 0 : }
95 0 : self->stack[ level ] = STATE_NULL;
96 0 : return;
97 0 : }
98 :
99 0 : } else {
100 0 : if( fd_flamenco_type_is_collection_end( type ) ) {
101 0 : switch( type ) {
102 0 : case FD_FLAMENCO_TYPE_MAP_END:
103 0 : fd_web_reply_sprintf( self->ws, "}" );
104 0 : break;
105 0 : case FD_FLAMENCO_TYPE_ENUM_END:
106 0 : fd_web_reply_sprintf( self->ws, "}" );
107 0 : break;
108 0 : case FD_FLAMENCO_TYPE_ARR_END:
109 0 : fd_web_reply_sprintf( self->ws, "]" );
110 0 : break;
111 0 : }
112 0 : self->stack[ level ] = STATE_NULL;
113 0 : return;
114 0 : }
115 0 : fd_web_reply_sprintf( self->ws, "," );
116 0 : }
117 :
118 : /* Print node tag */
119 0 : switch( self->stack[ level ] ) {
120 0 : case STATE_OBJECT_BEGIN:
121 0 : case STATE_OBJECT:
122 0 : if( name ) {
123 0 : fd_web_reply_sprintf( self->ws, "\"%s\":", name );
124 0 : }
125 0 : break;
126 :
127 0 : case STATE_ENUM_BEGIN:
128 0 : case STATE_ENUM:
129 0 : if( type == FD_FLAMENCO_TYPE_ENUM_DISC ) break;
130 0 : if( type != FD_FLAMENCO_TYPE_MAP ) {
131 0 : if( name ) {
132 0 : fd_web_reply_sprintf( self->ws, "\"%s\":", name );
133 0 : }
134 0 : } else {
135 0 : fd_web_reply_sprintf( self->ws, "\"info\":" );
136 0 : }
137 0 : break;
138 0 : }
139 :
140 : /* Print node value */
141 0 : switch( type ) {
142 0 : case FD_FLAMENCO_TYPE_MAP:
143 0 : self->stack[ level+1 ] = STATE_OBJECT_BEGIN;
144 0 : fd_web_reply_sprintf( self->ws, "{" );
145 0 : break;
146 0 : case FD_FLAMENCO_TYPE_ENUM:
147 0 : self->stack[ level+1 ] = STATE_ENUM_BEGIN;
148 0 : fd_web_reply_sprintf( self->ws, "{" );
149 0 : break;
150 0 : case FD_FLAMENCO_TYPE_ARR:
151 0 : self->stack[ level+1 ] = STATE_ARRAY_BEGIN;
152 0 : fd_web_reply_sprintf( self->ws, "[" );
153 0 : break;
154 :
155 0 : case FD_FLAMENCO_TYPE_NULL:
156 0 : fd_web_reply_sprintf( self->ws, "null" );
157 0 : break;
158 0 : case FD_FLAMENCO_TYPE_BOOL:
159 0 : fd_web_reply_sprintf( self->ws, "%s", (*(uchar const *)arg) ? "true" : "false" );
160 0 : break;
161 0 : case FD_FLAMENCO_TYPE_UCHAR:
162 0 : fd_web_reply_sprintf( self->ws, "%u", *(uchar const *)arg );
163 0 : break;
164 0 : case FD_FLAMENCO_TYPE_SCHAR:
165 0 : fd_web_reply_sprintf( self->ws, "%d", *(schar const *)arg );
166 0 : break;
167 0 : case FD_FLAMENCO_TYPE_USHORT:
168 0 : fd_web_reply_sprintf( self->ws, "%u", *(ushort const *)arg );
169 0 : break;
170 0 : case FD_FLAMENCO_TYPE_SSHORT:
171 0 : fd_web_reply_sprintf( self->ws, "%d", *(short const *)arg );
172 0 : break;
173 0 : case FD_FLAMENCO_TYPE_UINT:
174 0 : fd_web_reply_sprintf( self->ws, "%u", *(uint const *)arg );
175 0 : break;
176 0 : case FD_FLAMENCO_TYPE_SINT:
177 0 : fd_web_reply_sprintf( self->ws, "%d", *(int const *)arg );
178 0 : break;
179 0 : case FD_FLAMENCO_TYPE_ULONG:
180 0 : fd_web_reply_sprintf( self->ws, "%lu", *(ulong const *)arg );
181 0 : break;
182 0 : case FD_FLAMENCO_TYPE_SLONG:
183 0 : fd_web_reply_sprintf( self->ws, "%ld", *(long const *)arg );
184 0 : break;
185 0 : # if FD_HAS_INT128
186 0 : case FD_FLAMENCO_TYPE_UINT128:
187 0 : case FD_FLAMENCO_TYPE_SINT128: {
188 0 : uint128 v = *(uint128 const *)arg;
189 0 : fd_web_reply_sprintf( self->ws, "%s: 0x%016lx%016lx", name,
190 0 : (ulong)(v>>64), (ulong)v );
191 0 : break;
192 0 : }
193 0 : # endif
194 0 : case FD_FLAMENCO_TYPE_FLOAT:
195 0 : fd_web_reply_sprintf( self->ws, "%f", (double)( *(float const *)arg ) );
196 0 : break;
197 0 : case FD_FLAMENCO_TYPE_DOUBLE:
198 0 : fd_web_reply_sprintf( self->ws, "%f", *(double const *)arg );
199 0 : break;
200 0 : case FD_FLAMENCO_TYPE_HASH256: {
201 0 : char buf[ FD_BASE58_ENCODED_32_SZ ];
202 0 : fd_base58_encode_32( arg, NULL, buf );
203 0 : fd_web_reply_sprintf( self->ws, "\"%s\"", buf );
204 0 : break;
205 0 : }
206 0 : case FD_FLAMENCO_TYPE_SIG512: {
207 0 : char buf[ FD_BASE58_ENCODED_64_SZ ];
208 0 : fd_base58_encode_64( arg, NULL, buf );
209 0 : fd_web_reply_sprintf( self->ws, "\"%s\"", buf );
210 0 : break;
211 0 : }
212 0 : case FD_FLAMENCO_TYPE_CSTR:
213 0 : fd_web_reply_sprintf( self->ws, "\"%s\"", (char const *)arg );
214 0 : break;
215 :
216 0 : case FD_FLAMENCO_TYPE_ENUM_DISC:
217 0 : fd_web_reply_sprintf( self->ws, "\"type\":\"%s\"", name );
218 0 : break;
219 :
220 0 : default:
221 0 : FD_LOG_CRIT(( "unknown type %#x", (uint)type ));
222 0 : break;
223 0 : }
224 :
225 : /* Remember that we processed an element in the current level */
226 0 : self->stack[ level ] |= 1;
227 0 : }
|