about summary refs log tree commit diff stats
path: root/vendor/godobuf/addons/protobuf/protobuf_core.gd
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/godobuf/addons/protobuf/protobuf_core.gd')
-rw-r--r--vendor/godobuf/addons/protobuf/protobuf_core.gd668
1 files changed, 668 insertions, 0 deletions
diff --git a/vendor/godobuf/addons/protobuf/protobuf_core.gd b/vendor/godobuf/addons/protobuf/protobuf_core.gd new file mode 100644 index 0000000..7098413 --- /dev/null +++ b/vendor/godobuf/addons/protobuf/protobuf_core.gd
@@ -0,0 +1,668 @@
1#
2# BSD 3-Clause License
3#
4# Copyright (c) 2018 - 2023, Oleg Malyavkin
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions are met:
9#
10# * Redistributions of source code must retain the above copyright notice, this
11# list of conditions and the following disclaimer.
12#
13# * Redistributions in binary form must reproduce the above copyright notice,
14# this list of conditions and the following disclaimer in the documentation
15# and/or other materials provided with the distribution.
16#
17# * Neither the name of the copyright holder nor the names of its
18# contributors may be used to endorse or promote products derived from
19# this software without specific prior written permission.
20#
21# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32# DEBUG_TAB redefine this " " if you need, example: const DEBUG_TAB = "\t"
33
34const PROTO_VERSION = 0
35
36const DEBUG_TAB : String = " "
37
38enum PB_ERR {
39 NO_ERRORS = 0,
40 VARINT_NOT_FOUND = -1,
41 REPEATED_COUNT_NOT_FOUND = -2,
42 REPEATED_COUNT_MISMATCH = -3,
43 LENGTHDEL_SIZE_NOT_FOUND = -4,
44 LENGTHDEL_SIZE_MISMATCH = -5,
45 PACKAGE_SIZE_MISMATCH = -6,
46 UNDEFINED_STATE = -7,
47 PARSE_INCOMPLETE = -8,
48 REQUIRED_FIELDS = -9
49}
50
51enum PB_DATA_TYPE {
52 INT32 = 0,
53 SINT32 = 1,
54 UINT32 = 2,
55 INT64 = 3,
56 SINT64 = 4,
57 UINT64 = 5,
58 BOOL = 6,
59 ENUM = 7,
60 FIXED32 = 8,
61 SFIXED32 = 9,
62 FLOAT = 10,
63 FIXED64 = 11,
64 SFIXED64 = 12,
65 DOUBLE = 13,
66 STRING = 14,
67 BYTES = 15,
68 MESSAGE = 16,
69 MAP = 17
70}
71
72const DEFAULT_VALUES_2 = {
73 PB_DATA_TYPE.INT32: null,
74 PB_DATA_TYPE.SINT32: null,
75 PB_DATA_TYPE.UINT32: null,
76 PB_DATA_TYPE.INT64: null,
77 PB_DATA_TYPE.SINT64: null,
78 PB_DATA_TYPE.UINT64: null,
79 PB_DATA_TYPE.BOOL: null,
80 PB_DATA_TYPE.ENUM: null,
81 PB_DATA_TYPE.FIXED32: null,
82 PB_DATA_TYPE.SFIXED32: null,
83 PB_DATA_TYPE.FLOAT: null,
84 PB_DATA_TYPE.FIXED64: null,
85 PB_DATA_TYPE.SFIXED64: null,
86 PB_DATA_TYPE.DOUBLE: null,
87 PB_DATA_TYPE.STRING: null,
88 PB_DATA_TYPE.BYTES: null,
89 PB_DATA_TYPE.MESSAGE: null,
90 PB_DATA_TYPE.MAP: null
91}
92
93const DEFAULT_VALUES_3 = {
94 PB_DATA_TYPE.INT32: 0,
95 PB_DATA_TYPE.SINT32: 0,
96 PB_DATA_TYPE.UINT32: 0,
97 PB_DATA_TYPE.INT64: 0,
98 PB_DATA_TYPE.SINT64: 0,
99 PB_DATA_TYPE.UINT64: 0,
100 PB_DATA_TYPE.BOOL: false,
101 PB_DATA_TYPE.ENUM: 0,
102 PB_DATA_TYPE.FIXED32: 0,
103 PB_DATA_TYPE.SFIXED32: 0,
104 PB_DATA_TYPE.FLOAT: 0.0,
105 PB_DATA_TYPE.FIXED64: 0,
106 PB_DATA_TYPE.SFIXED64: 0,
107 PB_DATA_TYPE.DOUBLE: 0.0,
108 PB_DATA_TYPE.STRING: "",
109 PB_DATA_TYPE.BYTES: [],
110 PB_DATA_TYPE.MESSAGE: null,
111 PB_DATA_TYPE.MAP: []
112}
113
114enum PB_TYPE {
115 VARINT = 0,
116 FIX64 = 1,
117 LENGTHDEL = 2,
118 STARTGROUP = 3,
119 ENDGROUP = 4,
120 FIX32 = 5,
121 UNDEFINED = 8
122}
123
124enum PB_RULE {
125 OPTIONAL = 0,
126 REQUIRED = 1,
127 REPEATED = 2,
128 RESERVED = 3
129}
130
131enum PB_SERVICE_STATE {
132 FILLED = 0,
133 UNFILLED = 1
134}
135
136class PBField:
137 func _init(a_name : String, a_type : int, a_rule : int, a_tag : int, packed : bool, a_value = null):
138 name = a_name
139 type = a_type
140 rule = a_rule
141 tag = a_tag
142 option_packed = packed
143 value = a_value
144
145 var name : String
146 var type : int
147 var rule : int
148 var tag : int
149 var option_packed : bool
150 var value
151 var is_map_field : bool = false
152 var option_default : bool = false
153
154class PBTypeTag:
155 var ok : bool = false
156 var type : int
157 var tag : int
158 var offset : int
159
160class PBServiceField:
161 var field : PBField
162 var func_ref = null
163 var state : int = PB_SERVICE_STATE.UNFILLED
164
165class PBPacker:
166 static func convert_signed(n : int) -> int:
167 if n < -2147483648:
168 return (n << 1) ^ (n >> 63)
169 else:
170 return (n << 1) ^ (n >> 31)
171
172 static func deconvert_signed(n : int) -> int:
173 if n & 0x01:
174 return ~(n >> 1)
175 else:
176 return (n >> 1)
177
178 static func pack_varint(value) -> PackedByteArray:
179 var varint : PackedByteArray = PackedByteArray()
180 if typeof(value) == TYPE_BOOL:
181 if value:
182 value = 1
183 else:
184 value = 0
185 for _i in range(9):
186 var b = value & 0x7F
187 value >>= 7
188 if value:
189 varint.append(b | 0x80)
190 else:
191 varint.append(b)
192 break
193 if varint.size() == 9 && (varint[8] & 0x80 != 0):
194 varint.append(0x01)
195 return varint
196
197 static func pack_bytes(value, count : int, data_type : int) -> PackedByteArray:
198 var bytes : PackedByteArray = PackedByteArray()
199 if data_type == PB_DATA_TYPE.FLOAT:
200 var spb : StreamPeerBuffer = StreamPeerBuffer.new()
201 spb.put_float(value)
202 bytes = spb.get_data_array()
203 elif data_type == PB_DATA_TYPE.DOUBLE:
204 var spb : StreamPeerBuffer = StreamPeerBuffer.new()
205 spb.put_double(value)
206 bytes = spb.get_data_array()
207 else:
208 for _i in range(count):
209 bytes.append(value & 0xFF)
210 value >>= 8
211 return bytes
212
213 static func unpack_bytes(bytes : PackedByteArray, index : int, count : int, data_type : int):
214 if data_type == PB_DATA_TYPE.FLOAT:
215 return bytes.decode_float(index)
216 elif data_type == PB_DATA_TYPE.DOUBLE:
217 return bytes.decode_double(index)
218 else:
219 # Convert to big endian
220 var slice: PackedByteArray = bytes.slice(index, index + count)
221 slice.reverse()
222 return slice
223
224 static func unpack_varint(varint_bytes) -> int:
225 var value : int = 0
226 var i: int = varint_bytes.size() - 1
227 while i > -1:
228 value = (value << 7) | (varint_bytes[i] & 0x7F)
229 i -= 1
230 return value
231
232 static func pack_type_tag(type : int, tag : int) -> PackedByteArray:
233 return pack_varint((tag << 3) | type)
234
235 static func isolate_varint(bytes : PackedByteArray, index : int) -> PackedByteArray:
236 var i: int = index
237 while i <= index + 10: # Protobuf varint max size is 10 bytes
238 if !(bytes[i] & 0x80):
239 return bytes.slice(index, i + 1)
240 i += 1
241 return [] # Unreachable
242
243 static func unpack_type_tag(bytes : PackedByteArray, index : int) -> PBTypeTag:
244 var varint_bytes : PackedByteArray = isolate_varint(bytes, index)
245 var result : PBTypeTag = PBTypeTag.new()
246 if varint_bytes.size() != 0:
247 result.ok = true
248 result.offset = varint_bytes.size()
249 var unpacked : int = unpack_varint(varint_bytes)
250 result.type = unpacked & 0x07
251 result.tag = unpacked >> 3
252 return result
253
254 static func pack_length_delimeted(type : int, tag : int, bytes : PackedByteArray) -> PackedByteArray:
255 var result : PackedByteArray = pack_type_tag(type, tag)
256 result.append_array(pack_varint(bytes.size()))
257 result.append_array(bytes)
258 return result
259
260 static func pb_type_from_data_type(data_type : int) -> int:
261 if data_type == PB_DATA_TYPE.INT32 || data_type == PB_DATA_TYPE.SINT32 || data_type == PB_DATA_TYPE.UINT32 || data_type == PB_DATA_TYPE.INT64 || data_type == PB_DATA_TYPE.SINT64 || data_type == PB_DATA_TYPE.UINT64 || data_type == PB_DATA_TYPE.BOOL || data_type == PB_DATA_TYPE.ENUM:
262 return PB_TYPE.VARINT
263 elif data_type == PB_DATA_TYPE.FIXED32 || data_type == PB_DATA_TYPE.SFIXED32 || data_type == PB_DATA_TYPE.FLOAT:
264 return PB_TYPE.FIX32
265 elif data_type == PB_DATA_TYPE.FIXED64 || data_type == PB_DATA_TYPE.SFIXED64 || data_type == PB_DATA_TYPE.DOUBLE:
266 return PB_TYPE.FIX64
267 elif data_type == PB_DATA_TYPE.STRING || data_type == PB_DATA_TYPE.BYTES || data_type == PB_DATA_TYPE.MESSAGE || data_type == PB_DATA_TYPE.MAP:
268 return PB_TYPE.LENGTHDEL
269 else:
270 return PB_TYPE.UNDEFINED
271
272 static func pack_field(field : PBField) -> PackedByteArray:
273 var type : int = pb_type_from_data_type(field.type)
274 var type_copy : int = type
275 if field.rule == PB_RULE.REPEATED && field.option_packed:
276 type = PB_TYPE.LENGTHDEL
277 var head : PackedByteArray = pack_type_tag(type, field.tag)
278 var data : PackedByteArray = PackedByteArray()
279 if type == PB_TYPE.VARINT:
280 var value
281 if field.rule == PB_RULE.REPEATED:
282 for v in field.value:
283 data.append_array(head)
284 if field.type == PB_DATA_TYPE.SINT32 || field.type == PB_DATA_TYPE.SINT64:
285 value = convert_signed(v)
286 else:
287 value = v
288 data.append_array(pack_varint(value))
289 return data
290 else:
291 if field.type == PB_DATA_TYPE.SINT32 || field.type == PB_DATA_TYPE.SINT64:
292 value = convert_signed(field.value)
293 else:
294 value = field.value
295 data = pack_varint(value)
296 elif type == PB_TYPE.FIX32:
297 if field.rule == PB_RULE.REPEATED:
298 for v in field.value:
299 data.append_array(head)
300 data.append_array(pack_bytes(v, 4, field.type))
301 return data
302 else:
303 data.append_array(pack_bytes(field.value, 4, field.type))
304 elif type == PB_TYPE.FIX64:
305 if field.rule == PB_RULE.REPEATED:
306 for v in field.value:
307 data.append_array(head)
308 data.append_array(pack_bytes(v, 8, field.type))
309 return data
310 else:
311 data.append_array(pack_bytes(field.value, 8, field.type))
312 elif type == PB_TYPE.LENGTHDEL:
313 if field.rule == PB_RULE.REPEATED:
314 if type_copy == PB_TYPE.VARINT:
315 if field.type == PB_DATA_TYPE.SINT32 || field.type == PB_DATA_TYPE.SINT64:
316 var signed_value : int
317 for v in field.value:
318 signed_value = convert_signed(v)
319 data.append_array(pack_varint(signed_value))
320 else:
321 for v in field.value:
322 data.append_array(pack_varint(v))
323 return pack_length_delimeted(type, field.tag, data)
324 elif type_copy == PB_TYPE.FIX32:
325 for v in field.value:
326 data.append_array(pack_bytes(v, 4, field.type))
327 return pack_length_delimeted(type, field.tag, data)
328 elif type_copy == PB_TYPE.FIX64:
329 for v in field.value:
330 data.append_array(pack_bytes(v, 8, field.type))
331 return pack_length_delimeted(type, field.tag, data)
332 elif field.type == PB_DATA_TYPE.STRING:
333 for v in field.value:
334 var obj = v.to_utf8_buffer()
335 data.append_array(pack_length_delimeted(type, field.tag, obj))
336 return data
337 elif field.type == PB_DATA_TYPE.BYTES:
338 for v in field.value:
339 data.append_array(pack_length_delimeted(type, field.tag, v))
340 return data
341 elif typeof(field.value[0]) == TYPE_OBJECT:
342 for v in field.value:
343 var obj : PackedByteArray = v.to_bytes()
344 data.append_array(pack_length_delimeted(type, field.tag, obj))
345 return data
346 else:
347 if field.type == PB_DATA_TYPE.STRING:
348 var str_bytes : PackedByteArray = field.value.to_utf8_buffer()
349 if PROTO_VERSION == 2 || (PROTO_VERSION == 3 && str_bytes.size() > 0):
350 data.append_array(str_bytes)
351 return pack_length_delimeted(type, field.tag, data)
352 if field.type == PB_DATA_TYPE.BYTES:
353 if PROTO_VERSION == 2 || (PROTO_VERSION == 3 && field.value.size() > 0):
354 data.append_array(field.value)
355 return pack_length_delimeted(type, field.tag, data)
356 elif typeof(field.value) == TYPE_OBJECT:
357 var obj : PackedByteArray = field.value.to_bytes()
358 if obj.size() > 0:
359 data.append_array(obj)
360 return pack_length_delimeted(type, field.tag, data)
361 else:
362 pass
363 if data.size() > 0:
364 head.append_array(data)
365 return head
366 else:
367 return data
368
369 static func skip_unknown_field(bytes : PackedByteArray, offset : int, type : int) -> int:
370 if type == PB_TYPE.VARINT:
371 return offset + isolate_varint(bytes, offset).size()
372 if type == PB_TYPE.FIX64:
373 return offset + 8
374 if type == PB_TYPE.LENGTHDEL:
375 var length_bytes : PackedByteArray = isolate_varint(bytes, offset)
376 var length : int = unpack_varint(length_bytes)
377 return offset + length_bytes.size() + length
378 if type == PB_TYPE.FIX32:
379 return offset + 4
380 return PB_ERR.UNDEFINED_STATE
381
382 static func unpack_field(bytes : PackedByteArray, offset : int, field : PBField, type : int, message_func_ref) -> int:
383 if field.rule == PB_RULE.REPEATED && type != PB_TYPE.LENGTHDEL && field.option_packed:
384 var count = isolate_varint(bytes, offset)
385 if count.size() > 0:
386 offset += count.size()
387 count = unpack_varint(count)
388 if type == PB_TYPE.VARINT:
389 var val
390 var counter = offset + count
391 while offset < counter:
392 val = isolate_varint(bytes, offset)
393 if val.size() > 0:
394 offset += val.size()
395 val = unpack_varint(val)
396 if field.type == PB_DATA_TYPE.SINT32 || field.type == PB_DATA_TYPE.SINT64:
397 val = deconvert_signed(val)
398 elif field.type == PB_DATA_TYPE.BOOL:
399 if val:
400 val = true
401 else:
402 val = false
403 field.value.append(val)
404 else:
405 return PB_ERR.REPEATED_COUNT_MISMATCH
406 return offset
407 elif type == PB_TYPE.FIX32 || type == PB_TYPE.FIX64:
408 var type_size
409 if type == PB_TYPE.FIX32:
410 type_size = 4
411 else:
412 type_size = 8
413 var val
414 var counter = offset + count
415 while offset < counter:
416 if (offset + type_size) > bytes.size():
417 return PB_ERR.REPEATED_COUNT_MISMATCH
418 val = unpack_bytes(bytes, offset, type_size, field.type)
419 offset += type_size
420 field.value.append(val)
421 return offset
422 else:
423 return PB_ERR.REPEATED_COUNT_NOT_FOUND
424 else:
425 if type == PB_TYPE.VARINT:
426 var val = isolate_varint(bytes, offset)
427 if val.size() > 0:
428 offset += val.size()
429 val = unpack_varint(val)
430 if field.type == PB_DATA_TYPE.SINT32 || field.type == PB_DATA_TYPE.SINT64:
431 val = deconvert_signed(val)
432 elif field.type == PB_DATA_TYPE.BOOL:
433 if val:
434 val = true
435 else:
436 val = false
437 if field.rule == PB_RULE.REPEATED:
438 field.value.append(val)
439 else:
440 field.value = val
441 else:
442 return PB_ERR.VARINT_NOT_FOUND
443 return offset
444 elif type == PB_TYPE.FIX32 || type == PB_TYPE.FIX64:
445 var type_size
446 if type == PB_TYPE.FIX32:
447 type_size = 4
448 else:
449 type_size = 8
450 var val
451 if (offset + type_size) > bytes.size():
452 return PB_ERR.REPEATED_COUNT_MISMATCH
453 val = unpack_bytes(bytes, offset, type_size, field.type)
454 offset += type_size
455 if field.rule == PB_RULE.REPEATED:
456 field.value.append(val)
457 else:
458 field.value = val
459 return offset
460 elif type == PB_TYPE.LENGTHDEL:
461 var inner_size = isolate_varint(bytes, offset)
462 if inner_size.size() > 0:
463 offset += inner_size.size()
464 inner_size = unpack_varint(inner_size)
465 if inner_size >= 0:
466 if inner_size + offset > bytes.size():
467 return PB_ERR.LENGTHDEL_SIZE_MISMATCH
468 if message_func_ref != null:
469 var message = message_func_ref.call()
470 if inner_size > 0:
471 var sub_offset = message.from_bytes(bytes, offset, inner_size + offset)
472 if sub_offset > 0:
473 if sub_offset - offset >= inner_size:
474 offset = sub_offset
475 return offset
476 else:
477 return PB_ERR.LENGTHDEL_SIZE_MISMATCH
478 return sub_offset
479 else:
480 return offset
481 elif field.type == PB_DATA_TYPE.STRING:
482 var str_bytes : PackedByteArray = bytes.slice(offset, inner_size + offset)
483 if field.rule == PB_RULE.REPEATED:
484 field.value.append(str_bytes.get_string_from_utf8())
485 else:
486 field.value = str_bytes.get_string_from_utf8()
487 return offset + inner_size
488 elif field.type == PB_DATA_TYPE.BYTES:
489 var val_bytes : PackedByteArray = bytes.slice(offset, inner_size + offset)
490 if field.rule == PB_RULE.REPEATED:
491 field.value.append(val_bytes)
492 else:
493 field.value = val_bytes
494 return offset + inner_size
495 else:
496 return PB_ERR.LENGTHDEL_SIZE_NOT_FOUND
497 else:
498 return PB_ERR.LENGTHDEL_SIZE_NOT_FOUND
499 return PB_ERR.UNDEFINED_STATE
500
501 static func unpack_message(data, bytes : PackedByteArray, offset : int, limit : int) -> int:
502 while true:
503 var tt : PBTypeTag = unpack_type_tag(bytes, offset)
504 if tt.ok:
505 offset += tt.offset
506 if data.has(tt.tag):
507 var service : PBServiceField = data[tt.tag]
508 var type : int = pb_type_from_data_type(service.field.type)
509 if type == tt.type || (tt.type == PB_TYPE.LENGTHDEL && service.field.rule == PB_RULE.REPEATED && service.field.option_packed):
510 var res : int = unpack_field(bytes, offset, service.field, type, service.func_ref)
511 if res > 0:
512 service.state = PB_SERVICE_STATE.FILLED
513 offset = res
514 if offset == limit:
515 return offset
516 elif offset > limit:
517 return PB_ERR.PACKAGE_SIZE_MISMATCH
518 elif res < 0:
519 return res
520 else:
521 break
522 else:
523 var res : int = skip_unknown_field(bytes, offset, tt.type)
524 if res > 0:
525 offset = res
526 if offset == limit:
527 return offset
528 elif offset > limit:
529 return PB_ERR.PACKAGE_SIZE_MISMATCH
530 elif res < 0:
531 return res
532 else:
533 break
534 else:
535 return offset
536 return PB_ERR.UNDEFINED_STATE
537
538 static func pack_message(data) -> PackedByteArray:
539 var DEFAULT_VALUES
540 if PROTO_VERSION == 2:
541 DEFAULT_VALUES = DEFAULT_VALUES_2
542 elif PROTO_VERSION == 3:
543 DEFAULT_VALUES = DEFAULT_VALUES_3
544 var result : PackedByteArray = PackedByteArray()
545 var keys : Array = data.keys()
546 keys.sort()
547 for i in keys:
548 if data[i].field.value != null:
549 if data[i].state == PB_SERVICE_STATE.UNFILLED \
550 && !data[i].field.is_map_field \
551 && typeof(data[i].field.value) == typeof(DEFAULT_VALUES[data[i].field.type]) \
552 && data[i].field.value == DEFAULT_VALUES[data[i].field.type]:
553 continue
554 elif data[i].field.rule == PB_RULE.REPEATED && data[i].field.value.size() == 0:
555 continue
556 result.append_array(pack_field(data[i].field))
557 elif data[i].field.rule == PB_RULE.REQUIRED:
558 print("Error: required field is not filled: Tag:", data[i].field.tag)
559 return PackedByteArray()
560 return result
561
562 static func check_required(data) -> bool:
563 var keys : Array = data.keys()
564 for i in keys:
565 if data[i].field.rule == PB_RULE.REQUIRED && data[i].state == PB_SERVICE_STATE.UNFILLED:
566 return false
567 return true
568
569 static func construct_map(key_values):
570 var result = {}
571 for kv in key_values:
572 result[kv.get_key()] = kv.get_value()
573 return result
574
575 static func tabulate(text : String, nesting : int) -> String:
576 var tab : String = ""
577 for _i in range(nesting):
578 tab += DEBUG_TAB
579 return tab + text
580
581 static func value_to_string(value, field : PBField, nesting : int) -> String:
582 var result : String = ""
583 var text : String
584 if field.type == PB_DATA_TYPE.MESSAGE:
585 result += "{"
586 nesting += 1
587 text = message_to_string(value.data, nesting)
588 if text != "":
589 result += "\n" + text
590 nesting -= 1
591 result += tabulate("}", nesting)
592 else:
593 nesting -= 1
594 result += "}"
595 elif field.type == PB_DATA_TYPE.BYTES:
596 result += "<"
597 for i in range(value.size()):
598 result += str(value[i])
599 if i != (value.size() - 1):
600 result += ", "
601 result += ">"
602 elif field.type == PB_DATA_TYPE.STRING:
603 result += "\"" + value + "\""
604 elif field.type == PB_DATA_TYPE.ENUM:
605 result += "ENUM::" + str(value)
606 else:
607 result += str(value)
608 return result
609
610 static func field_to_string(field : PBField, nesting : int) -> String:
611 var result : String = tabulate(field.name + ": ", nesting)
612 if field.type == PB_DATA_TYPE.MAP:
613 if field.value.size() > 0:
614 result += "(\n"
615 nesting += 1
616 for i in range(field.value.size()):
617 var local_key_value = field.value[i].data[1].field
618 result += tabulate(value_to_string(local_key_value.value, local_key_value, nesting), nesting) + ": "
619 local_key_value = field.value[i].data[2].field
620 result += value_to_string(local_key_value.value, local_key_value, nesting)
621 if i != (field.value.size() - 1):
622 result += ","
623 result += "\n"
624 nesting -= 1
625 result += tabulate(")", nesting)
626 else:
627 result += "()"
628 elif field.rule == PB_RULE.REPEATED:
629 if field.value.size() > 0:
630 result += "[\n"
631 nesting += 1
632 for i in range(field.value.size()):
633 result += tabulate(str(i) + ": ", nesting)
634 result += value_to_string(field.value[i], field, nesting)
635 if i != (field.value.size() - 1):
636 result += ","
637 result += "\n"
638 nesting -= 1
639 result += tabulate("]", nesting)
640 else:
641 result += "[]"
642 else:
643 result += value_to_string(field.value, field, nesting)
644 result += ";\n"
645 return result
646
647 static func message_to_string(data, nesting : int = 0) -> String:
648 var DEFAULT_VALUES
649 if PROTO_VERSION == 2:
650 DEFAULT_VALUES = DEFAULT_VALUES_2
651 elif PROTO_VERSION == 3:
652 DEFAULT_VALUES = DEFAULT_VALUES_3
653 var result : String = ""
654 var keys : Array = data.keys()
655 keys.sort()
656 for i in keys:
657 if data[i].field.value != null:
658 if data[i].state == PB_SERVICE_STATE.UNFILLED \
659 && !data[i].field.is_map_field \
660 && typeof(data[i].field.value) == typeof(DEFAULT_VALUES[data[i].field.type]) \
661 && data[i].field.value == DEFAULT_VALUES[data[i].field.type]:
662 continue
663 elif data[i].field.rule == PB_RULE.REPEATED && data[i].field.value.size() == 0:
664 continue
665 result += field_to_string(data[i].field, nesting)
666 elif data[i].field.rule == PB_RULE.REQUIRED:
667 result += data[i].field.name + ": " + "error"
668 return result