pbwire 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1836 @@
1
+ /* Ruby C extension: the Ruby binding.
2
+ *
3
+ * The schema is a FileDescriptorSet (protoc --descriptor_set_out) loaded at run
4
+ * time, so field numbers, types and presence rules are the descriptor's, never a
5
+ * hand-written copy. Two message representations exist, both Ruby objects of the
6
+ * same class:
7
+ *
8
+ * builder schema.message(name), mutable: set() stores into a pbw_message
9
+ * tree, encode() walks it with the C core (pbw_encode_to writes
10
+ * straight into the returned String), get() reads it back.
11
+ *
12
+ * wire view decode(bytes), read-only: one validating tag scan records, per
13
+ * wire field, where its value lives. get() materializes only the
14
+ * field asked for (a scalar, a String, a sub-message view, or an
15
+ * Array for a repeated field), and encode() hands back the exact
16
+ * bytes it was parsed from, so unknown fields, field order and
17
+ * non-canonical encodings survive a decode/encode round trip.
18
+ *
19
+ * The wire view is what keeps this binding near the C core instead of behind a
20
+ * per-field bridge: decoding 3000 repeated items costs one scan, not 3000
21
+ * message trees, and encoding a builder costs one pass into the caller's
22
+ * string.
23
+ *
24
+ * Field facts (number, kind, wire type, packed/required/oneof, sub type, name
25
+ * lookup) are resolved once per message type and cached per schema, so the hot
26
+ * loops never touch the descriptor again.
27
+ *
28
+ * Memory: a Schema and its messages share a refcounted holder, so whichever
29
+ * side is released last frees the C schema. Nothing relies on finalizer order.
30
+ */
31
+ #include <ruby.h>
32
+ #include <ruby/encoding.h>
33
+
34
+ #include <pbwire.h>
35
+
36
+ #include <stdint.h>
37
+ #include <stdlib.h>
38
+ #include <string.h>
39
+
40
+ /* Same cap as the core's PBW_MAX_DEPTH (src/internal.h, not public). */
41
+ #define RB_PBW_MAX_DEPTH 256
42
+ #define SLICE_INLINE 32
43
+ #define SLICE_DEAD 0xffffffffu
44
+
45
+ static VALUE mPbwire;
46
+ static VALUE eError;
47
+ static VALUE cSchema;
48
+ static VALUE cMessage;
49
+ static VALUE cType;
50
+
51
+ /* --------------------------------------------------------------- schema */
52
+
53
+ /* The C schema plus the number of Ruby objects pointing at it. The holder
54
+ * outlives whichever side goes first, because pbw_message_free() reads the
55
+ * descriptor and Ruby gives no order for GC. */
56
+ typedef struct {
57
+ pbw_schema *schema; /* NULL once freed */
58
+ long refs;
59
+ } pbw_holder;
60
+
61
+ typedef struct {
62
+ pbw_holder *holder;
63
+ VALUE types; /* Hash: message name -> Type, built lazily */
64
+ int closed;
65
+ } schema_t;
66
+
67
+ /* One field of one message type, resolved once. */
68
+ typedef struct {
69
+ uint32_t number;
70
+ uint32_t index; /* position in the descriptor's field array */
71
+ uint8_t type; /* pbw_type */
72
+ uint8_t wire; /* expected wire type */
73
+ uint8_t repeated;
74
+ uint8_t packed;
75
+ uint8_t required;
76
+ uint8_t oneof; /* 1-based oneof group, 0 = none */
77
+ uint8_t unsupported;
78
+ VALUE name; /* frozen UTF-8 String */
79
+ VALUE sub; /* Type of a MESSAGE field, else Qnil */
80
+ } field_t;
81
+
82
+ typedef struct {
83
+ pbw_holder *holder; /* not owned: the Schema or a message keeps it */
84
+ const pbw_descriptor *desc;
85
+ size_t count;
86
+ field_t *fields; /* sorted by field number */
87
+ uint32_t *by_number; /* dense field number -> index, or NULL */
88
+ uint32_t by_number_size; /* entries in by_number */
89
+ VALUE by_name; /* Hash: field name -> Integer index */
90
+ uint32_t oneofs;
91
+ int has_required;
92
+ } type_t;
93
+
94
+ /* One wire field of a decoded message. */
95
+ typedef struct {
96
+ size_t off; /* payload offset (delimited) or value offset */
97
+ size_t len; /* payload length (delimited), 0 otherwise */
98
+ uint32_t fidx;
99
+ uint32_t n; /* elements: 1 for an unpacked occurrence */
100
+ uint8_t delimited;
101
+ } slice_t;
102
+
103
+ enum {
104
+ MSG_CLOSED = 0,
105
+ MSG_BUILDER = 1, /* mutable pbw_message tree */
106
+ MSG_WIRE = 2 /* read-only view over decoded bytes */
107
+ };
108
+
109
+ typedef struct {
110
+ int kind;
111
+ VALUE type; /* Type object, also for a builder */
112
+ /* builder */
113
+ pbw_message *tree;
114
+ pbw_holder *holder;
115
+ VALUE parent; /* borrowed sub-message: the builder that owns tree */
116
+ int owned;
117
+ size_t enc_cap;
118
+ /* wire view */
119
+ VALUE buffer; /* frozen String holding the bytes */
120
+ const uint8_t *data;
121
+ size_t off;
122
+ size_t len;
123
+ uint32_t depth;
124
+ slice_t *slices;
125
+ uint32_t nslices;
126
+ uint32_t cap;
127
+ slice_t inline_slices[SLICE_INLINE];
128
+ } message_t;
129
+
130
+ static void schema_mark(void *ptr);
131
+ static void schema_free(void *ptr);
132
+ static void type_mark(void *ptr);
133
+ static void type_free(void *ptr);
134
+ static void message_mark(void *ptr);
135
+ static void message_free(void *ptr);
136
+
137
+ static const rb_data_type_t schema_data_type = {
138
+ "pbwire/schema",
139
+ {schema_mark, schema_free, NULL},
140
+ 0,
141
+ 0,
142
+ RUBY_TYPED_FREE_IMMEDIATELY,
143
+ };
144
+
145
+ static const rb_data_type_t type_data_type = {
146
+ "pbwire/type",
147
+ {type_mark, type_free, NULL},
148
+ 0,
149
+ 0,
150
+ RUBY_TYPED_FREE_IMMEDIATELY,
151
+ };
152
+
153
+ static const rb_data_type_t message_data_type = {
154
+ "pbwire/message",
155
+ {message_mark, message_free, NULL},
156
+ 0,
157
+ 0,
158
+ RUBY_TYPED_FREE_IMMEDIATELY,
159
+ };
160
+
161
+ /* Allocate through the class allocator, so every field starts at its documented
162
+ * empty value (Qnil, not zero). TypedData_Make_Struct zero-fills instead. */
163
+ static VALUE
164
+ typed_object_alloc(VALUE klass, const rb_data_type_t *data_type, void **out)
165
+ {
166
+ VALUE obj = rb_obj_alloc(klass);
167
+
168
+ TypedData_Get_Struct(obj, void, data_type, *out);
169
+ return obj;
170
+ }
171
+
172
+ static pbw_holder *
173
+ holder_new(pbw_schema *schema)
174
+ {
175
+ pbw_holder *holder = ALLOC(pbw_holder);
176
+
177
+ holder->schema = schema;
178
+ holder->refs = 1;
179
+ return holder;
180
+ }
181
+
182
+ static void
183
+ holder_ref(pbw_holder *holder)
184
+ {
185
+ if (holder != NULL) {
186
+ holder->refs++;
187
+ }
188
+ }
189
+
190
+ static void
191
+ holder_release(pbw_holder *holder)
192
+ {
193
+ if (holder == NULL) {
194
+ return;
195
+ }
196
+ if (--holder->refs == 0) {
197
+ if (holder->schema != NULL) {
198
+ pbw_schema_free(holder->schema);
199
+ }
200
+ xfree(holder);
201
+ }
202
+ }
203
+
204
+ /* Schema#close: free the C schema now when nobody else points at it, else let
205
+ * the last message release it. */
206
+ static void
207
+ holder_close(pbw_holder *holder)
208
+ {
209
+ if (holder->schema != NULL && holder->refs == 1) {
210
+ pbw_schema_free(holder->schema);
211
+ holder->schema = NULL;
212
+ }
213
+ }
214
+
215
+ static void
216
+ schema_mark(void *ptr)
217
+ {
218
+ schema_t *schema = (schema_t *)ptr;
219
+
220
+ if (schema != NULL) {
221
+ rb_gc_mark(schema->types);
222
+ }
223
+ }
224
+
225
+ static void
226
+ schema_free(void *ptr)
227
+ {
228
+ schema_t *schema = (schema_t *)ptr;
229
+
230
+ if (schema == NULL) {
231
+ return;
232
+ }
233
+ holder_release(schema->holder);
234
+ xfree(schema);
235
+ }
236
+
237
+ static void
238
+ type_mark(void *ptr)
239
+ {
240
+ type_t *type = (type_t *)ptr;
241
+ size_t i;
242
+
243
+ if (type == NULL) {
244
+ return;
245
+ }
246
+ rb_gc_mark(type->by_name);
247
+ for (i = 0; i < type->count; i++) {
248
+ rb_gc_mark(type->fields[i].name);
249
+ rb_gc_mark(type->fields[i].sub);
250
+ }
251
+ }
252
+
253
+ static void
254
+ type_free(void *ptr)
255
+ {
256
+ type_t *type = (type_t *)ptr;
257
+
258
+ if (type == NULL) {
259
+ return;
260
+ }
261
+ xfree(type->fields);
262
+ xfree(type->by_number);
263
+ xfree(type);
264
+ }
265
+
266
+ static void
267
+ message_mark(void *ptr)
268
+ {
269
+ message_t *message = (message_t *)ptr;
270
+
271
+ if (message == NULL) {
272
+ return;
273
+ }
274
+ rb_gc_mark(message->type);
275
+ rb_gc_mark(message->parent);
276
+ rb_gc_mark(message->buffer);
277
+ }
278
+
279
+ static void
280
+ message_free(void *ptr)
281
+ {
282
+ message_t *message = (message_t *)ptr;
283
+
284
+ if (message == NULL) {
285
+ return;
286
+ }
287
+ if (message->kind == MSG_BUILDER && message->owned &&
288
+ message->tree != NULL) {
289
+ pbw_message_free(message->tree);
290
+ }
291
+ holder_release(message->holder);
292
+ if (message->slices != message->inline_slices) {
293
+ free(message->slices);
294
+ }
295
+ xfree(message);
296
+ }
297
+
298
+ static VALUE
299
+ schema_alloc(VALUE klass)
300
+ {
301
+ schema_t *schema;
302
+ VALUE obj = TypedData_Make_Struct(klass, schema_t, &schema_data_type, schema);
303
+
304
+ schema->holder = NULL;
305
+ schema->types = Qnil;
306
+ schema->closed = 0;
307
+ return obj;
308
+ }
309
+
310
+ static VALUE
311
+ type_alloc(VALUE klass)
312
+ {
313
+ type_t *type;
314
+ VALUE obj = TypedData_Make_Struct(klass, type_t, &type_data_type, type);
315
+
316
+ type->holder = NULL;
317
+ type->desc = NULL;
318
+ type->count = 0;
319
+ type->fields = NULL;
320
+ type->by_number = NULL;
321
+ type->by_number_size = 0;
322
+ type->by_name = Qnil;
323
+ type->oneofs = 0;
324
+ type->has_required = 0;
325
+ return obj;
326
+ }
327
+
328
+ static VALUE
329
+ message_alloc(VALUE klass)
330
+ {
331
+ message_t *message;
332
+ VALUE obj = TypedData_Make_Struct(klass, message_t, &message_data_type,
333
+ message);
334
+
335
+ message->kind = MSG_CLOSED;
336
+ message->type = Qnil;
337
+ message->tree = NULL;
338
+ message->holder = NULL;
339
+ message->parent = Qnil;
340
+ message->owned = 0;
341
+ message->enc_cap = 0;
342
+ message->buffer = Qnil;
343
+ message->data = NULL;
344
+ message->off = 0;
345
+ message->len = 0;
346
+ message->depth = 0;
347
+ message->slices = message->inline_slices;
348
+ message->nslices = 0;
349
+ message->cap = SLICE_INLINE;
350
+ return obj;
351
+ }
352
+
353
+ static const char *
354
+ type_name(type_t *type)
355
+ {
356
+ const char *name = pbw_descriptor_name(type->desc);
357
+
358
+ return name != NULL ? name : "message";
359
+ }
360
+
361
+ static pbw_schema *
362
+ schema_ptr(VALUE obj)
363
+ {
364
+ schema_t *schema;
365
+
366
+ TypedData_Get_Struct(obj, schema_t, &schema_data_type, schema);
367
+ if (schema->closed || schema->holder == NULL ||
368
+ schema->holder->schema == NULL) {
369
+ rb_raise(eError, "schema is closed");
370
+ }
371
+ return schema->holder->schema;
372
+ }
373
+
374
+ /* -------------------------------------------------------------- field facts */
375
+
376
+ static unsigned
377
+ wire_type_of(pbw_type type)
378
+ {
379
+ switch (type) {
380
+ case PBW_TYPE_DOUBLE:
381
+ case PBW_TYPE_FIXED64:
382
+ case PBW_TYPE_SFIXED64:
383
+ return 1;
384
+ case PBW_TYPE_FLOAT:
385
+ case PBW_TYPE_FIXED32:
386
+ case PBW_TYPE_SFIXED32:
387
+ return 5;
388
+ case PBW_TYPE_STRING:
389
+ case PBW_TYPE_BYTES:
390
+ case PBW_TYPE_MESSAGE:
391
+ return 2;
392
+ case PBW_TYPE_GROUP:
393
+ return 3;
394
+ default:
395
+ return 0;
396
+ }
397
+ }
398
+
399
+ static int
400
+ packable(pbw_type type)
401
+ {
402
+ switch (type) {
403
+ case PBW_TYPE_STRING:
404
+ case PBW_TYPE_BYTES:
405
+ case PBW_TYPE_MESSAGE:
406
+ case PBW_TYPE_GROUP:
407
+ return 0;
408
+ default:
409
+ return 1;
410
+ }
411
+ }
412
+
413
+ /* A Type object for `desc`, cached on the Schema; recursive schemas resolve
414
+ * because the Type is published before its sub-types are built. */
415
+ static VALUE
416
+ type_for(VALUE schema_obj, const pbw_descriptor *desc)
417
+ {
418
+ schema_t *schema;
419
+ VALUE types;
420
+ VALUE key;
421
+ VALUE found;
422
+ VALUE obj;
423
+ type_t *type;
424
+ size_t count;
425
+ size_t i;
426
+
427
+ TypedData_Get_Struct(schema_obj, schema_t, &schema_data_type, schema);
428
+ types = schema->types;
429
+ if (NIL_P(types)) {
430
+ types = rb_hash_new();
431
+ schema->types = types;
432
+ }
433
+ key = rb_utf8_str_new_cstr(pbw_descriptor_name(desc));
434
+ found = rb_hash_aref(types, key);
435
+ if (!NIL_P(found)) {
436
+ return found;
437
+ }
438
+ count = pbw_descriptor_field_count(desc);
439
+ obj = typed_object_alloc(cType, &type_data_type, (void **)&type);
440
+ type->desc = desc;
441
+ type->count = count;
442
+ type->fields = count == 0 ? NULL : ZALLOC_N(field_t, count);
443
+ type->by_name = rb_hash_new();
444
+ rb_hash_aset(types, key, obj); /* before the subs: recursive schemas */
445
+
446
+ for (i = 0; i < count; i++) {
447
+ const pbw_field *field = pbw_descriptor_field_at(desc, i);
448
+ field_t *f = &type->fields[i];
449
+
450
+ f->number = pbw_field_number(field);
451
+ f->index = (uint32_t)i;
452
+ f->type = (uint8_t)pbw_field_type(field);
453
+ f->wire = (uint8_t)wire_type_of((pbw_type)f->type);
454
+ f->repeated = pbw_field_label(field) == PBW_LABEL_REPEATED;
455
+ f->packed = pbw_field_is_packed(field) != 0;
456
+ f->required = pbw_field_label(field) == PBW_LABEL_REQUIRED;
457
+ f->oneof = (uint8_t)pbw_field_oneof_index(field);
458
+ f->unsupported = f->type == PBW_TYPE_GROUP;
459
+ f->name = rb_utf8_str_new_cstr(pbw_field_name(field));
460
+ rb_obj_freeze(f->name);
461
+ f->sub = Qnil;
462
+ if (f->oneof > type->oneofs) {
463
+ type->oneofs = f->oneof;
464
+ }
465
+ if (f->required) {
466
+ type->has_required = 1;
467
+ }
468
+ rb_hash_aset(type->by_name, f->name, UINT2NUM(i));
469
+ }
470
+ for (i = 0; i < count; i++) {
471
+ const pbw_field *field = pbw_descriptor_field_at(desc, i);
472
+ field_t *f = &type->fields[i];
473
+
474
+ if (f->type == PBW_TYPE_MESSAGE) {
475
+ f->sub = type_for(schema_obj, pbw_field_message_type(field));
476
+ }
477
+ }
478
+ {
479
+ uint32_t max = 0;
480
+
481
+ for (i = 0; i < count; i++) {
482
+ if (type->fields[i].number > max) {
483
+ max = type->fields[i].number;
484
+ }
485
+ }
486
+ if (max <= 512 && max <= (uint32_t)(count * 8 + 8)) {
487
+ type->by_number = ALLOC_N(uint32_t, (size_t)max + 1);
488
+ type->by_number_size = max + 1;
489
+ for (i = 0; i <= max; i++) {
490
+ type->by_number[i] = UINT32_MAX;
491
+ }
492
+ for (i = 0; i < count; i++) {
493
+ type->by_number[type->fields[i].number] = (uint32_t)i;
494
+ }
495
+ }
496
+ }
497
+ return obj;
498
+ }
499
+
500
+ static type_t *
501
+ message_type_of(VALUE message)
502
+ {
503
+ message_t *m;
504
+ type_t *type;
505
+
506
+ TypedData_Get_Struct(message, message_t, &message_data_type, m);
507
+ TypedData_Get_Struct(m->type, type_t, &type_data_type, type);
508
+ return type;
509
+ }
510
+
511
+ /* One indexed load for a dense field-number space, binary search otherwise
512
+ * (descriptor fields are sorted by number). */
513
+ static field_t *
514
+ type_field_by_number(type_t *type, uint32_t number)
515
+ {
516
+ if (type->by_number != NULL) {
517
+ if (number < type->by_number_size) {
518
+ uint32_t index = type->by_number[number];
519
+
520
+ if (index != UINT32_MAX) {
521
+ return &type->fields[index];
522
+ }
523
+ }
524
+ return NULL;
525
+ }
526
+ {
527
+ uint32_t lo = 0;
528
+ uint32_t hi = (uint32_t)type->count;
529
+
530
+ while (lo < hi) {
531
+ uint32_t mid = lo + (hi - lo) / 2;
532
+
533
+ if (type->fields[mid].number < number) {
534
+ lo = mid + 1;
535
+ } else {
536
+ hi = mid;
537
+ }
538
+ }
539
+ if (lo < type->count && type->fields[lo].number == number) {
540
+ return &type->fields[lo];
541
+ }
542
+ return NULL;
543
+ }
544
+ }
545
+
546
+ static field_t *
547
+ field_lookup(type_t *type, VALUE key)
548
+ {
549
+ VALUE index;
550
+
551
+ if (RB_INTEGER_TYPE_P(key)) {
552
+ long number = NUM2LONG(key);
553
+ field_t *field = NULL;
554
+
555
+ if (number >= 0 && number <= 536870911L) {
556
+ field = type_field_by_number(type, (uint32_t)number);
557
+ }
558
+ if (field != NULL) {
559
+ return field;
560
+ }
561
+ rb_raise(eError, "%s: no field %ld", type_name(type), number);
562
+ }
563
+ if (SYMBOL_P(key)) {
564
+ key = rb_sym2str(key);
565
+ } else {
566
+ key = StringValue(key);
567
+ }
568
+ index = rb_hash_aref(type->by_name, key);
569
+ if (NIL_P(index)) {
570
+ rb_raise(eError, "%s: no field %s", type_name(type),
571
+ StringValueCStr(key));
572
+ }
573
+ return &type->fields[NUM2UINT(index)];
574
+ }
575
+
576
+ /* --------------------------------------------------------------- wire read */
577
+
578
+ typedef struct {
579
+ const uint8_t *p;
580
+ const uint8_t *end;
581
+ } rdr;
582
+
583
+ static int
584
+ rd_bytes(rdr *r, size_t n)
585
+ {
586
+ if ((size_t)(r->end - r->p) < n) {
587
+ return 0;
588
+ }
589
+ r->p += n;
590
+ return 1;
591
+ }
592
+
593
+ static int
594
+ rd_varint(rdr *r, uint64_t *out)
595
+ {
596
+ const uint8_t *p = r->p;
597
+ const uint8_t *end = r->end;
598
+ uint64_t value = 0;
599
+ unsigned shift = 0;
600
+
601
+ while (p < end && shift < 64) {
602
+ uint8_t byte = *p++;
603
+
604
+ value |= (uint64_t)(byte & 0x7f) << shift;
605
+ if ((byte & 0x80) == 0) {
606
+ r->p = p;
607
+ *out = value;
608
+ return 1;
609
+ }
610
+ shift += 7;
611
+ }
612
+ return 0;
613
+ }
614
+
615
+ static int
616
+ rd_fixed(rdr *r, uint64_t *out, size_t width)
617
+ {
618
+ const uint8_t *p;
619
+
620
+ if ((size_t)(r->end - r->p) < width) {
621
+ return 0;
622
+ }
623
+ p = r->p;
624
+ *out = (uint64_t)p[0] | ((uint64_t)p[1] << 8) | ((uint64_t)p[2] << 16) |
625
+ ((uint64_t)p[3] << 24);
626
+ if (width == 8) {
627
+ *out |= ((uint64_t)p[4] << 32) | ((uint64_t)p[5] << 40) |
628
+ ((uint64_t)p[6] << 48) | ((uint64_t)p[7] << 56);
629
+ }
630
+ r->p += width;
631
+ return 1;
632
+ }
633
+
634
+ /* A field tag is a varint32: at most five bytes, a field number above zero and
635
+ * a wire type at most 5. */
636
+ static int
637
+ rd_tag(rdr *r, uint32_t *fnum, unsigned *wt)
638
+ {
639
+ const uint8_t *start = r->p;
640
+ uint64_t value;
641
+
642
+ if (!rd_varint(r, &value)) {
643
+ return 0;
644
+ }
645
+ if ((size_t)(r->p - start) > 5) {
646
+ return 0;
647
+ }
648
+ if ((value >> 3) == 0 || (value >> 3) > 0x1fffffffull) {
649
+ return 0;
650
+ }
651
+ *wt = (unsigned)(value & 7);
652
+ if (*wt > 5) {
653
+ return 0;
654
+ }
655
+ *fnum = (uint32_t)(value >> 3);
656
+ return 1;
657
+ }
658
+
659
+ /* Unknown or wrongly typed field: skip its value, groups included. */
660
+ static int
661
+ rd_skip(rdr *r, uint32_t fnum, unsigned wt, unsigned depth)
662
+ {
663
+ switch (wt) {
664
+ case 0: {
665
+ uint64_t value;
666
+
667
+ return rd_varint(r, &value);
668
+ }
669
+ case 1:
670
+ return rd_bytes(r, 8);
671
+ case 2: {
672
+ uint64_t n;
673
+
674
+ if (!rd_varint(r, &n) || n > (uint64_t)(r->end - r->p)) {
675
+ return 0;
676
+ }
677
+ r->p += (size_t)n;
678
+ return 1;
679
+ }
680
+ case 3:
681
+ if (depth >= RB_PBW_MAX_DEPTH) {
682
+ return 0;
683
+ }
684
+ for (;;) {
685
+ uint32_t inner_fnum;
686
+ unsigned inner_wt;
687
+
688
+ if (!rd_tag(r, &inner_fnum, &inner_wt)) {
689
+ return 0;
690
+ }
691
+ if (inner_wt == 4) {
692
+ return inner_fnum == fnum;
693
+ }
694
+ if (!rd_skip(r, inner_fnum, inner_wt, depth + 1)) {
695
+ return 0;
696
+ }
697
+ }
698
+ case 5:
699
+ return rd_bytes(r, 4);
700
+ default:
701
+ return 0; /* stray END_GROUP */
702
+ }
703
+ }
704
+
705
+ /* A packed run must hold a whole number of complete values; returns the count
706
+ * or -1. */
707
+ static long
708
+ scan_run(field_t *f, const uint8_t *p, size_t len)
709
+ {
710
+ rdr r;
711
+ long n = 0;
712
+
713
+ if (f->wire != 0) {
714
+ size_t width = f->wire == 1 ? 8 : 4;
715
+
716
+ if (len % width != 0) {
717
+ return -1;
718
+ }
719
+ return (long)(len / width);
720
+ }
721
+ r.p = p;
722
+ r.end = p + len;
723
+ while (r.p < r.end) {
724
+ uint64_t value;
725
+
726
+ if (!rd_varint(&r, &value)) {
727
+ return -1;
728
+ }
729
+ n++;
730
+ }
731
+ return n;
732
+ }
733
+
734
+ /* ------------------------------------------------------------- wire scan */
735
+
736
+ static int
737
+ slice_reserve(message_t *m, uint32_t need)
738
+ {
739
+ uint32_t cap;
740
+ slice_t *grown;
741
+
742
+ if (need <= m->cap) {
743
+ return 1;
744
+ }
745
+ cap = m->cap;
746
+ while (cap < need) {
747
+ if (cap > UINT32_MAX / 2) {
748
+ return 0;
749
+ }
750
+ cap *= 2;
751
+ }
752
+ if (m->slices == m->inline_slices) {
753
+ grown = (slice_t *)malloc((size_t)cap * sizeof(*grown));
754
+ if (grown != NULL) {
755
+ memcpy(grown, m->inline_slices,
756
+ (size_t)m->nslices * sizeof(*grown));
757
+ }
758
+ } else {
759
+ grown = (slice_t *)realloc(m->slices, (size_t)cap * sizeof(*grown));
760
+ }
761
+ if (grown == NULL) {
762
+ return 0;
763
+ }
764
+ m->slices = grown;
765
+ m->cap = cap;
766
+ return 1;
767
+ }
768
+
769
+ /* Records one field, keeping at most one live slice per oneof group. */
770
+ static int
771
+ slice_add(message_t *m, field_t *f, size_t off, size_t len, uint32_t n,
772
+ int delimited, uint32_t *oneof_last)
773
+ {
774
+ uint32_t slot = f->oneof == 0 ? 0 : (uint32_t)f->oneof - 1;
775
+
776
+ if (f->oneof != 0 && oneof_last[slot] != 0 &&
777
+ m->slices[oneof_last[slot] - 1].fidx != f->index) {
778
+ /* Another member of the group: it is gone. Repeats of this same member
779
+ * stay, because a message merges with itself. */
780
+ m->slices[oneof_last[slot] - 1].fidx = SLICE_DEAD;
781
+ }
782
+ if (!slice_reserve(m, m->nslices + 1)) {
783
+ return 0;
784
+ }
785
+ m->slices[m->nslices].off = off;
786
+ m->slices[m->nslices].len = len;
787
+ m->slices[m->nslices].fidx = f->index;
788
+ m->slices[m->nslices].n = n;
789
+ m->slices[m->nslices].delimited = (uint8_t)delimited;
790
+ m->nslices++;
791
+ if (f->oneof != 0) {
792
+ oneof_last[slot] = m->nslices;
793
+ }
794
+ return 1;
795
+ }
796
+
797
+ /* One tag scan of one message range: every tag, length and packed run checked.
798
+ * With `m` set it also records a slice per wire field; with `m` NULL it only
799
+ * validates, which is how sub-messages are checked without being materialized. */
800
+ static pbw_status
801
+ scan_message(message_t *m, type_t *type, const uint8_t *data, size_t off,
802
+ size_t len, uint32_t depth, const char **missing)
803
+ {
804
+ rdr r;
805
+ unsigned char *seen = NULL;
806
+ uint32_t oneof_stack[8];
807
+ uint32_t *oneof_last = oneof_stack;
808
+ int oneof_heap = 0;
809
+ pbw_status status = PBW_OK;
810
+ size_t i;
811
+
812
+ if (depth >= RB_PBW_MAX_DEPTH) {
813
+ return PBW_ERR_LIMIT;
814
+ }
815
+ if (type->has_required) {
816
+ seen = (unsigned char *)calloc(type->count, 1);
817
+ if (seen == NULL) {
818
+ return PBW_ERR_NOMEM;
819
+ }
820
+ }
821
+ if (m != NULL && type->oneofs > 0) {
822
+ if (type->oneofs > (uint32_t)(sizeof(oneof_stack) /
823
+ sizeof(*oneof_last))) {
824
+ oneof_last =
825
+ (uint32_t *)calloc(type->oneofs, sizeof(*oneof_last));
826
+ if (oneof_last == NULL) {
827
+ free(seen);
828
+ return PBW_ERR_NOMEM;
829
+ }
830
+ oneof_heap = 1;
831
+ } else {
832
+ memset(oneof_stack, 0, type->oneofs * sizeof(*oneof_last));
833
+ }
834
+ }
835
+ r.p = data + off;
836
+ r.end = r.p + len;
837
+ while (r.p < r.end) {
838
+ uint32_t fnum;
839
+ unsigned wt;
840
+ field_t *f = NULL;
841
+
842
+ if (!rd_tag(&r, &fnum, &wt)) {
843
+ status = PBW_ERR_INVALID;
844
+ goto done;
845
+ }
846
+ if (m == NULL && wt != 2 && !type->has_required) {
847
+ /* Validating only: a non-delimited value holds no fields, so only
848
+ * the bytes matter. */
849
+ if (!rd_skip(&r, fnum, wt, depth)) {
850
+ status = PBW_ERR_INVALID;
851
+ goto done;
852
+ }
853
+ continue;
854
+ }
855
+ f = type_field_by_number(type, fnum);
856
+ if (f == NULL || f->unsupported ||
857
+ (wt != (unsigned)f->wire &&
858
+ !(wt == 2 && f->repeated && packable((pbw_type)f->type)))) {
859
+ if (!rd_skip(&r, fnum, wt, depth)) {
860
+ status = PBW_ERR_INVALID;
861
+ goto done;
862
+ }
863
+ continue;
864
+ }
865
+ if (seen != NULL && f->required) {
866
+ seen[f->index] = 1;
867
+ }
868
+ if (wt == 2) {
869
+ uint64_t plen;
870
+ size_t payload;
871
+ uint32_t n = 1;
872
+
873
+ if (!rd_varint(&r, &plen) || plen > (uint64_t)(r.end - r.p)) {
874
+ status = PBW_ERR_INVALID;
875
+ goto done;
876
+ }
877
+ payload = (size_t)(r.p - data);
878
+ if (f->type == PBW_TYPE_MESSAGE) {
879
+ type_t *sub = NULL;
880
+
881
+ TypedData_Get_Struct(f->sub, type_t, &type_data_type, sub);
882
+ status = scan_message(NULL, sub, data, payload, (size_t)plen,
883
+ depth + 1, missing);
884
+ if (status != PBW_OK) {
885
+ goto done;
886
+ }
887
+ } else if (f->wire != 2) {
888
+ long count = scan_run(f, r.p, (size_t)plen);
889
+
890
+ if (count < 0) {
891
+ status = PBW_ERR_INVALID;
892
+ goto done;
893
+ }
894
+ n = (uint32_t)count;
895
+ }
896
+ r.p += (size_t)plen;
897
+ if (m != NULL &&
898
+ !slice_add(m, f, payload, (size_t)plen, n, 1, oneof_last)) {
899
+ status = PBW_ERR_NOMEM;
900
+ goto done;
901
+ }
902
+ continue;
903
+ }
904
+ {
905
+ size_t value_off = (size_t)(r.p - data);
906
+
907
+ if (!rd_skip(&r, fnum, wt, depth)) {
908
+ status = PBW_ERR_INVALID;
909
+ goto done;
910
+ }
911
+ if (m != NULL &&
912
+ !slice_add(m, f, value_off, 0, 1, 0, oneof_last)) {
913
+ status = PBW_ERR_NOMEM;
914
+ goto done;
915
+ }
916
+ }
917
+ }
918
+ if (seen != NULL) {
919
+ for (i = 0; i < type->count; i++) {
920
+ if (type->fields[i].required && !seen[i]) {
921
+ *missing = pbw_field_name(
922
+ pbw_descriptor_field_at(type->desc, i));
923
+ status = PBW_ERR_REQUIRED;
924
+ goto done;
925
+ }
926
+ }
927
+ }
928
+
929
+ done:
930
+ if (oneof_heap) {
931
+ free(oneof_last);
932
+ }
933
+ free(seen);
934
+ return status;
935
+ }
936
+
937
+ static void
938
+ scan_check(pbw_status status, type_t *type, const char *missing)
939
+ {
940
+ switch (status) {
941
+ case PBW_OK:
942
+ return;
943
+ case PBW_ERR_NOMEM:
944
+ rb_raise(eError, "out of memory");
945
+ return;
946
+ case PBW_ERR_LIMIT:
947
+ rb_raise(eError, "%s: nesting limit exceeded", type_name(type));
948
+ return;
949
+ case PBW_ERR_REQUIRED:
950
+ rb_raise(eError, "%s: required field %s is missing", type_name(type),
951
+ missing != NULL ? missing : "?");
952
+ return;
953
+ default:
954
+ rb_raise(eError, "%s: invalid serialized data", type_name(type));
955
+ return;
956
+ }
957
+ }
958
+
959
+ /* ----------------------------------------------------------- wire -> Ruby */
960
+
961
+ static VALUE
962
+ scalar_to_ruby(uint8_t type, uint64_t bits)
963
+ {
964
+ switch ((pbw_type)type) {
965
+ case PBW_TYPE_INT32:
966
+ case PBW_TYPE_SINT32:
967
+ case PBW_TYPE_SFIXED32:
968
+ case PBW_TYPE_ENUM:
969
+ return LL2NUM((int32_t)bits);
970
+ case PBW_TYPE_UINT32:
971
+ case PBW_TYPE_FIXED32:
972
+ return ULL2NUM((uint32_t)bits);
973
+ case PBW_TYPE_INT64:
974
+ case PBW_TYPE_SINT64:
975
+ case PBW_TYPE_SFIXED64:
976
+ return LL2NUM((int64_t)bits);
977
+ case PBW_TYPE_UINT64:
978
+ case PBW_TYPE_FIXED64:
979
+ return ULL2NUM(bits);
980
+ case PBW_TYPE_BOOL:
981
+ return bits != 0 ? Qtrue : Qfalse;
982
+ case PBW_TYPE_FLOAT: {
983
+ uint32_t u = (uint32_t)bits;
984
+ float f;
985
+
986
+ memcpy(&f, &u, 4);
987
+ return rb_float_new((double)f);
988
+ }
989
+ case PBW_TYPE_DOUBLE: {
990
+ double d;
991
+
992
+ memcpy(&d, &bits, 8);
993
+ return rb_float_new(d);
994
+ }
995
+ default:
996
+ rb_raise(eError, "unsupported scalar type");
997
+ return Qnil;
998
+ }
999
+ }
1000
+
1001
+ static uint64_t
1002
+ unzigzag(uint64_t value, unsigned width)
1003
+ {
1004
+ uint64_t mask = width == 32 ? 0xffffffffull : ~0ull;
1005
+
1006
+ value &= mask;
1007
+ return ((value >> 1) ^ (0ull - (value & 1))) & mask;
1008
+ }
1009
+
1010
+ static VALUE
1011
+ string_from(uint8_t type, const uint8_t *p, size_t len)
1012
+ {
1013
+ if (type == PBW_TYPE_STRING) {
1014
+ return rb_utf8_str_new((const char *)p, (long)len);
1015
+ }
1016
+ return rb_str_new((const char *)p, (long)len);
1017
+ }
1018
+
1019
+ /* One scalar at `p`, bounded by `end`; `used` reports the bytes consumed. */
1020
+ static VALUE
1021
+ scalar_at(field_t *f, const uint8_t *p, const uint8_t *end, size_t *used)
1022
+ {
1023
+ rdr r;
1024
+ uint64_t bits = 0;
1025
+
1026
+ r.p = p;
1027
+ r.end = end;
1028
+ if (f->wire == 0) {
1029
+ if (!rd_varint(&r, &bits)) {
1030
+ rb_raise(eError, "invalid serialized data");
1031
+ }
1032
+ if (f->type == PBW_TYPE_SINT32 || f->type == PBW_TYPE_SINT64) {
1033
+ bits = unzigzag(bits, f->type == PBW_TYPE_SINT32 ? 32 : 64);
1034
+ }
1035
+ } else if (!rd_fixed(&r, &bits, f->wire == 1 ? 8 : 4)) {
1036
+ rb_raise(eError, "invalid serialized data");
1037
+ }
1038
+ if (used != NULL) {
1039
+ *used = (size_t)(r.p - p);
1040
+ }
1041
+ return scalar_to_ruby(f->type, bits);
1042
+ }
1043
+
1044
+ static VALUE message_wire_new(VALUE type, VALUE buffer, size_t off, size_t len,
1045
+ uint32_t depth);
1046
+ static VALUE field_value(message_t *m, field_t *f);
1047
+
1048
+ /* One repeated slice: a single unpacked value, or a whole packed run. */
1049
+ static void
1050
+ push_slice(message_t *m, field_t *f, const slice_t *s, VALUE array)
1051
+ {
1052
+ const uint8_t *p = m->data + s->off;
1053
+ const uint8_t *end = s->delimited ? p + s->len : m->data + m->off + m->len;
1054
+
1055
+ for (;;) {
1056
+ size_t used = 0;
1057
+
1058
+ rb_ary_push(array, scalar_at(f, p, end, &used));
1059
+ if (!s->delimited) {
1060
+ return;
1061
+ }
1062
+ p += used;
1063
+ if (p >= end) {
1064
+ return;
1065
+ }
1066
+ }
1067
+ }
1068
+
1069
+ /* A singular message field that appears more than once merges: the payloads
1070
+ * concatenate, which is what parsing them as one message means. */
1071
+ static VALUE
1072
+ joined_message(message_t *m, field_t *f)
1073
+ {
1074
+ size_t total = 0;
1075
+ size_t i;
1076
+ VALUE buffer;
1077
+ char *dst;
1078
+
1079
+ for (i = 0; i < m->nslices; i++) {
1080
+ if (m->slices[i].fidx == f->index) {
1081
+ total += m->slices[i].len;
1082
+ }
1083
+ }
1084
+ buffer = rb_str_new(NULL, (long)total);
1085
+ dst = RSTRING_PTR(buffer);
1086
+ for (i = 0; i < m->nslices; i++) {
1087
+ if (m->slices[i].fidx == f->index) {
1088
+ memcpy(dst, m->data + m->slices[i].off, m->slices[i].len);
1089
+ dst += m->slices[i].len;
1090
+ }
1091
+ }
1092
+ return message_wire_new(f->sub, rb_str_new_frozen(buffer), 0, total,
1093
+ m->depth + 1);
1094
+ }
1095
+
1096
+ static VALUE
1097
+ field_value(message_t *m, field_t *f)
1098
+ {
1099
+ ssize_t last = -1;
1100
+ uint32_t i;
1101
+
1102
+ if (!f->repeated) {
1103
+ for (i = m->nslices; i > 0; i--) {
1104
+ if (m->slices[i - 1].fidx == f->index) {
1105
+ last = (ssize_t)(i - 1);
1106
+ break;
1107
+ }
1108
+ }
1109
+ if (last < 0) {
1110
+ return Qnil;
1111
+ }
1112
+ if (f->type == PBW_TYPE_MESSAGE) {
1113
+ uint32_t n = 0;
1114
+
1115
+ for (i = 0; i < m->nslices; i++) {
1116
+ n += m->slices[i].fidx == f->index;
1117
+ }
1118
+ if (n > 1) {
1119
+ return joined_message(m, f);
1120
+ }
1121
+ return message_wire_new(f->sub, m->buffer,
1122
+ m->slices[last].off, m->slices[last].len,
1123
+ m->depth + 1);
1124
+ }
1125
+ if (f->type == PBW_TYPE_STRING || f->type == PBW_TYPE_BYTES) {
1126
+ return string_from(f->type, m->data + m->slices[last].off,
1127
+ m->slices[last].len);
1128
+ }
1129
+ return scalar_at(f, m->data + m->slices[last].off,
1130
+ m->data + m->off + m->len, NULL);
1131
+ }
1132
+
1133
+ {
1134
+ uint32_t count = 0;
1135
+ size_t total = 0;
1136
+
1137
+ for (i = 0; i < m->nslices; i++) {
1138
+ if (m->slices[i].fidx == f->index) {
1139
+ count++;
1140
+ total += m->slices[i].n;
1141
+ }
1142
+ }
1143
+ if (count == 0) {
1144
+ return rb_ary_new();
1145
+ }
1146
+ {
1147
+ VALUE array = rb_ary_new_capa((long)total);
1148
+
1149
+ for (i = 0; i < m->nslices; i++) {
1150
+ const slice_t *s = &m->slices[i];
1151
+
1152
+ if (s->fidx != f->index) {
1153
+ continue;
1154
+ }
1155
+ if (f->type == PBW_TYPE_MESSAGE) {
1156
+ rb_ary_push(array, message_wire_new(f->sub, m->buffer,
1157
+ s->off, s->len,
1158
+ m->depth + 1));
1159
+ } else if (f->type == PBW_TYPE_STRING ||
1160
+ f->type == PBW_TYPE_BYTES) {
1161
+ rb_ary_push(array,
1162
+ string_from(f->type, m->data + s->off, s->len));
1163
+ } else {
1164
+ push_slice(m, f, s, array);
1165
+ }
1166
+ }
1167
+ return array;
1168
+ }
1169
+ }
1170
+ }
1171
+
1172
+ /* ------------------------------------------------------ message lifecycle */
1173
+
1174
+ static VALUE
1175
+ message_wire_new(VALUE type, VALUE buffer, size_t off, size_t len,
1176
+ uint32_t depth)
1177
+ {
1178
+ message_t *message;
1179
+ type_t *t;
1180
+ const char *missing = NULL;
1181
+ pbw_status status;
1182
+ VALUE obj;
1183
+
1184
+ TypedData_Get_Struct(type, type_t, &type_data_type, t);
1185
+ obj = typed_object_alloc(cMessage, &message_data_type,
1186
+ (void **)&message);
1187
+ message->kind = MSG_WIRE;
1188
+ message->type = type;
1189
+ message->buffer = buffer;
1190
+ message->data = (const uint8_t *)RSTRING_PTR(buffer);
1191
+ message->off = off;
1192
+ message->len = len;
1193
+ message->depth = depth;
1194
+ status = scan_message(message, t, message->data, off, len, depth, &missing);
1195
+ if (status != PBW_OK) {
1196
+ scan_check(status, t, missing);
1197
+ }
1198
+ return obj;
1199
+ }
1200
+
1201
+ /* A builder: an empty C message of the type. */
1202
+ static VALUE message_builder_new(VALUE type, pbw_holder *holder,
1203
+ pbw_message *tree, VALUE parent, int owned);
1204
+
1205
+ /* A sub-message reached through a builder: the parent owns the tree, so the
1206
+ * Ruby object only borrows it (and marks the parent alive). */
1207
+ static VALUE
1208
+ message_borrowed(VALUE parent, VALUE type, pbw_message *tree)
1209
+ {
1210
+ message_t *message;
1211
+ message_t *owner;
1212
+ VALUE obj = typed_object_alloc(cMessage, &message_data_type,
1213
+ (void **)&message);
1214
+
1215
+ TypedData_Get_Struct(parent, message_t, &message_data_type, owner);
1216
+ message->kind = MSG_BUILDER;
1217
+ message->type = type;
1218
+ message->tree = tree;
1219
+ message->holder = owner->holder;
1220
+ message->parent = parent;
1221
+ message->owned = 0;
1222
+ holder_ref(owner->holder);
1223
+ return obj;
1224
+ }
1225
+
1226
+ static VALUE
1227
+ message_builder_new(VALUE type, pbw_holder *holder, pbw_message *tree,
1228
+ VALUE parent, int owned)
1229
+ {
1230
+ message_t *message;
1231
+ VALUE obj = typed_object_alloc(cMessage, &message_data_type,
1232
+ (void **)&message);
1233
+
1234
+ message->kind = MSG_BUILDER;
1235
+ message->type = type;
1236
+ message->tree = tree;
1237
+ message->holder = holder;
1238
+ message->parent = parent;
1239
+ message->owned = owned;
1240
+ holder_ref(holder);
1241
+ return obj;
1242
+ }
1243
+
1244
+ static pbw_message *
1245
+ message_tree(VALUE obj, message_t **out)
1246
+ {
1247
+ message_t *message;
1248
+ VALUE parent;
1249
+
1250
+ TypedData_Get_Struct(obj, message_t, &message_data_type, message);
1251
+ if (out != NULL) {
1252
+ *out = message;
1253
+ }
1254
+ if (message->kind == MSG_CLOSED) {
1255
+ rb_raise(eError, "%s: message is closed",
1256
+ type_name(message_type_of(obj)));
1257
+ }
1258
+ if (message->kind != MSG_BUILDER) {
1259
+ rb_raise(eError, "%s: decoded messages are read-only",
1260
+ type_name(message_type_of(obj)));
1261
+ }
1262
+ parent = message->parent;
1263
+ while (!NIL_P(parent)) {
1264
+ message_t *owner;
1265
+
1266
+ TypedData_Get_Struct(parent, message_t, &message_data_type, owner);
1267
+ if (owner->kind != MSG_BUILDER) {
1268
+ rb_raise(eError, "%s: parent message is closed",
1269
+ type_name(message_type_of(obj)));
1270
+ }
1271
+ parent = owner->parent;
1272
+ }
1273
+ return message->tree;
1274
+ }
1275
+
1276
+ /* Drops this object's view of the tree without freeing it (hand-over). */
1277
+ static void
1278
+ message_forget(message_t *message)
1279
+ {
1280
+ pbw_holder *holder = message->holder;
1281
+
1282
+ message->tree = NULL;
1283
+ message->holder = NULL;
1284
+ message->parent = Qnil;
1285
+ message->kind = MSG_CLOSED;
1286
+ holder_release(holder);
1287
+ }
1288
+
1289
+ /* ---------------------------------------------------- builder: Ruby -> core */
1290
+
1291
+ static void
1292
+ value_error(VALUE owner, field_t *f, const char *expected)
1293
+ {
1294
+ rb_raise(rb_eTypeError, "%s.%s: expected %s",
1295
+ type_name(message_type_of(owner)), RSTRING_PTR(f->name), expected);
1296
+ }
1297
+
1298
+ /* Everything value_build() would reject, checked before any value is allocated,
1299
+ * so a bad element cannot leave a half-applied repeated field behind. */
1300
+ static void
1301
+ validate_value(VALUE owner, field_t *f, VALUE value)
1302
+ {
1303
+ switch ((pbw_type)f->type) {
1304
+ case PBW_TYPE_STRING:
1305
+ case PBW_TYPE_BYTES:
1306
+ if (!RB_TYPE_P(value, T_STRING)) {
1307
+ value_error(owner, f, "a String");
1308
+ }
1309
+ return;
1310
+ case PBW_TYPE_MESSAGE: {
1311
+ message_t *sub;
1312
+
1313
+ if (!rb_obj_is_kind_of(value, cMessage)) {
1314
+ value_error(owner, f, "a message");
1315
+ }
1316
+ if (value == owner) {
1317
+ rb_raise(eError, "a message cannot contain itself");
1318
+ }
1319
+ TypedData_Get_Struct(value, message_t, &message_data_type, sub);
1320
+ if (sub->kind == MSG_CLOSED || sub->tree == NULL) {
1321
+ rb_raise(eError, "message is closed");
1322
+ }
1323
+ if (!sub->owned) {
1324
+ rb_raise(eError,
1325
+ "a borrowed sub-message cannot be moved to another "
1326
+ "message");
1327
+ }
1328
+ if (sub->type != f->sub) {
1329
+ type_t *subtype;
1330
+
1331
+ TypedData_Get_Struct(f->sub, type_t, &type_data_type, subtype);
1332
+ rb_raise(rb_eTypeError, "%s.%s: expected a %s message",
1333
+ type_name(message_type_of(owner)), RSTRING_PTR(f->name),
1334
+ type_name(subtype));
1335
+ }
1336
+ return;
1337
+ }
1338
+ case PBW_TYPE_GROUP:
1339
+ rb_raise(eError, "%s: group fields are not supported",
1340
+ RSTRING_PTR(f->name));
1341
+ return;
1342
+ case PBW_TYPE_FLOAT:
1343
+ case PBW_TYPE_DOUBLE:
1344
+ if (!RB_INTEGER_TYPE_P(value) && !RB_FLOAT_TYPE_P(value)) {
1345
+ value_error(owner, f, "a Numeric");
1346
+ }
1347
+ return;
1348
+ case PBW_TYPE_BOOL:
1349
+ if (value != Qtrue && value != Qfalse && !NIL_P(value)) {
1350
+ value_error(owner, f, "true or false");
1351
+ }
1352
+ return;
1353
+ default:
1354
+ if (!RB_INTEGER_TYPE_P(value)) {
1355
+ value_error(owner, f, "an Integer");
1356
+ }
1357
+ return;
1358
+ }
1359
+ }
1360
+
1361
+ /* A value the caller either stores or frees. NULL means allocation failure, or
1362
+ * - when `moved` is set - a message that was already handed to another field by
1363
+ * an earlier element of the same repeated assignment. */
1364
+ static pbw_value *
1365
+ value_build(field_t *f, VALUE value, int *moved)
1366
+ {
1367
+ switch ((pbw_type)f->type) {
1368
+ case PBW_TYPE_STRING:
1369
+ case PBW_TYPE_BYTES:
1370
+ StringValue(value);
1371
+ return pbw_value_new_bytes(RSTRING_PTR(value),
1372
+ (size_t)RSTRING_LEN(value));
1373
+ case PBW_TYPE_MESSAGE: {
1374
+ message_t *sub;
1375
+ pbw_message *tree;
1376
+ pbw_value *built;
1377
+
1378
+ TypedData_Get_Struct(value, message_t, &message_data_type, sub);
1379
+ tree = sub->tree;
1380
+ if (tree == NULL) {
1381
+ *moved = 1;
1382
+ return NULL;
1383
+ }
1384
+ built = pbw_value_new_message(tree);
1385
+ if (built == NULL) {
1386
+ pbw_message_free(tree);
1387
+ return NULL;
1388
+ }
1389
+ message_forget(sub);
1390
+ return built;
1391
+ }
1392
+ case PBW_TYPE_FLOAT:
1393
+ return pbw_value_new_float((float)NUM2DBL(value));
1394
+ case PBW_TYPE_DOUBLE:
1395
+ return pbw_value_new_double(NUM2DBL(value));
1396
+ case PBW_TYPE_BOOL:
1397
+ return pbw_value_new_bool(value == Qtrue ? 1 : 0);
1398
+ case PBW_TYPE_INT32:
1399
+ case PBW_TYPE_INT64:
1400
+ case PBW_TYPE_SINT32:
1401
+ case PBW_TYPE_SINT64:
1402
+ case PBW_TYPE_SFIXED32:
1403
+ case PBW_TYPE_SFIXED64:
1404
+ case PBW_TYPE_ENUM:
1405
+ return pbw_value_new_int(NUM2LL(value));
1406
+ default:
1407
+ return pbw_value_new_uint(NUM2ULL(value));
1408
+ }
1409
+ }
1410
+
1411
+ /* --------------------------------------------------------- Ruby methods */
1412
+
1413
+ /* One value of a builder's tree as the Ruby value of its field. */
1414
+ static VALUE
1415
+ item_to_ruby(VALUE owner, field_t *f, pbw_value *value)
1416
+ {
1417
+ switch ((pbw_type)f->type) {
1418
+ case PBW_TYPE_MESSAGE: {
1419
+ pbw_message *child = pbw_value_get_message(value);
1420
+
1421
+ return child == NULL ? Qnil : message_borrowed(owner, f->sub, child);
1422
+ }
1423
+ case PBW_TYPE_STRING:
1424
+ case PBW_TYPE_BYTES: {
1425
+ size_t len = 0;
1426
+ const uint8_t *data = (const uint8_t *)pbw_value_get_bytes(value, &len);
1427
+
1428
+ return string_from(f->type, data, len);
1429
+ }
1430
+ case PBW_TYPE_FLOAT:
1431
+ return rb_float_new((double)pbw_value_get_float(value));
1432
+ case PBW_TYPE_DOUBLE:
1433
+ return rb_float_new(pbw_value_get_double(value));
1434
+ case PBW_TYPE_BOOL:
1435
+ return pbw_value_get_bool(value) ? Qtrue : Qfalse;
1436
+ case PBW_TYPE_INT32:
1437
+ case PBW_TYPE_INT64:
1438
+ case PBW_TYPE_SINT32:
1439
+ case PBW_TYPE_SINT64:
1440
+ case PBW_TYPE_SFIXED32:
1441
+ case PBW_TYPE_SFIXED64:
1442
+ case PBW_TYPE_ENUM:
1443
+ return LL2NUM(pbw_value_get_int(value));
1444
+ default:
1445
+ return ULL2NUM(pbw_value_get_uint(value));
1446
+ }
1447
+ }
1448
+
1449
+ static VALUE
1450
+ schema_s_load(VALUE klass, VALUE bytes)
1451
+ {
1452
+ pbw_schema *schema = NULL;
1453
+ pbw_status status;
1454
+ schema_t *self;
1455
+ VALUE obj;
1456
+
1457
+ StringValue(bytes);
1458
+ status = pbw_descriptor_set_load(RSTRING_PTR(bytes),
1459
+ (size_t)RSTRING_LEN(bytes), &schema);
1460
+ if (status != PBW_OK) {
1461
+ const char *reason = pbw_schema_error(schema);
1462
+ pbw_schema_free(schema);
1463
+ rb_raise(eError, "descriptor set rejected: %s",
1464
+ reason != NULL && reason[0] != '\0' ? reason
1465
+ : pbw_strerror(status));
1466
+ }
1467
+ obj = typed_object_alloc(klass, &schema_data_type, (void **)&self);
1468
+ self->holder = holder_new(schema);
1469
+ self->types = Qnil;
1470
+ self->closed = 0;
1471
+ return obj;
1472
+ }
1473
+
1474
+ static VALUE
1475
+ schema_s_from_file(VALUE klass, VALUE path)
1476
+ {
1477
+ VALUE bytes = rb_funcall(rb_cFile, rb_intern2("binread", 7), 1, path);
1478
+
1479
+ return schema_s_load(klass, bytes);
1480
+ }
1481
+
1482
+ static VALUE
1483
+ schema_message(VALUE self, VALUE name)
1484
+ {
1485
+ pbw_schema *schema = schema_ptr(self);
1486
+ const pbw_descriptor *desc;
1487
+ pbw_message *tree;
1488
+ schema_t *own;
1489
+ VALUE type;
1490
+
1491
+ StringValue(name);
1492
+ desc = pbw_schema_find(schema, StringValueCStr(name));
1493
+ if (desc == NULL || pbw_descriptor_is_enum(desc)) {
1494
+ rb_raise(eError, "no message %" PRIsVALUE " in the schema", name);
1495
+ }
1496
+ tree = pbw_message_new(desc);
1497
+ if (tree == NULL) {
1498
+ rb_raise(eError, "out of memory");
1499
+ }
1500
+ TypedData_Get_Struct(self, schema_t, &schema_data_type, own);
1501
+ type = type_for(self, desc);
1502
+ return message_builder_new(type, own->holder, tree, Qnil, 1);
1503
+ }
1504
+
1505
+ static VALUE
1506
+ schema_close(VALUE self)
1507
+ {
1508
+ schema_t *schema;
1509
+
1510
+ TypedData_Get_Struct(self, schema_t, &schema_data_type, schema);
1511
+ if (!schema->closed && schema->holder != NULL) {
1512
+ schema->closed = 1;
1513
+ schema->types = Qnil;
1514
+ holder_close(schema->holder);
1515
+ }
1516
+ return self;
1517
+ }
1518
+
1519
+ static VALUE
1520
+ schema_closed_p(VALUE self)
1521
+ {
1522
+ schema_t *schema;
1523
+
1524
+ TypedData_Get_Struct(self, schema_t, &schema_data_type, schema);
1525
+ return schema->closed ? Qtrue : Qfalse;
1526
+ }
1527
+
1528
+ static VALUE
1529
+ schema_inspect(VALUE self)
1530
+ {
1531
+ schema_t *schema;
1532
+
1533
+ TypedData_Get_Struct(self, schema_t, &schema_data_type, schema);
1534
+ return rb_sprintf("#<%" PRIsVALUE " %s>", rb_obj_class(self),
1535
+ schema->closed ? "closed" : "open");
1536
+ }
1537
+
1538
+ static VALUE
1539
+ message_type(VALUE self)
1540
+ {
1541
+ message_t *message;
1542
+
1543
+ TypedData_Get_Struct(self, message_t, &message_data_type, message);
1544
+ if (message->kind == MSG_CLOSED) {
1545
+ rb_raise(eError, "%s: message is closed",
1546
+ type_name(message_type_of(self)));
1547
+ }
1548
+ return rb_utf8_str_new_cstr(type_name(message_type_of(self)));
1549
+ }
1550
+
1551
+ static VALUE
1552
+ message_set(VALUE self, VALUE key, VALUE value)
1553
+ {
1554
+ message_t *message;
1555
+ pbw_message *tree = message_tree(self, &message);
1556
+ type_t *type = message_type_of(self);
1557
+ field_t *f = field_lookup(type, key);
1558
+ const pbw_field *descriptor_field =
1559
+ pbw_descriptor_field_at(type->desc, (size_t)f->index);
1560
+ pbw_status status;
1561
+ int moved = 0;
1562
+
1563
+ if (!f->repeated) {
1564
+ pbw_value *built;
1565
+
1566
+ validate_value(self, f, value);
1567
+ built = value_build(f, value, &moved);
1568
+ if (built == NULL) {
1569
+ if (moved) {
1570
+ rb_raise(eError, "%s.%s: the message was already moved",
1571
+ type_name(type), RSTRING_PTR(f->name));
1572
+ }
1573
+ rb_raise(eError, "out of memory");
1574
+ }
1575
+ status = pbw_message_set_field(tree, descriptor_field, built);
1576
+ if (status != PBW_OK) {
1577
+ pbw_value_free(built);
1578
+ rb_raise(eError, "%s.%s: %s", type_name(type),
1579
+ RSTRING_PTR(f->name), pbw_strerror(status));
1580
+ }
1581
+ return self;
1582
+ }
1583
+ {
1584
+ long count;
1585
+ long i;
1586
+ pbw_value **values;
1587
+
1588
+ Check_Type(value, T_ARRAY);
1589
+ count = RARRAY_LEN(value);
1590
+ for (i = 0; i < count; i++) {
1591
+ validate_value(self, f, RARRAY_AREF(value, i));
1592
+ }
1593
+ values = count > 0 ? ALLOC_N(pbw_value *, (size_t)count) : NULL;
1594
+ for (i = 0; i < count; i++) {
1595
+ values[i] = value_build(f, RARRAY_AREF(value, i), &moved);
1596
+ if (values[i] == NULL) {
1597
+ long j;
1598
+
1599
+ for (j = 0; j < i; j++) {
1600
+ pbw_value_free(values[j]);
1601
+ }
1602
+ xfree(values);
1603
+ if (moved) {
1604
+ rb_raise(eError, "%s.%s: the message was already moved",
1605
+ type_name(type), RSTRING_PTR(f->name));
1606
+ }
1607
+ rb_raise(eError, "out of memory");
1608
+ }
1609
+ }
1610
+ pbw_message_clear(tree, f->number);
1611
+ for (i = 0; i < count; i++) {
1612
+ status = pbw_message_set_field(tree, descriptor_field, values[i]);
1613
+ if (status != PBW_OK) {
1614
+ long j;
1615
+
1616
+ for (j = i; j < count; j++) {
1617
+ pbw_value_free(values[j]);
1618
+ }
1619
+ xfree(values);
1620
+ rb_raise(eError, "%s.%s: %s", type_name(type),
1621
+ RSTRING_PTR(f->name), pbw_strerror(status));
1622
+ }
1623
+ }
1624
+ xfree(values);
1625
+ return self;
1626
+ }
1627
+ }
1628
+
1629
+ static VALUE
1630
+ message_get(VALUE self, VALUE key)
1631
+ {
1632
+ message_t *message;
1633
+
1634
+ TypedData_Get_Struct(self, message_t, &message_data_type, message);
1635
+ if (message->kind == MSG_CLOSED) {
1636
+ rb_raise(eError, "%s: message is closed",
1637
+ type_name(message_type_of(self)));
1638
+ }
1639
+ {
1640
+ type_t *type = message_type_of(self);
1641
+ field_t *f = field_lookup(type, key);
1642
+
1643
+ if (f->unsupported) {
1644
+ rb_raise(eError, "%s: group fields are not supported",
1645
+ RSTRING_PTR(f->name));
1646
+ }
1647
+ if (message->kind == MSG_WIRE) {
1648
+ return field_value(message, f);
1649
+ }
1650
+ {
1651
+ /* Also checks that no parent this builder was borrowed from has
1652
+ * been closed under it. */
1653
+ pbw_message *tree = message_tree(self, &message);
1654
+ pbw_value *value = pbw_message_get_field(
1655
+ tree, pbw_descriptor_field_at(type->desc, (size_t)f->index));
1656
+
1657
+ if (f->repeated) {
1658
+ VALUE array;
1659
+ size_t count;
1660
+ size_t i;
1661
+
1662
+ if (value == NULL) {
1663
+ return rb_ary_new();
1664
+ }
1665
+ count = pbw_value_count(value);
1666
+ array = rb_ary_new_capa((long)count);
1667
+ for (i = 0; i < count; i++) {
1668
+ rb_ary_push(array,
1669
+ item_to_ruby(self, f, pbw_value_at(value, i)));
1670
+ }
1671
+ return array;
1672
+ }
1673
+ if (value == NULL) {
1674
+ return Qnil;
1675
+ }
1676
+ return item_to_ruby(self, f, value);
1677
+ }
1678
+ }
1679
+ }
1680
+
1681
+ static VALUE
1682
+ message_encode(VALUE self)
1683
+ {
1684
+ message_t *message;
1685
+
1686
+ TypedData_Get_Struct(self, message_t, &message_data_type, message);
1687
+ if (message->kind == MSG_CLOSED) {
1688
+ rb_raise(eError, "%s: message is closed",
1689
+ type_name(message_type_of(self)));
1690
+ }
1691
+ if (message->kind == MSG_WIRE) {
1692
+ VALUE out = rb_str_new((const char *)message->data + message->off,
1693
+ (long)message->len);
1694
+
1695
+ return out;
1696
+ }
1697
+ {
1698
+ pbw_message *tree = message_tree(self, &message);
1699
+ size_t cap = message->enc_cap;
1700
+ size_t wire = pbw_message_wire_size(tree);
1701
+
1702
+ if (cap == 0) {
1703
+ cap = wire > 0 ? wire + 32 : 256;
1704
+ } else {
1705
+ cap += 32;
1706
+ }
1707
+ for (;;) {
1708
+ VALUE out = rb_str_buf_new((long)cap);
1709
+ size_t len = 0;
1710
+ pbw_status status =
1711
+ pbw_encode_to(tree, RSTRING_PTR(out), cap, &len);
1712
+
1713
+ if (status == PBW_OK) {
1714
+ rb_str_set_len(out, (long)len);
1715
+ message->enc_cap = len;
1716
+ return out;
1717
+ }
1718
+ if (status != PBW_ERR_LIMIT) {
1719
+ rb_raise(eError, "%s: %s",
1720
+ type_name(message_type_of(self)),
1721
+ pbw_strerror(status));
1722
+ }
1723
+ if (cap > ((size_t)-1) / 2) {
1724
+ rb_raise(eError, "%s: message too large to encode",
1725
+ type_name(message_type_of(self)));
1726
+ }
1727
+ cap *= 2;
1728
+ }
1729
+ }
1730
+ }
1731
+
1732
+ static VALUE
1733
+ message_decode(VALUE self, VALUE bytes)
1734
+ {
1735
+ message_t *message;
1736
+ VALUE buffer;
1737
+
1738
+ TypedData_Get_Struct(self, message_t, &message_data_type, message);
1739
+ if (message->kind == MSG_CLOSED) {
1740
+ rb_raise(eError, "%s: message is closed",
1741
+ type_name(message_type_of(self)));
1742
+ }
1743
+ StringValue(bytes);
1744
+ buffer = rb_str_new_frozen(bytes);
1745
+ return message_wire_new(message->type, buffer, 0,
1746
+ (size_t)RSTRING_LEN(buffer), 0);
1747
+ }
1748
+
1749
+ static VALUE
1750
+ message_close(VALUE self)
1751
+ {
1752
+ message_t *message;
1753
+
1754
+ TypedData_Get_Struct(self, message_t, &message_data_type, message);
1755
+ if (message->kind == MSG_BUILDER) {
1756
+ if (message->owned && message->tree != NULL) {
1757
+ pbw_message_free(message->tree);
1758
+ }
1759
+ message->tree = NULL;
1760
+ holder_release(message->holder);
1761
+ message->holder = NULL;
1762
+ message->parent = Qnil;
1763
+ }
1764
+ if (message->slices != message->inline_slices) {
1765
+ free(message->slices);
1766
+ message->slices = message->inline_slices;
1767
+ message->nslices = 0;
1768
+ message->cap = SLICE_INLINE;
1769
+ }
1770
+ message->buffer = Qnil;
1771
+ message->data = NULL;
1772
+ message->kind = MSG_CLOSED;
1773
+ return self;
1774
+ }
1775
+
1776
+ static VALUE
1777
+ message_closed_p(VALUE self)
1778
+ {
1779
+ message_t *message;
1780
+
1781
+ TypedData_Get_Struct(self, message_t, &message_data_type, message);
1782
+ return message->kind == MSG_CLOSED ? Qtrue : Qfalse;
1783
+ }
1784
+
1785
+ static VALUE
1786
+ message_inspect(VALUE self)
1787
+ {
1788
+ message_t *message;
1789
+
1790
+ TypedData_Get_Struct(self, message_t, &message_data_type, message);
1791
+ if (message->kind == MSG_CLOSED) {
1792
+ return rb_sprintf("#<%" PRIsVALUE " closed>", rb_obj_class(self));
1793
+ }
1794
+ return rb_sprintf("#<%" PRIsVALUE " %s>", rb_obj_class(self),
1795
+ type_name(message_type_of(self)));
1796
+ }
1797
+
1798
+ /* ------------------------------------------------------------- extension */
1799
+
1800
+ void
1801
+ Init_pbwire_ext(void)
1802
+ {
1803
+ mPbwire = rb_define_module("Pbwire");
1804
+ eError = rb_define_class_under(mPbwire, "Error", rb_eStandardError);
1805
+
1806
+ rb_define_const(mPbwire, "ABI_VERSION", INT2NUM(PBW_ABI_VERSION));
1807
+
1808
+ cSchema = rb_define_class_under(mPbwire, "Schema", rb_cObject);
1809
+ rb_define_alloc_func(cSchema, schema_alloc);
1810
+ rb_define_singleton_method(cSchema, "from_bytes", schema_s_load, 1);
1811
+ rb_define_singleton_method(cSchema, "from_file", schema_s_from_file, 1);
1812
+ rb_define_method(cSchema, "message", schema_message, 1);
1813
+ rb_define_method(cSchema, "close", schema_close, 0);
1814
+ rb_define_method(cSchema, "release", schema_close, 0);
1815
+ rb_define_method(cSchema, "closed?", schema_closed_p, 0);
1816
+ rb_define_method(cSchema, "inspect", schema_inspect, 0);
1817
+ rb_define_method(cSchema, "to_s", schema_inspect, 0);
1818
+
1819
+ cType = rb_define_class_under(mPbwire, "Type", rb_cObject);
1820
+ rb_define_alloc_func(cType, type_alloc);
1821
+
1822
+ cMessage = rb_define_class_under(mPbwire, "Message", rb_cObject);
1823
+ rb_define_alloc_func(cMessage, message_alloc);
1824
+ rb_define_method(cMessage, "type", message_type, 0);
1825
+ rb_define_method(cMessage, "set", message_set, 2);
1826
+ rb_define_method(cMessage, "[]=", message_set, 2);
1827
+ rb_define_method(cMessage, "get", message_get, 1);
1828
+ rb_define_method(cMessage, "[]", message_get, 1);
1829
+ rb_define_method(cMessage, "encode", message_encode, 0);
1830
+ rb_define_method(cMessage, "decode", message_decode, 1);
1831
+ rb_define_method(cMessage, "close", message_close, 0);
1832
+ rb_define_method(cMessage, "release", message_close, 0);
1833
+ rb_define_method(cMessage, "closed?", message_closed_p, 0);
1834
+ rb_define_method(cMessage, "inspect", message_inspect, 0);
1835
+ rb_define_method(cMessage, "to_s", message_inspect, 0);
1836
+ }