Source file pb_parsing_parse_tree.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
(** Protobuf parse tree *)
type message_field_label =
[ `Optional
| `Required
| `Repeated
| `Nolabel
]
(** A field property defining its occurence
*)
type oneof_field_label = unit
(** Oneof field fields label
Oneof fields have no label, they are simply choices for the
oneof fiel they belong to. *)
type 'a field = {
field_name: string;
field_number: int;
field_label: 'a;
field_type: Pb_field_type.unresolved_t;
field_options: Pb_option.set;
}
(** message field.
Note this field is parametrized with the label type
so that it can be used both by normal field and one of
field since the only difference between the 2 is
the label.
*)
type message_field = message_field_label field
type oneof_field = oneof_field_label field
type map_field = {
map_name: string;
map_number: int;
map_key_type: Pb_field_type.map_key_type;
map_value_type: Pb_field_type.unresolved_t;
map_options: Pb_option.set;
}
type oneof_body_content =
| Oneof_field of oneof_field
| Oneof_option of Pb_option.t
type oneof = {
oneof_name: string;
oneof_body: oneof_body_content list;
}
(** oneof entity *)
type enum_value = {
enum_value_name: string;
enum_value_int: int;
enum_value_options: Pb_option.set;
}
type enum_body_content =
| Enum_value of enum_value
| Enum_option of Pb_option.t
type enum = {
enum_id: int;
enum_name: string;
enum_body: enum_body_content list;
}
type extension_range_to =
| To_max
| To_number of int
type extension_range_from = int
type extension_range =
| Extension_single_number of int
| Extension_range of extension_range_from * extension_range_to
(** Body content defines all the possible consituant
of a message.
*)
type message_body_content =
| Message_field of message_field
| Message_map_field of map_field
| Message_oneof_field of oneof
| Message_sub of message
| Message_enum of enum
| Message_extension of extension_range list
| Message_reserved of extension_range list
| Message_option of Pb_option.t
and message = {
id: int;
message_name: string;
message_body: message_body_content list;
}
(** Message entity.
Note the ID is simply for uniquely (and easily) identifying a type. It is
expected to be generated by a parser. The later compilation
functions expects this id to be unique.
*)
type rpc = {
rpc_name: string;
rpc_options: Pb_option.set;
rpc_req_stream: bool;
rpc_req: Pb_field_type.unresolved_t;
rpc_res_stream: bool;
rpc_res: Pb_field_type.unresolved_t;
}
type service_body_content =
| Service_rpc of rpc
| Service_option of Pb_option.t
type service = {
service_name: string;
service_body: service_body_content list;
}
type extend = {
id: int;
extend_name: string;
extend_body: message_field list;
}
type import = {
file_name: string;
public: bool;
}
type proto = {
proto_file_name: string option;
syntax: string option;
imports: import list;
file_options: Pb_option.set;
package: string option;
messages: message list;
services: service list;
enums: enum list;
extends: extend list;
}
(** Definition of a protobuffer message file.
*)
[@@@warning "-44"]
open Format
open Pb_format_util
let pp_message_field_label ppf label =
let label_str =
match label with
| `Optional -> "Optional"
| `Required -> "Required"
| `Repeated -> "Repeated"
| `Nolabel -> "Nolabel"
in
fprintf ppf "`%s" label_str
let pp_oneof_field_label _ppf () = ()
let pp_field pp_label ppf field =
fprintf ppf
"{@[<v 2>@,\
field_name = %S;@,\
field_number = %d;@,\
field_label = %a;@,\
field_type = %a;@,\
field_options = %a;@,\
}@]"
field.field_name field.field_number pp_label field.field_label
Pb_field_type.pp_unresolved_t field.field_type Pb_option.pp_set
field.field_options
let pp_message_field ppf field = pp_field pp_message_field_label ppf field
let pp_oneof_field ppf field = pp_field pp_oneof_field_label ppf field
let pp_map_field ppf map_field =
fprintf ppf
"{@[<v 2>@,\
map_name = %S;@,\
map_number = %d;@,\
map_key_type = %a;@,\
map_value_type = %a;@,\
map_options = %a;@,\
}@]"
map_field.map_name map_field.map_number Pb_field_type.pp_map_key_type
map_field.map_key_type Pb_field_type.pp_unresolved_t
map_field.map_value_type Pb_option.pp_set map_field.map_options
let pp_oneof_body_content ppf = function
| Oneof_field field -> pp_oneof_field ppf field
| Oneof_option option -> Pb_option.pp_t ppf option
let pp_oneof ppf oneof =
fprintf ppf "{@[<v 2>%s = %S;@,%s = [@[<v>%a@]];@,@]}" "oneof_name"
oneof.oneof_name "oneof_body"
(pp_print_list
~pp_sep:(fun ppf () -> fprintf ppf ";@,")
pp_oneof_body_content)
oneof.oneof_body
let pp_enum_value ppf enum_value =
fprintf ppf "{@[<v 2>@,enum_value_name = %S;@,enum_value_int = %d;@,}@]"
enum_value.enum_value_name enum_value.enum_value_int
let pp_enum_body_content ppf enum_body_content =
match enum_body_content with
| Enum_value enum_value -> pp_enum_value ppf enum_value
| Enum_option option -> Pb_option.pp_t ppf option
let pp_enum ppf enum =
fprintf ppf
"{@[<v 2>@,enum_id = %d;@,enum_name = %S;@,enum_body = [@[<v>%a@]];@,}@]"
enum.enum_id enum.enum_name
(pp_print_list
~pp_sep:(fun ppf () -> fprintf ppf ";@,")
pp_enum_body_content)
enum.enum_body
let pp_extension_range_to ppf ext_range_to =
match ext_range_to with
| To_max -> fprintf ppf "To_max"
| To_number n -> fprintf ppf "(To_number %d)" n
let pp_extension_range_from ppf ext_range_from = fprintf ppf "%d" ext_range_from
let pp_extension_range ppf ext_range =
match ext_range with
| Extension_single_number n -> fprintf ppf "(Extension_single_number %d)" n
| Extension_range (from, to_) ->
fprintf ppf "(Extension_range (%d, %a))" from pp_extension_range_to to_
let rec pp_message_body_content ppf msg_body_content =
match msg_body_content with
| Message_field field -> pp_message_field ppf field
| Message_map_field map_field -> pp_map_field ppf map_field
| Message_oneof_field oneof_field -> pp_oneof ppf oneof_field
| Message_sub sub_message -> pp_message ppf sub_message
| Message_enum enum -> pp_enum ppf enum
| Message_extension ext_ranges ->
fprintf ppf "Message_extension [@[<v>%a@]]"
(pp_print_list
~pp_sep:(fun ppf () -> fprintf ppf ";@,")
pp_extension_range)
ext_ranges
| Message_reserved res_ranges ->
fprintf ppf "Message_reserved [@[<v>%a@]]"
(pp_print_list
~pp_sep:(fun ppf () -> fprintf ppf ";@,")
pp_extension_range)
res_ranges
| Message_option option -> Pb_option.pp_t ppf option
and pp_message ppf message =
fprintf ppf
"{@[<v 2>@,id = %d;@,message_name = %S;@,message_body = [@[<v>%a@]];@,}@]"
message.id message.message_name
(pp_print_list
~pp_sep:(fun ppf () -> fprintf ppf ";@,")
pp_message_body_content)
message.message_body
let pp_rpc ppf rpc =
fprintf ppf
"{@[<v 2>@,\
rpc_name = %S;@,\
rpc_options = %a;@,\
rpc_req_stream = %b;@,\
rpc_req = %a;@,\
rpc_res_stream = %b;@,\
rpc_res = %a;@,\
}@]"
rpc.rpc_name Pb_option.pp_set rpc.rpc_options rpc.rpc_req_stream
Pb_field_type.pp_unresolved_t rpc.rpc_req rpc.rpc_res_stream
Pb_field_type.pp_unresolved_t rpc.rpc_res
let rec pp_service_body_content ppf service_body_content =
match service_body_content with
| Service_rpc rpc -> pp_rpc ppf rpc
| Service_option option -> Pb_option.pp_t ppf option
and pp_service ppf service =
fprintf ppf "{@[<v 2>@,service_name = %S;@,service_body = [@[<v>%a@]];@,}@]"
service.service_name
(pp_print_list
~pp_sep:(fun ppf () -> fprintf ppf ";@,")
pp_service_body_content)
service.service_body
let pp_extend ppf extend =
fprintf ppf
"{@[<v 2>@,id = %d;@,extend_name = %S;@,extend_body = [@[<v>%a@]];@,}@]"
extend.id extend.extend_name
(pp_print_list ~pp_sep:(fun ppf () -> fprintf ppf ";@,") pp_message_field)
extend.extend_body
let pp_import ppf import =
fprintf ppf "{@[<2>@,file_name = %S;@,public = %b;@,}@]" import.file_name
import.public
let pp_proto ppf proto =
fprintf ppf
"{@[<v 2>@ proto_file_name = %a;@,\
syntax = %a;@,\
imports = [@[<v>%a@]];@,\
file_options = %a;@,\
package = %a;@,\
messages = [@[<v>%a@]];@,\
services = [@[<v>%a@]];@,\
enums = [@[<v>%a@]];@,\
extends = [@[<v>%a@]];@,\
}@]"
(pp_print_option ~none:pp_none pp_print_string)
proto.proto_file_name
(pp_print_option ~none:pp_none pp_print_string)
proto.syntax
(pp_print_list ~pp_sep:(fun ppf () -> fprintf ppf ";@,") pp_import)
proto.imports Pb_option.pp_set proto.file_options
(pp_print_option ~none:pp_none pp_print_string)
proto.package
(pp_print_list ~pp_sep:(fun ppf () -> fprintf ppf ";@,") pp_message)
proto.messages
(pp_print_list ~pp_sep:(fun ppf () -> fprintf ppf ";@,") pp_service)
proto.services
(pp_print_list ~pp_sep:(fun ppf () -> fprintf ppf ";@,") pp_enum)
proto.enums
(pp_print_list ~pp_sep:(fun ppf () -> fprintf ppf ";@,") pp_extend)
proto.extends