protobuf/ruby/ext/google/protobuf_c/map.c
Go to the documentation of this file.
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2014 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 #include "convert.h"
32 #include "defs.h"
33 #include "message.h"
34 #include "protobuf.h"
35 
36 // -----------------------------------------------------------------------------
37 // Basic map operations on top of upb_map.
38 //
39 // Note that we roll our own `Map` container here because, as for
40 // `RepeatedField`, we want a strongly-typed container. This is so that any user
41 // errors due to incorrect map key or value types are raised as close as
42 // possible to the error site, rather than at some deferred point (e.g.,
43 // serialization).
44 // -----------------------------------------------------------------------------
45 
46 // -----------------------------------------------------------------------------
47 // Map container type.
48 // -----------------------------------------------------------------------------
49 
50 typedef struct {
51  const upb_map *map; // Can convert to mutable when non-frozen.
54  VALUE value_type_class;
55  VALUE arena;
56 } Map;
57 
58 static void Map_mark(void* _self) {
59  Map* self = _self;
60  rb_gc_mark(self->value_type_class);
61  rb_gc_mark(self->arena);
62 }
63 
64 const rb_data_type_t Map_type = {
65  "Google::Protobuf::Map",
66  { Map_mark, RUBY_DEFAULT_FREE, NULL },
67  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
68 };
69 
70 VALUE cMap;
71 
72 static Map* ruby_to_Map(VALUE _self) {
73  Map* self;
74  TypedData_Get_Struct(_self, Map, &Map_type, self);
75  return self;
76 }
77 
78 static VALUE Map_alloc(VALUE klass) {
79  Map* self = ALLOC(Map);
80  self->map = NULL;
81  self->value_type_class = Qnil;
82  self->value_type_info.def.msgdef = NULL;
83  self->arena = Qnil;
84  return TypedData_Wrap_Struct(klass, &Map_type, self);
85 }
86 
88  TypeInfo value_type, VALUE arena) {
90 
91  VALUE val = ObjectCache_Get(map);
92 
93  if (val == Qnil) {
94  val = Map_alloc(cMap);
95  Map* self;
96  ObjectCache_Add(map, val);
97  TypedData_Get_Struct(val, Map, &Map_type, self);
98  self->map = map;
99  self->arena = arena;
100  self->key_type = key_type;
101  self->value_type_info = value_type;
102  if (self->value_type_info.type == UPB_TYPE_MESSAGE) {
103  const upb_msgdef *val_m = self->value_type_info.def.msgdef;
104  self->value_type_class = Descriptor_DefToClass(val_m);
105  }
106  }
107 
108  return val;
109 }
110 
111 static VALUE Map_new_this_type(Map *from) {
112  VALUE arena_rb = Arena_new();
113  upb_map* map = upb_map_new(Arena_get(arena_rb), from->key_type,
114  from->value_type_info.type);
115  VALUE ret =
116  Map_GetRubyWrapper(map, from->key_type, from->value_type_info, arena_rb);
117  PBRUBY_ASSERT(ruby_to_Map(ret)->value_type_class == from->value_type_class);
118  return ret;
119 }
120 
121 static TypeInfo Map_keyinfo(Map* self) {
122  TypeInfo ret;
123  ret.type = self->key_type;
124  ret.def.msgdef = NULL;
125  return ret;
126 }
127 
128 static upb_map *Map_GetMutable(VALUE _self) {
129  rb_check_frozen(_self);
130  return (upb_map*)ruby_to_Map(_self)->map;
131 }
132 
134  TypeInfo val_info) {
135  VALUE hash = rb_hash_new();
136  size_t iter = UPB_MAP_BEGIN;
138 
139  if (!map) return hash;
140 
141  while (upb_mapiter_next(map, &iter)) {
144  VALUE key_val = Convert_UpbToRuby(key, key_info, Qnil);
145  VALUE val_val = Scalar_CreateHash(val, val_info);
146  rb_hash_aset(hash, key_val, val_val);
147  }
148 
149  return hash;
150 }
151 
152 VALUE Map_deep_copy(VALUE obj) {
153  Map* self = ruby_to_Map(obj);
154  VALUE new_arena_rb = Arena_new();
155  upb_arena *arena = Arena_get(new_arena_rb);
156  upb_map* new_map =
157  upb_map_new(arena, self->key_type, self->value_type_info.type);
158  size_t iter = UPB_MAP_BEGIN;
159  while (upb_mapiter_next(self->map, &iter)) {
161  upb_msgval val = upb_mapiter_value(self->map, iter);
162  upb_msgval val_copy = Msgval_DeepCopy(val, self->value_type_info, arena);
163  upb_map_set(new_map, key, val_copy, arena);
164  }
165 
166  return Map_GetRubyWrapper(new_map, self->key_type, self->value_type_info,
167  new_arena_rb);
168 }
169 
170 const upb_map* Map_GetUpbMap(VALUE val, const upb_fielddef* field,
171  upb_arena* arena) {
172  const upb_fielddef* key_field = map_field_key(field);
173  const upb_fielddef* value_field = map_field_value(field);
174  TypeInfo value_type_info = TypeInfo_get(value_field);
175  Map* self;
176 
177  if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
178  RTYPEDDATA_TYPE(val) != &Map_type) {
179  rb_raise(cTypeError, "Expected Map instance");
180  }
181 
182  self = ruby_to_Map(val);
183  if (self->key_type != upb_fielddef_type(key_field)) {
184  rb_raise(cTypeError, "Map key type does not match field's key type");
185  }
186  if (self->value_type_info.type != value_type_info.type) {
187  rb_raise(cTypeError, "Map value type does not match field's value type");
188  }
189  if (self->value_type_info.def.msgdef != value_type_info.def.msgdef) {
190  rb_raise(cTypeError, "Map value type has wrong message/enum class");
191  }
192 
193  Arena_fuse(self->arena, arena);
194  return self->map;
195 }
196 
198  TypeInfo val_type) {
199  bool first = true;
200  TypeInfo key_type_info = {key_type};
201  StringBuilder_Printf(b, "{");
202  if (map) {
203  size_t iter = UPB_MAP_BEGIN;
204  while (upb_mapiter_next(map, &iter)) {
207  if (first) {
208  first = false;
209  } else {
210  StringBuilder_Printf(b, ", ");
211  }
212  StringBuilder_PrintMsgval(b, key, key_type_info);
213  StringBuilder_Printf(b, "=>");
214  StringBuilder_PrintMsgval(b, val, val_type);
215  }
216  }
217  StringBuilder_Printf(b, "}");
218 }
219 
220 static int merge_into_self_callback(VALUE key, VALUE val, VALUE _self) {
221  Map* self = ruby_to_Map(_self);
222  upb_arena *arena = Arena_get(self->arena);
223  upb_msgval key_val = Convert_RubyToUpb(key, "", Map_keyinfo(self), arena);
224  upb_msgval val_val = Convert_RubyToUpb(val, "", self->value_type_info, arena);
225  upb_map_set(Map_GetMutable(_self), key_val, val_val, arena);
226  return ST_CONTINUE;
227 }
228 
229 // Used only internally -- shared by #merge and #initialize.
230 static VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) {
231  if (TYPE(hashmap) == T_HASH) {
232  rb_hash_foreach(hashmap, merge_into_self_callback, _self);
233  } else if (RB_TYPE_P(hashmap, T_DATA) && RTYPEDDATA_P(hashmap) &&
234  RTYPEDDATA_TYPE(hashmap) == &Map_type) {
235  Map* self = ruby_to_Map(_self);
236  Map* other = ruby_to_Map(hashmap);
237  upb_arena *arena = Arena_get(self->arena);
238  upb_msg *self_msg = Map_GetMutable(_self);
239  size_t iter = UPB_MAP_BEGIN;
240 
241  Arena_fuse(other->arena, arena);
242 
243  if (self->key_type != other->key_type ||
244  self->value_type_info.type != other->value_type_info.type ||
245  self->value_type_class != other->value_type_class) {
246  rb_raise(rb_eArgError, "Attempt to merge Map with mismatching types");
247  }
248 
249  while (upb_mapiter_next(other->map, &iter)) {
251  upb_msgval val = upb_mapiter_value(other->map, iter);
252  upb_map_set(self_msg, key, val, arena);
253  }
254  } else {
255  rb_raise(rb_eArgError, "Unknown type merging into Map");
256  }
257  return _self;
258 }
259 
260 /*
261  * call-seq:
262  * Map.new(key_type, value_type, value_typeclass = nil, init_hashmap = {})
263  * => new map
264  *
265  * Allocates a new Map container. This constructor may be called with 2, 3, or 4
266  * arguments. The first two arguments are always present and are symbols (taking
267  * on the same values as field-type symbols in message descriptors) that
268  * indicate the type of the map key and value fields.
269  *
270  * The supported key types are: :int32, :int64, :uint32, :uint64, :bool,
271  * :string, :bytes.
272  *
273  * The supported value types are: :int32, :int64, :uint32, :uint64, :bool,
274  * :string, :bytes, :enum, :message.
275  *
276  * The third argument, value_typeclass, must be present if value_type is :enum
277  * or :message. As in RepeatedField#new, this argument must be a message class
278  * (for :message) or enum module (for :enum).
279  *
280  * The last argument, if present, provides initial content for map. Note that
281  * this may be an ordinary Ruby hashmap or another Map instance with identical
282  * key and value types. Also note that this argument may be present whether or
283  * not value_typeclass is present (and it is unambiguously separate from
284  * value_typeclass because value_typeclass's presence is strictly determined by
285  * value_type). The contents of this initial hashmap or Map instance are
286  * shallow-copied into the new Map: the original map is unmodified, but
287  * references to underlying objects will be shared if the value type is a
288  * message type.
289  */
290 static VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
291  Map* self = ruby_to_Map(_self);
292  VALUE init_arg;
293 
294  // We take either two args (:key_type, :value_type), three args (:key_type,
295  // :value_type, "ValueMessageType"), or four args (the above plus an initial
296  // hashmap).
297  if (argc < 2 || argc > 4) {
298  rb_raise(rb_eArgError, "Map constructor expects 2, 3 or 4 arguments.");
299  }
300 
301  self->key_type = ruby_to_fieldtype(argv[0]);
302  self->value_type_info =
303  TypeInfo_FromClass(argc, argv, 1, &self->value_type_class, &init_arg);
304  self->arena = Arena_new();
305 
306  // Check that the key type is an allowed type.
307  switch (self->key_type) {
308  case UPB_TYPE_INT32:
309  case UPB_TYPE_INT64:
310  case UPB_TYPE_UINT32:
311  case UPB_TYPE_UINT64:
312  case UPB_TYPE_BOOL:
313  case UPB_TYPE_STRING:
314  case UPB_TYPE_BYTES:
315  // These are OK.
316  break;
317  default:
318  rb_raise(rb_eArgError, "Invalid key type for map.");
319  }
320 
321  self->map = upb_map_new(Arena_get(self->arena), self->key_type,
322  self->value_type_info.type);
323  ObjectCache_Add(self->map, _self);
324 
325  if (init_arg != Qnil) {
326  Map_merge_into_self(_self, init_arg);
327  }
328 
329  return Qnil;
330 }
331 
332 /*
333  * call-seq:
334  * Map.each(&block)
335  *
336  * Invokes &block on each |key, value| pair in the map, in unspecified order.
337  * Note that Map also includes Enumerable; map thus acts like a normal Ruby
338  * sequence.
339  */
340 static VALUE Map_each(VALUE _self) {
341  Map* self = ruby_to_Map(_self);
342  size_t iter = UPB_MAP_BEGIN;
343 
344  while (upb_mapiter_next(self->map, &iter)) {
346  upb_msgval val = upb_mapiter_value(self->map, iter);
347  VALUE key_val = Convert_UpbToRuby(key, Map_keyinfo(self), self->arena);
348  VALUE val_val = Convert_UpbToRuby(val, self->value_type_info, self->arena);
349  rb_yield_values(2, key_val, val_val);
350  }
351 
352  return Qnil;
353 }
354 
355 /*
356  * call-seq:
357  * Map.keys => [list_of_keys]
358  *
359  * Returns the list of keys contained in the map, in unspecified order.
360  */
361 static VALUE Map_keys(VALUE _self) {
362  Map* self = ruby_to_Map(_self);
363  size_t iter = UPB_MAP_BEGIN;
364  VALUE ret = rb_ary_new();
365 
366  while (upb_mapiter_next(self->map, &iter)) {
368  VALUE key_val = Convert_UpbToRuby(key, Map_keyinfo(self), self->arena);
369  rb_ary_push(ret, key_val);
370  }
371 
372  return ret;
373 }
374 
375 /*
376  * call-seq:
377  * Map.values => [list_of_values]
378  *
379  * Returns the list of values contained in the map, in unspecified order.
380  */
381 static VALUE Map_values(VALUE _self) {
382  Map* self = ruby_to_Map(_self);
383  size_t iter = UPB_MAP_BEGIN;
384  VALUE ret = rb_ary_new();
385 
386  while (upb_mapiter_next(self->map, &iter)) {
387  upb_msgval val = upb_mapiter_value(self->map, iter);
388  VALUE val_val = Convert_UpbToRuby(val, self->value_type_info, self->arena);
389  rb_ary_push(ret, val_val);
390  }
391 
392  return ret;
393 }
394 
395 /*
396  * call-seq:
397  * Map.[](key) => value
398  *
399  * Accesses the element at the given key. Throws an exception if the key type is
400  * incorrect. Returns nil when the key is not present in the map.
401  */
402 static VALUE Map_index(VALUE _self, VALUE key) {
403  Map* self = ruby_to_Map(_self);
404  upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
405  upb_msgval val;
406 
407  if (upb_map_get(self->map, key_upb, &val)) {
408  return Convert_UpbToRuby(val, self->value_type_info, self->arena);
409  } else {
410  return Qnil;
411  }
412 }
413 
414 /*
415  * call-seq:
416  * Map.[]=(key, value) => value
417  *
418  * Inserts or overwrites the value at the given key with the given new value.
419  * Throws an exception if the key type is incorrect. Returns the new value that
420  * was just inserted.
421  */
422 static VALUE Map_index_set(VALUE _self, VALUE key, VALUE val) {
423  Map* self = ruby_to_Map(_self);
424  upb_arena *arena = Arena_get(self->arena);
425  upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
426  upb_msgval val_upb = Convert_RubyToUpb(val, "", self->value_type_info, arena);
427 
428  upb_map_set(Map_GetMutable(_self), key_upb, val_upb, arena);
429 
430  return val;
431 }
432 
433 /*
434  * call-seq:
435  * Map.has_key?(key) => bool
436  *
437  * Returns true if the given key is present in the map. Throws an exception if
438  * the key has the wrong type.
439  */
440 static VALUE Map_has_key(VALUE _self, VALUE key) {
441  Map* self = ruby_to_Map(_self);
442  upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
443 
444  if (upb_map_get(self->map, key_upb, NULL)) {
445  return Qtrue;
446  } else {
447  return Qfalse;
448  }
449 }
450 
451 /*
452  * call-seq:
453  * Map.delete(key) => old_value
454  *
455  * Deletes the value at the given key, if any, returning either the old value or
456  * nil if none was present. Throws an exception if the key is of the wrong type.
457  */
458 static VALUE Map_delete(VALUE _self, VALUE key) {
459  Map* self = ruby_to_Map(_self);
460  upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
461  upb_msgval val_upb;
462  VALUE ret;
463 
464  rb_check_frozen(_self);
465 
466  // TODO(haberman): make upb_map_delete() also capable of returning the deleted
467  // value.
468  if (upb_map_get(self->map, key_upb, &val_upb)) {
469  ret = Convert_UpbToRuby(val_upb, self->value_type_info, self->arena);
470  } else {
471  ret = Qnil;
472  }
473 
474  upb_map_delete(Map_GetMutable(_self), key_upb);
475 
476  return ret;
477 }
478 
479 /*
480  * call-seq:
481  * Map.clear
482  *
483  * Removes all entries from the map.
484  */
485 static VALUE Map_clear(VALUE _self) {
487  return Qnil;
488 }
489 
490 /*
491  * call-seq:
492  * Map.length
493  *
494  * Returns the number of entries (key-value pairs) in the map.
495  */
496 static VALUE Map_length(VALUE _self) {
497  Map* self = ruby_to_Map(_self);
498  return ULL2NUM(upb_map_size(self->map));
499 }
500 
501 /*
502  * call-seq:
503  * Map.dup => new_map
504  *
505  * Duplicates this map with a shallow copy. References to all non-primitive
506  * element objects (e.g., submessages) are shared.
507  */
508 static VALUE Map_dup(VALUE _self) {
509  Map* self = ruby_to_Map(_self);
510  VALUE new_map_rb = Map_new_this_type(self);
511  Map* new_self = ruby_to_Map(new_map_rb);
512  size_t iter = UPB_MAP_BEGIN;
513  upb_arena *arena = Arena_get(new_self->arena);
514  upb_map *new_map = Map_GetMutable(new_map_rb);
515 
516  Arena_fuse(self->arena, arena);
517 
518  while (upb_mapiter_next(self->map, &iter)) {
520  upb_msgval val = upb_mapiter_value(self->map, iter);
521  upb_map_set(new_map, key, val, arena);
522  }
523 
524  return new_map_rb;
525 }
526 
527 /*
528  * call-seq:
529  * Map.==(other) => boolean
530  *
531  * Compares this map to another. Maps are equal if they have identical key sets,
532  * and for each key, the values in both maps compare equal. Elements are
533  * compared as per normal Ruby semantics, by calling their :== methods (or
534  * performing a more efficient comparison for primitive types).
535  *
536  * Maps with dissimilar key types or value types/typeclasses are never equal,
537  * even if value comparison (for example, between integers and floats) would
538  * have otherwise indicated that every element has equal value.
539  */
540 VALUE Map_eq(VALUE _self, VALUE _other) {
541  Map* self = ruby_to_Map(_self);
542  Map* other;
543 
544  // Allow comparisons to Ruby hashmaps by converting to a temporary Map
545  // instance. Slow, but workable.
546  if (TYPE(_other) == T_HASH) {
547  VALUE other_map = Map_new_this_type(self);
548  Map_merge_into_self(other_map, _other);
549  _other = other_map;
550  }
551 
552  other = ruby_to_Map(_other);
553 
554  if (self == other) {
555  return Qtrue;
556  }
557  if (self->key_type != other->key_type ||
558  self->value_type_info.type != other->value_type_info.type ||
559  self->value_type_class != other->value_type_class) {
560  return Qfalse;
561  }
562  if (upb_map_size(self->map) != upb_map_size(other->map)) {
563  return Qfalse;
564  }
565 
566  // For each member of self, check that an equal member exists at the same key
567  // in other.
568  size_t iter = UPB_MAP_BEGIN;
569  while (upb_mapiter_next(self->map, &iter)) {
571  upb_msgval val = upb_mapiter_value(self->map, iter);
572  upb_msgval other_val;
573  if (!upb_map_get(other->map, key, &other_val)) {
574  // Not present in other map.
575  return Qfalse;
576  }
577  if (!Msgval_IsEqual(val, other_val, self->value_type_info)) {
578  // Present but different value.
579  return Qfalse;
580  }
581  }
582 
583  return Qtrue;
584 }
585 
586 /*
587  * call-seq:
588  * Message.freeze => self
589  *
590  * Freezes the message object. We have to intercept this so we can pin the
591  * Ruby object into memory so we don't forget it's frozen.
592  */
593 static VALUE Map_freeze(VALUE _self) {
594  Map* self = ruby_to_Map(_self);
595  if (!RB_OBJ_FROZEN(_self)) {
596  Arena_Pin(self->arena, _self);
597  RB_OBJ_FREEZE(_self);
598  }
599  return _self;
600 }
601 
602 /*
603  * call-seq:
604  * Map.hash => hash_value
605  *
606  * Returns a hash value based on this map's contents.
607  */
608 VALUE Map_hash(VALUE _self) {
609  Map* self = ruby_to_Map(_self);
610  uint64_t hash = 0;
611 
612  size_t iter = UPB_MAP_BEGIN;
613  TypeInfo key_info = {self->key_type};
614  while (upb_mapiter_next(self->map, &iter)) {
616  upb_msgval val = upb_mapiter_value(self->map, iter);
617  hash = Msgval_GetHash(key, key_info, hash);
618  hash = Msgval_GetHash(val, self->value_type_info, hash);
619  }
620 
621  return LL2NUM(hash);
622 }
623 
624 /*
625  * call-seq:
626  * Map.to_h => {}
627  *
628  * Returns a Ruby Hash object containing all the values within the map
629  */
630 VALUE Map_to_h(VALUE _self) {
631  Map* self = ruby_to_Map(_self);
632  return Map_CreateHash(self->map, self->key_type, self->value_type_info);
633 }
634 
635 /*
636  * call-seq:
637  * Map.inspect => string
638  *
639  * Returns a string representing this map's elements. It will be formatted as
640  * "{key => value, key => value, ...}", with each key and value string
641  * representation computed by its own #inspect method.
642  */
643 VALUE Map_inspect(VALUE _self) {
644  Map* self = ruby_to_Map(_self);
645 
647  Map_Inspect(builder, self->map, self->key_type, self->value_type_info);
650  return ret;
651 }
652 
653 /*
654  * call-seq:
655  * Map.merge(other_map) => map
656  *
657  * Copies key/value pairs from other_map into a copy of this map. If a key is
658  * set in other_map and this map, the value from other_map overwrites the value
659  * in the new copy of this map. Returns the new copy of this map with merged
660  * contents.
661  */
662 static VALUE Map_merge(VALUE _self, VALUE hashmap) {
663  VALUE dupped = Map_dup(_self);
664  return Map_merge_into_self(dupped, hashmap);
665 }
666 
667 void Map_register(VALUE module) {
668  VALUE klass = rb_define_class_under(module, "Map", rb_cObject);
669  rb_define_alloc_func(klass, Map_alloc);
670  rb_gc_register_address(&cMap);
671  cMap = klass;
672 
673  rb_define_method(klass, "initialize", Map_init, -1);
674  rb_define_method(klass, "each", Map_each, 0);
675  rb_define_method(klass, "keys", Map_keys, 0);
676  rb_define_method(klass, "values", Map_values, 0);
677  rb_define_method(klass, "[]", Map_index, 1);
678  rb_define_method(klass, "[]=", Map_index_set, 2);
679  rb_define_method(klass, "has_key?", Map_has_key, 1);
680  rb_define_method(klass, "delete", Map_delete, 1);
681  rb_define_method(klass, "clear", Map_clear, 0);
682  rb_define_method(klass, "length", Map_length, 0);
683  rb_define_method(klass, "size", Map_length, 0);
684  rb_define_method(klass, "dup", Map_dup, 0);
685  // Also define #clone so that we don't inherit Object#clone.
686  rb_define_method(klass, "clone", Map_dup, 0);
687  rb_define_method(klass, "==", Map_eq, 1);
688  rb_define_method(klass, "freeze", Map_freeze, 0);
689  rb_define_method(klass, "hash", Map_hash, 0);
690  rb_define_method(klass, "to_h", Map_to_h, 0);
691  rb_define_method(klass, "inspect", Map_inspect, 0);
692  rb_define_method(klass, "merge", Map_merge, 1);
693  rb_include_module(klass, rb_mEnumerable);
694 }
obj
OPENSSL_EXPORT const ASN1_OBJECT * obj
Definition: x509.h:1671
Map_each
static VALUE Map_each(VALUE _self)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:340
UPB_TYPE_UINT64
@ UPB_TYPE_UINT64
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.h:487
upb_arena
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.c:2252
Convert_RubyToUpb
upb_msgval Convert_RubyToUpb(VALUE value, const char *name, TypeInfo type_info, upb_arena *arena)
Definition: protobuf/ruby/ext/google/protobuf_c/convert.c:127
StringBuilder_Free
void StringBuilder_Free(StringBuilder *b)
Definition: protobuf/ruby/ext/google/protobuf_c/protobuf.c:78
Convert_UpbToRuby
VALUE Convert_UpbToRuby(upb_msgval upb_val, TypeInfo type_info, VALUE arena)
Definition: protobuf/ruby/ext/google/protobuf_c/convert.c:230
Map_new_this_type
static VALUE Map_new_this_type(Map *from)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:111
Map
Definition: bloaty/third_party/protobuf/ruby/ext/google/protobuf_c/protobuf.h:451
StringBuilder
Definition: protobuf/ruby/ext/google/protobuf_c/protobuf.c:57
map_field_key
const upb_fielddef * map_field_key(const upb_fielddef *field)
Definition: php/ext/google/protobuf/storage.c:530
Map_merge_into_self
static VALUE Map_merge_into_self(VALUE _self, VALUE hashmap)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:230
upb_fieldtype_t
upb_fieldtype_t
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.h:472
Descriptor_DefToClass
VALUE Descriptor_DefToClass(const upb_msgdef *m)
Definition: protobuf/ruby/ext/google/protobuf_c/defs.c:1213
upb_map_clear
void upb_map_clear(upb_map *map)
Definition: php-upb.c:7308
Arena_Pin
void Arena_Pin(VALUE _arena, VALUE obj)
Definition: protobuf/ruby/ext/google/protobuf_c/protobuf.c:221
TypeInfo
Definition: protobuf/php/ext/google/protobuf/def.h:69
PBRUBY_ASSERT
#define PBRUBY_ASSERT(expr)
Definition: protobuf/ruby/ext/google/protobuf_c/protobuf.h:110
Map_register
void Map_register(VALUE module)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:667
UPB_TYPE_UINT32
@ UPB_TYPE_UINT32
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.h:478
TypeInfo_FromClass
TypeInfo TypeInfo_FromClass(int argc, VALUE *argv, int skip_arg, VALUE *type_class, VALUE *init_arg)
Definition: protobuf/ruby/ext/google/protobuf_c/defs.c:1238
Map_eq
VALUE Map_eq(VALUE _self, VALUE _other)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:540
Arena_get
upb_arena * Arena_get(VALUE _arena)
Definition: protobuf/ruby/ext/google/protobuf_c/protobuf.c:201
map
zval * map
Definition: php/ext/google/protobuf/encode_decode.c:480
ruby_to_fieldtype
upb_fieldtype_t ruby_to_fieldtype(VALUE type)
Definition: bloaty/third_party/protobuf/ruby/ext/google/protobuf_c/defs.c:840
Map_keys
static VALUE Map_keys(VALUE _self)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:361
upb_msg
void upb_msg
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.h:548
arena
grpc_core::ScopedArenaPtr arena
Definition: binder_transport_test.cc:237
Map::value_type_class
VALUE value_type_class
Definition: bloaty/third_party/protobuf/ruby/ext/google/protobuf_c/protobuf.h:454
Msgval_IsEqual
bool Msgval_IsEqual(upb_msgval val1, upb_msgval val2, TypeInfo type_info)
Definition: protobuf/ruby/ext/google/protobuf_c/convert.c:302
hash
uint64_t hash
Definition: ring_hash.cc:284
cMap
VALUE cMap
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:70
from
size_t from
Definition: abseil-cpp/absl/container/internal/layout_test.cc:1384
UPB_TYPE_BYTES
@ UPB_TYPE_BYTES
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.h:482
profile_analyzer.builder
builder
Definition: profile_analyzer.py:159
Map_alloc
static VALUE Map_alloc(VALUE klass)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:78
Map
struct Map Map
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:657
Map_deep_copy
VALUE Map_deep_copy(VALUE obj)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:152
Map_CreateHash
VALUE Map_CreateHash(const upb_map *map, upb_fieldtype_t key_type, TypeInfo val_info)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:133
TypeInfo_from_type
static TypeInfo TypeInfo_from_type(upb_fieldtype_t type)
Definition: defs.h:79
protobuf.h
upb_mapiter_key
upb_msgval upb_mapiter_key(const upb_map *map, size_t iter)
Definition: php-upb.c:7334
TypeInfo::msgdef
const upb_msgdef * msgdef
Definition: defs.h:56
uint64_t
unsigned __int64 uint64_t
Definition: stdint-msvc2008.h:90
merge_into_self_callback
static int merge_into_self_callback(VALUE key, VALUE val, VALUE _self)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:220
Map_freeze
static VALUE Map_freeze(VALUE _self)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:593
Map_hash
VALUE Map_hash(VALUE _self)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:608
Msgval_GetHash
uint64_t Msgval_GetHash(upb_msgval val, TypeInfo type_info, uint64_t seed)
Definition: protobuf/ruby/ext/google/protobuf_c/convert.c:327
Map_values
static VALUE Map_values(VALUE _self)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:381
absl::compare_internal::value_type
int8_t value_type
Definition: abseil-cpp/absl/types/compare.h:45
StringBuilder_PrintMsgval
void StringBuilder_PrintMsgval(StringBuilder *b, upb_msgval val, TypeInfo info)
Definition: protobuf/ruby/ext/google/protobuf_c/protobuf.c:123
upb_fielddef
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.c:2934
ObjectCache_Add
void ObjectCache_Add(const void *key, VALUE val)
Definition: protobuf/ruby/ext/google/protobuf_c/protobuf.c:383
map_field_value
const upb_fielddef * map_field_value(const upb_fielddef *field)
Definition: php/ext/google/protobuf/storage.c:535
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
Map_inspect
VALUE Map_inspect(VALUE _self)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:643
UPB_MAP_BEGIN
#define UPB_MAP_BEGIN
Definition: php-upb.h:574
cTypeError
VALUE cTypeError
Definition: bloaty/third_party/protobuf/ruby/ext/google/protobuf_c/protobuf.c:35
UPB_TYPE_INT32
@ UPB_TYPE_INT32
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.h:477
Map_mark
static void Map_mark(void *_self)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:58
StringBuilder_Printf
void StringBuilder_Printf(StringBuilder *b, const char *fmt,...)
Definition: protobuf/ruby/ext/google/protobuf_c/protobuf.c:83
upb_map_delete
bool upb_map_delete(upb_map *map, upb_msgval key)
Definition: php-upb.c:7317
Map_Inspect
void Map_Inspect(StringBuilder *b, const upb_map *map, upb_fieldtype_t key_type, TypeInfo val_type)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:197
TypeInfo_get
static TypeInfo TypeInfo_get(const upb_fielddef *f)
Definition: defs.h:61
Scalar_CreateHash
VALUE Scalar_CreateHash(upb_msgval msgval, TypeInfo type_info)
Definition: protobuf/ruby/ext/google/protobuf_c/message.c:837
ruby_to_Map
static Map * ruby_to_Map(VALUE _self)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:72
Map_has_key
static VALUE Map_has_key(VALUE _self, VALUE key)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:440
Map_to_h
VALUE Map_to_h(VALUE _self)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:630
upb_msgval
Definition: php-upb.h:4612
field
const FieldDescriptor * field
Definition: bloaty/third_party/protobuf/src/google/protobuf/compiler/parser_unittest.cc:2692
key
const char * key
Definition: hpack_parser_table.cc:164
StringBuilder_ToRubyString
VALUE StringBuilder_ToRubyString(StringBuilder *b)
Definition: protobuf/ruby/ext/google/protobuf_c/protobuf.c:107
Map_index_set
static VALUE Map_index_set(VALUE _self, VALUE key, VALUE val)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:422
UPB_TYPE_STRING
@ UPB_TYPE_STRING
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.h:481
Map_GetMutable
static upb_map * Map_GetMutable(VALUE _self)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:128
ALLOC
#define ALLOC(class_name)
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:1486
Map::key_type
upb_fieldtype_t key_type
Definition: bloaty/third_party/protobuf/ruby/ext/google/protobuf_c/protobuf.h:452
ret
UniquePtr< SSL_SESSION > ret
Definition: ssl_x509.cc:1029
Msgval_DeepCopy
upb_msgval Msgval_DeepCopy(upb_msgval msgval, TypeInfo type_info, upb_arena *arena)
Definition: protobuf/ruby/ext/google/protobuf_c/convert.c:276
upb_map_size
size_t upb_map_size(const upb_map *map)
Definition: php-upb.c:7300
StringBuilder_New
StringBuilder * StringBuilder_New()
Definition: protobuf/ruby/ext/google/protobuf_c/protobuf.c:69
descriptor_database_test_wrapper.module
module
Definition: descriptor_database_test_wrapper.py:30
first
StrT first
Definition: cxa_demangle.cpp:4884
Map_clear
static VALUE Map_clear(VALUE _self)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:485
upb_map_new
upb_map * upb_map_new(upb_arena *a, upb_fieldtype_t key_type, upb_fieldtype_t value_type)
Definition: php-upb.c:7294
Map::value_type_info
TypeInfo value_type_info
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:53
Map_keyinfo
static TypeInfo Map_keyinfo(Map *self)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:121
UPB_TYPE_MESSAGE
@ UPB_TYPE_MESSAGE
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.h:483
defs.h
TYPE
#define TYPE(u, l)
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.c:8202
Map_type
const rb_data_type_t Map_type
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:64
Map::arena
VALUE arena
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:55
iter
Definition: test_winkernel.cpp:47
TypeInfo::type
upb_fieldtype_t type
Definition: protobuf/php/ext/google/protobuf/def.h:70
Map_length
static VALUE Map_length(VALUE _self)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:496
Map_index
static VALUE Map_index(VALUE _self, VALUE key)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:402
Map::map
const upb_map * map
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:51
Arena_new
VALUE Arena_new()
Definition: protobuf/ruby/ext/google/protobuf_c/protobuf.c:217
Map_dup
static VALUE Map_dup(VALUE _self)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:508
key_type
upb_fieldtype_t key_type
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:1071
self
PHP_PROTO_OBJECT_FREE_END PHP_PROTO_OBJECT_DTOR_END intern self
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/map.c:543
Arena_fuse
void Arena_fuse(VALUE _arena, upb_arena *other)
Definition: protobuf/ruby/ext/google/protobuf_c/protobuf.c:207
upb_map_set
bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val, upb_arena *arena)
Definition: php-upb.c:7312
convert.h
Map_delete
static VALUE Map_delete(VALUE _self, VALUE key)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:458
klass
zend_class_entry * klass
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:810
Map_GetRubyWrapper
VALUE Map_GetRubyWrapper(upb_map *map, upb_fieldtype_t key_type, TypeInfo value_type, VALUE arena)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:87
ObjectCache_Get
VALUE ObjectCache_Get(const void *key)
Definition: protobuf/ruby/ext/google/protobuf_c/protobuf.c:397
TypeInfo::def
union TypeInfo::@436 def
UPB_TYPE_BOOL
@ UPB_TYPE_BOOL
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.h:474
UPB_TYPE_INT64
@ UPB_TYPE_INT64
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.h:486
upb_mapiter_next
bool upb_mapiter_next(const upb_map *map, size_t *iter)
Definition: php-upb.c:7321
upb_mapiter_value
upb_msgval upb_mapiter_value(const upb_map *map, size_t iter)
Definition: php-upb.c:7343
upb_msgdef
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.c:2962
upb_map_get
bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val)
Definition: php-upb.c:7304
upb_fielddef_type
upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f)
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.c:3304
Map_init
static VALUE Map_init(int argc, VALUE *argv, VALUE _self)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:290
message.h
Map_merge
static VALUE Map_merge(VALUE _self, VALUE hashmap)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:662
Map_GetUpbMap
const upb_map * Map_GetUpbMap(VALUE val, const upb_fielddef *field, upb_arena *arena)
Definition: protobuf/ruby/ext/google/protobuf_c/map.c:170
upb_map
Definition: php-upb.h:1487


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:18