map.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694
  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. #include "convert.h"
  31. #include "defs.h"
  32. #include "message.h"
  33. #include "protobuf.h"
  34. // -----------------------------------------------------------------------------
  35. // Basic map operations on top of upb_map.
  36. //
  37. // Note that we roll our own `Map` container here because, as for
  38. // `RepeatedField`, we want a strongly-typed container. This is so that any user
  39. // errors due to incorrect map key or value types are raised as close as
  40. // possible to the error site, rather than at some deferred point (e.g.,
  41. // serialization).
  42. // -----------------------------------------------------------------------------
  43. // -----------------------------------------------------------------------------
  44. // Map container type.
  45. // -----------------------------------------------------------------------------
  46. typedef struct {
  47. const upb_map *map; // Can convert to mutable when non-frozen.
  48. upb_fieldtype_t key_type;
  49. TypeInfo value_type_info;
  50. VALUE value_type_class;
  51. VALUE arena;
  52. } Map;
  53. static void Map_mark(void* _self) {
  54. Map* self = _self;
  55. rb_gc_mark(self->value_type_class);
  56. rb_gc_mark(self->arena);
  57. }
  58. const rb_data_type_t Map_type = {
  59. "Google::Protobuf::Map",
  60. { Map_mark, RUBY_DEFAULT_FREE, NULL },
  61. .flags = RUBY_TYPED_FREE_IMMEDIATELY,
  62. };
  63. VALUE cMap;
  64. static Map* ruby_to_Map(VALUE _self) {
  65. Map* self;
  66. TypedData_Get_Struct(_self, Map, &Map_type, self);
  67. return self;
  68. }
  69. static VALUE Map_alloc(VALUE klass) {
  70. Map* self = ALLOC(Map);
  71. self->map = NULL;
  72. self->value_type_class = Qnil;
  73. self->value_type_info.def.msgdef = NULL;
  74. self->arena = Qnil;
  75. return TypedData_Wrap_Struct(klass, &Map_type, self);
  76. }
  77. VALUE Map_GetRubyWrapper(upb_map* map, upb_fieldtype_t key_type,
  78. TypeInfo value_type, VALUE arena) {
  79. PBRUBY_ASSERT(map);
  80. VALUE val = ObjectCache_Get(map);
  81. if (val == Qnil) {
  82. val = Map_alloc(cMap);
  83. Map* self;
  84. ObjectCache_Add(map, val);
  85. TypedData_Get_Struct(val, Map, &Map_type, self);
  86. self->map = map;
  87. self->arena = arena;
  88. self->key_type = key_type;
  89. self->value_type_info = value_type;
  90. if (self->value_type_info.type == UPB_TYPE_MESSAGE) {
  91. const upb_msgdef *val_m = self->value_type_info.def.msgdef;
  92. self->value_type_class = Descriptor_DefToClass(val_m);
  93. }
  94. }
  95. return val;
  96. }
  97. static VALUE Map_new_this_type(Map *from) {
  98. VALUE arena_rb = Arena_new();
  99. upb_map* map = upb_map_new(Arena_get(arena_rb), from->key_type,
  100. from->value_type_info.type);
  101. VALUE ret =
  102. Map_GetRubyWrapper(map, from->key_type, from->value_type_info, arena_rb);
  103. PBRUBY_ASSERT(ruby_to_Map(ret)->value_type_class == from->value_type_class);
  104. return ret;
  105. }
  106. static TypeInfo Map_keyinfo(Map* self) {
  107. TypeInfo ret;
  108. ret.type = self->key_type;
  109. ret.def.msgdef = NULL;
  110. return ret;
  111. }
  112. static upb_map *Map_GetMutable(VALUE _self) {
  113. rb_check_frozen(_self);
  114. return (upb_map*)ruby_to_Map(_self)->map;
  115. }
  116. VALUE Map_CreateHash(const upb_map* map, upb_fieldtype_t key_type,
  117. TypeInfo val_info) {
  118. VALUE hash = rb_hash_new();
  119. size_t iter = UPB_MAP_BEGIN;
  120. TypeInfo key_info = TypeInfo_from_type(key_type);
  121. if (!map) return hash;
  122. while (upb_mapiter_next(map, &iter)) {
  123. upb_msgval key = upb_mapiter_key(map, iter);
  124. upb_msgval val = upb_mapiter_value(map, iter);
  125. VALUE key_val = Convert_UpbToRuby(key, key_info, Qnil);
  126. VALUE val_val = Scalar_CreateHash(val, val_info);
  127. rb_hash_aset(hash, key_val, val_val);
  128. }
  129. return hash;
  130. }
  131. VALUE Map_deep_copy(VALUE obj) {
  132. Map* self = ruby_to_Map(obj);
  133. VALUE new_arena_rb = Arena_new();
  134. upb_arena *arena = Arena_get(new_arena_rb);
  135. upb_map* new_map =
  136. upb_map_new(arena, self->key_type, self->value_type_info.type);
  137. size_t iter = UPB_MAP_BEGIN;
  138. while (upb_mapiter_next(self->map, &iter)) {
  139. upb_msgval key = upb_mapiter_key(self->map, iter);
  140. upb_msgval val = upb_mapiter_value(self->map, iter);
  141. upb_msgval val_copy = Msgval_DeepCopy(val, self->value_type_info, arena);
  142. upb_map_set(new_map, key, val_copy, arena);
  143. }
  144. return Map_GetRubyWrapper(new_map, self->key_type, self->value_type_info,
  145. new_arena_rb);
  146. }
  147. const upb_map* Map_GetUpbMap(VALUE val, const upb_fielddef* field,
  148. upb_arena* arena) {
  149. const upb_fielddef* key_field = map_field_key(field);
  150. const upb_fielddef* value_field = map_field_value(field);
  151. TypeInfo value_type_info = TypeInfo_get(value_field);
  152. Map* self;
  153. if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
  154. RTYPEDDATA_TYPE(val) != &Map_type) {
  155. rb_raise(cTypeError, "Expected Map instance");
  156. }
  157. self = ruby_to_Map(val);
  158. if (self->key_type != upb_fielddef_type(key_field)) {
  159. rb_raise(cTypeError, "Map key type does not match field's key type");
  160. }
  161. if (self->value_type_info.type != value_type_info.type) {
  162. rb_raise(cTypeError, "Map value type does not match field's value type");
  163. }
  164. if (self->value_type_info.def.msgdef != value_type_info.def.msgdef) {
  165. rb_raise(cTypeError, "Map value type has wrong message/enum class");
  166. }
  167. Arena_fuse(self->arena, arena);
  168. return self->map;
  169. }
  170. void Map_Inspect(StringBuilder* b, const upb_map* map, upb_fieldtype_t key_type,
  171. TypeInfo val_type) {
  172. bool first = true;
  173. TypeInfo key_type_info = {key_type};
  174. StringBuilder_Printf(b, "{");
  175. if (map) {
  176. size_t iter = UPB_MAP_BEGIN;
  177. while (upb_mapiter_next(map, &iter)) {
  178. upb_msgval key = upb_mapiter_key(map, iter);
  179. upb_msgval val = upb_mapiter_value(map, iter);
  180. if (first) {
  181. first = false;
  182. } else {
  183. StringBuilder_Printf(b, ", ");
  184. }
  185. StringBuilder_PrintMsgval(b, key, key_type_info);
  186. StringBuilder_Printf(b, "=>");
  187. StringBuilder_PrintMsgval(b, val, val_type);
  188. }
  189. }
  190. StringBuilder_Printf(b, "}");
  191. }
  192. static int merge_into_self_callback(VALUE key, VALUE val, VALUE _self) {
  193. Map* self = ruby_to_Map(_self);
  194. upb_arena *arena = Arena_get(self->arena);
  195. upb_msgval key_val = Convert_RubyToUpb(key, "", Map_keyinfo(self), arena);
  196. upb_msgval val_val = Convert_RubyToUpb(val, "", self->value_type_info, arena);
  197. upb_map_set(Map_GetMutable(_self), key_val, val_val, arena);
  198. return ST_CONTINUE;
  199. }
  200. // Used only internally -- shared by #merge and #initialize.
  201. static VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) {
  202. if (TYPE(hashmap) == T_HASH) {
  203. rb_hash_foreach(hashmap, merge_into_self_callback, _self);
  204. } else if (RB_TYPE_P(hashmap, T_DATA) && RTYPEDDATA_P(hashmap) &&
  205. RTYPEDDATA_TYPE(hashmap) == &Map_type) {
  206. Map* self = ruby_to_Map(_self);
  207. Map* other = ruby_to_Map(hashmap);
  208. upb_arena *arena = Arena_get(self->arena);
  209. upb_msg *self_msg = Map_GetMutable(_self);
  210. size_t iter = UPB_MAP_BEGIN;
  211. Arena_fuse(other->arena, arena);
  212. if (self->key_type != other->key_type ||
  213. self->value_type_info.type != other->value_type_info.type ||
  214. self->value_type_class != other->value_type_class) {
  215. rb_raise(rb_eArgError, "Attempt to merge Map with mismatching types");
  216. }
  217. while (upb_mapiter_next(other->map, &iter)) {
  218. upb_msgval key = upb_mapiter_key(other->map, iter);
  219. upb_msgval val = upb_mapiter_value(other->map, iter);
  220. upb_map_set(self_msg, key, val, arena);
  221. }
  222. } else {
  223. rb_raise(rb_eArgError, "Unknown type merging into Map");
  224. }
  225. return _self;
  226. }
  227. /*
  228. * call-seq:
  229. * Map.new(key_type, value_type, value_typeclass = nil, init_hashmap = {})
  230. * => new map
  231. *
  232. * Allocates a new Map container. This constructor may be called with 2, 3, or 4
  233. * arguments. The first two arguments are always present and are symbols (taking
  234. * on the same values as field-type symbols in message descriptors) that
  235. * indicate the type of the map key and value fields.
  236. *
  237. * The supported key types are: :int32, :int64, :uint32, :uint64, :bool,
  238. * :string, :bytes.
  239. *
  240. * The supported value types are: :int32, :int64, :uint32, :uint64, :bool,
  241. * :string, :bytes, :enum, :message.
  242. *
  243. * The third argument, value_typeclass, must be present if value_type is :enum
  244. * or :message. As in RepeatedField#new, this argument must be a message class
  245. * (for :message) or enum module (for :enum).
  246. *
  247. * The last argument, if present, provides initial content for map. Note that
  248. * this may be an ordinary Ruby hashmap or another Map instance with identical
  249. * key and value types. Also note that this argument may be present whether or
  250. * not value_typeclass is present (and it is unambiguously separate from
  251. * value_typeclass because value_typeclass's presence is strictly determined by
  252. * value_type). The contents of this initial hashmap or Map instance are
  253. * shallow-copied into the new Map: the original map is unmodified, but
  254. * references to underlying objects will be shared if the value type is a
  255. * message type.
  256. */
  257. static VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
  258. Map* self = ruby_to_Map(_self);
  259. VALUE init_arg;
  260. // We take either two args (:key_type, :value_type), three args (:key_type,
  261. // :value_type, "ValueMessageType"), or four args (the above plus an initial
  262. // hashmap).
  263. if (argc < 2 || argc > 4) {
  264. rb_raise(rb_eArgError, "Map constructor expects 2, 3 or 4 arguments.");
  265. }
  266. self->key_type = ruby_to_fieldtype(argv[0]);
  267. self->value_type_info =
  268. TypeInfo_FromClass(argc, argv, 1, &self->value_type_class, &init_arg);
  269. self->arena = Arena_new();
  270. // Check that the key type is an allowed type.
  271. switch (self->key_type) {
  272. case UPB_TYPE_INT32:
  273. case UPB_TYPE_INT64:
  274. case UPB_TYPE_UINT32:
  275. case UPB_TYPE_UINT64:
  276. case UPB_TYPE_BOOL:
  277. case UPB_TYPE_STRING:
  278. case UPB_TYPE_BYTES:
  279. // These are OK.
  280. break;
  281. default:
  282. rb_raise(rb_eArgError, "Invalid key type for map.");
  283. }
  284. self->map = upb_map_new(Arena_get(self->arena), self->key_type,
  285. self->value_type_info.type);
  286. ObjectCache_Add(self->map, _self);
  287. if (init_arg != Qnil) {
  288. Map_merge_into_self(_self, init_arg);
  289. }
  290. return Qnil;
  291. }
  292. /*
  293. * call-seq:
  294. * Map.each(&block)
  295. *
  296. * Invokes &block on each |key, value| pair in the map, in unspecified order.
  297. * Note that Map also includes Enumerable; map thus acts like a normal Ruby
  298. * sequence.
  299. */
  300. static VALUE Map_each(VALUE _self) {
  301. Map* self = ruby_to_Map(_self);
  302. size_t iter = UPB_MAP_BEGIN;
  303. while (upb_mapiter_next(self->map, &iter)) {
  304. upb_msgval key = upb_mapiter_key(self->map, iter);
  305. upb_msgval val = upb_mapiter_value(self->map, iter);
  306. VALUE key_val = Convert_UpbToRuby(key, Map_keyinfo(self), self->arena);
  307. VALUE val_val = Convert_UpbToRuby(val, self->value_type_info, self->arena);
  308. rb_yield_values(2, key_val, val_val);
  309. }
  310. return Qnil;
  311. }
  312. /*
  313. * call-seq:
  314. * Map.keys => [list_of_keys]
  315. *
  316. * Returns the list of keys contained in the map, in unspecified order.
  317. */
  318. static VALUE Map_keys(VALUE _self) {
  319. Map* self = ruby_to_Map(_self);
  320. size_t iter = UPB_MAP_BEGIN;
  321. VALUE ret = rb_ary_new();
  322. while (upb_mapiter_next(self->map, &iter)) {
  323. upb_msgval key = upb_mapiter_key(self->map, iter);
  324. VALUE key_val = Convert_UpbToRuby(key, Map_keyinfo(self), self->arena);
  325. rb_ary_push(ret, key_val);
  326. }
  327. return ret;
  328. }
  329. /*
  330. * call-seq:
  331. * Map.values => [list_of_values]
  332. *
  333. * Returns the list of values contained in the map, in unspecified order.
  334. */
  335. static VALUE Map_values(VALUE _self) {
  336. Map* self = ruby_to_Map(_self);
  337. size_t iter = UPB_MAP_BEGIN;
  338. VALUE ret = rb_ary_new();
  339. while (upb_mapiter_next(self->map, &iter)) {
  340. upb_msgval val = upb_mapiter_value(self->map, iter);
  341. VALUE val_val = Convert_UpbToRuby(val, self->value_type_info, self->arena);
  342. rb_ary_push(ret, val_val);
  343. }
  344. return ret;
  345. }
  346. /*
  347. * call-seq:
  348. * Map.[](key) => value
  349. *
  350. * Accesses the element at the given key. Throws an exception if the key type is
  351. * incorrect. Returns nil when the key is not present in the map.
  352. */
  353. static VALUE Map_index(VALUE _self, VALUE key) {
  354. Map* self = ruby_to_Map(_self);
  355. upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
  356. upb_msgval val;
  357. if (upb_map_get(self->map, key_upb, &val)) {
  358. return Convert_UpbToRuby(val, self->value_type_info, self->arena);
  359. } else {
  360. return Qnil;
  361. }
  362. }
  363. /*
  364. * call-seq:
  365. * Map.[]=(key, value) => value
  366. *
  367. * Inserts or overwrites the value at the given key with the given new value.
  368. * Throws an exception if the key type is incorrect. Returns the new value that
  369. * was just inserted.
  370. */
  371. static VALUE Map_index_set(VALUE _self, VALUE key, VALUE val) {
  372. Map* self = ruby_to_Map(_self);
  373. upb_arena *arena = Arena_get(self->arena);
  374. upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
  375. upb_msgval val_upb = Convert_RubyToUpb(val, "", self->value_type_info, arena);
  376. upb_map_set(Map_GetMutable(_self), key_upb, val_upb, arena);
  377. return val;
  378. }
  379. /*
  380. * call-seq:
  381. * Map.has_key?(key) => bool
  382. *
  383. * Returns true if the given key is present in the map. Throws an exception if
  384. * the key has the wrong type.
  385. */
  386. static VALUE Map_has_key(VALUE _self, VALUE key) {
  387. Map* self = ruby_to_Map(_self);
  388. upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
  389. if (upb_map_get(self->map, key_upb, NULL)) {
  390. return Qtrue;
  391. } else {
  392. return Qfalse;
  393. }
  394. }
  395. /*
  396. * call-seq:
  397. * Map.delete(key) => old_value
  398. *
  399. * Deletes the value at the given key, if any, returning either the old value or
  400. * nil if none was present. Throws an exception if the key is of the wrong type.
  401. */
  402. static VALUE Map_delete(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_upb;
  406. VALUE ret;
  407. rb_check_frozen(_self);
  408. // TODO(haberman): make upb_map_delete() also capable of returning the deleted
  409. // value.
  410. if (upb_map_get(self->map, key_upb, &val_upb)) {
  411. ret = Convert_UpbToRuby(val_upb, self->value_type_info, self->arena);
  412. } else {
  413. ret = Qnil;
  414. }
  415. upb_map_delete(Map_GetMutable(_self), key_upb);
  416. return ret;
  417. }
  418. /*
  419. * call-seq:
  420. * Map.clear
  421. *
  422. * Removes all entries from the map.
  423. */
  424. static VALUE Map_clear(VALUE _self) {
  425. upb_map_clear(Map_GetMutable(_self));
  426. return Qnil;
  427. }
  428. /*
  429. * call-seq:
  430. * Map.length
  431. *
  432. * Returns the number of entries (key-value pairs) in the map.
  433. */
  434. static VALUE Map_length(VALUE _self) {
  435. Map* self = ruby_to_Map(_self);
  436. return ULL2NUM(upb_map_size(self->map));
  437. }
  438. /*
  439. * call-seq:
  440. * Map.dup => new_map
  441. *
  442. * Duplicates this map with a shallow copy. References to all non-primitive
  443. * element objects (e.g., submessages) are shared.
  444. */
  445. static VALUE Map_dup(VALUE _self) {
  446. Map* self = ruby_to_Map(_self);
  447. VALUE new_map_rb = Map_new_this_type(self);
  448. Map* new_self = ruby_to_Map(new_map_rb);
  449. size_t iter = UPB_MAP_BEGIN;
  450. upb_arena *arena = Arena_get(new_self->arena);
  451. upb_map *new_map = Map_GetMutable(new_map_rb);
  452. Arena_fuse(self->arena, arena);
  453. while (upb_mapiter_next(self->map, &iter)) {
  454. upb_msgval key = upb_mapiter_key(self->map, iter);
  455. upb_msgval val = upb_mapiter_value(self->map, iter);
  456. upb_map_set(new_map, key, val, arena);
  457. }
  458. return new_map_rb;
  459. }
  460. /*
  461. * call-seq:
  462. * Map.==(other) => boolean
  463. *
  464. * Compares this map to another. Maps are equal if they have identical key sets,
  465. * and for each key, the values in both maps compare equal. Elements are
  466. * compared as per normal Ruby semantics, by calling their :== methods (or
  467. * performing a more efficient comparison for primitive types).
  468. *
  469. * Maps with dissimilar key types or value types/typeclasses are never equal,
  470. * even if value comparison (for example, between integers and floats) would
  471. * have otherwise indicated that every element has equal value.
  472. */
  473. VALUE Map_eq(VALUE _self, VALUE _other) {
  474. Map* self = ruby_to_Map(_self);
  475. Map* other;
  476. // Allow comparisons to Ruby hashmaps by converting to a temporary Map
  477. // instance. Slow, but workable.
  478. if (TYPE(_other) == T_HASH) {
  479. VALUE other_map = Map_new_this_type(self);
  480. Map_merge_into_self(other_map, _other);
  481. _other = other_map;
  482. }
  483. other = ruby_to_Map(_other);
  484. if (self == other) {
  485. return Qtrue;
  486. }
  487. if (self->key_type != other->key_type ||
  488. self->value_type_info.type != other->value_type_info.type ||
  489. self->value_type_class != other->value_type_class) {
  490. return Qfalse;
  491. }
  492. if (upb_map_size(self->map) != upb_map_size(other->map)) {
  493. return Qfalse;
  494. }
  495. // For each member of self, check that an equal member exists at the same key
  496. // in other.
  497. size_t iter = UPB_MAP_BEGIN;
  498. while (upb_mapiter_next(self->map, &iter)) {
  499. upb_msgval key = upb_mapiter_key(self->map, iter);
  500. upb_msgval val = upb_mapiter_value(self->map, iter);
  501. upb_msgval other_val;
  502. if (!upb_map_get(other->map, key, &other_val)) {
  503. // Not present in other map.
  504. return Qfalse;
  505. }
  506. if (!Msgval_IsEqual(val, other_val, self->value_type_info)) {
  507. // Present but different value.
  508. return Qfalse;
  509. }
  510. }
  511. return Qtrue;
  512. }
  513. /*
  514. * call-seq:
  515. * Message.freeze => self
  516. *
  517. * Freezes the message object. We have to intercept this so we can pin the
  518. * Ruby object into memory so we don't forget it's frozen.
  519. */
  520. static VALUE Map_freeze(VALUE _self) {
  521. Map* self = ruby_to_Map(_self);
  522. if (!RB_OBJ_FROZEN(_self)) {
  523. Arena_Pin(self->arena, _self);
  524. RB_OBJ_FREEZE(_self);
  525. }
  526. return _self;
  527. }
  528. /*
  529. * call-seq:
  530. * Map.hash => hash_value
  531. *
  532. * Returns a hash value based on this map's contents.
  533. */
  534. VALUE Map_hash(VALUE _self) {
  535. Map* self = ruby_to_Map(_self);
  536. uint64_t hash = 0;
  537. size_t iter = UPB_MAP_BEGIN;
  538. TypeInfo key_info = {self->key_type};
  539. while (upb_mapiter_next(self->map, &iter)) {
  540. upb_msgval key = upb_mapiter_key(self->map, iter);
  541. upb_msgval val = upb_mapiter_value(self->map, iter);
  542. hash = Msgval_GetHash(key, key_info, hash);
  543. hash = Msgval_GetHash(val, self->value_type_info, hash);
  544. }
  545. return LL2NUM(hash);
  546. }
  547. /*
  548. * call-seq:
  549. * Map.to_h => {}
  550. *
  551. * Returns a Ruby Hash object containing all the values within the map
  552. */
  553. VALUE Map_to_h(VALUE _self) {
  554. Map* self = ruby_to_Map(_self);
  555. return Map_CreateHash(self->map, self->key_type, self->value_type_info);
  556. }
  557. /*
  558. * call-seq:
  559. * Map.inspect => string
  560. *
  561. * Returns a string representing this map's elements. It will be formatted as
  562. * "{key => value, key => value, ...}", with each key and value string
  563. * representation computed by its own #inspect method.
  564. */
  565. VALUE Map_inspect(VALUE _self) {
  566. Map* self = ruby_to_Map(_self);
  567. StringBuilder* builder = StringBuilder_New();
  568. Map_Inspect(builder, self->map, self->key_type, self->value_type_info);
  569. VALUE ret = StringBuilder_ToRubyString(builder);
  570. StringBuilder_Free(builder);
  571. return ret;
  572. }
  573. /*
  574. * call-seq:
  575. * Map.merge(other_map) => map
  576. *
  577. * Copies key/value pairs from other_map into a copy of this map. If a key is
  578. * set in other_map and this map, the value from other_map overwrites the value
  579. * in the new copy of this map. Returns the new copy of this map with merged
  580. * contents.
  581. */
  582. static VALUE Map_merge(VALUE _self, VALUE hashmap) {
  583. VALUE dupped = Map_dup(_self);
  584. return Map_merge_into_self(dupped, hashmap);
  585. }
  586. void Map_register(VALUE module) {
  587. VALUE klass = rb_define_class_under(module, "Map", rb_cObject);
  588. rb_define_alloc_func(klass, Map_alloc);
  589. rb_gc_register_address(&cMap);
  590. cMap = klass;
  591. rb_define_method(klass, "initialize", Map_init, -1);
  592. rb_define_method(klass, "each", Map_each, 0);
  593. rb_define_method(klass, "keys", Map_keys, 0);
  594. rb_define_method(klass, "values", Map_values, 0);
  595. rb_define_method(klass, "[]", Map_index, 1);
  596. rb_define_method(klass, "[]=", Map_index_set, 2);
  597. rb_define_method(klass, "has_key?", Map_has_key, 1);
  598. rb_define_method(klass, "delete", Map_delete, 1);
  599. rb_define_method(klass, "clear", Map_clear, 0);
  600. rb_define_method(klass, "length", Map_length, 0);
  601. rb_define_method(klass, "size", Map_length, 0);
  602. rb_define_method(klass, "dup", Map_dup, 0);
  603. // Also define #clone so that we don't inherit Object#clone.
  604. rb_define_method(klass, "clone", Map_dup, 0);
  605. rb_define_method(klass, "==", Map_eq, 1);
  606. rb_define_method(klass, "freeze", Map_freeze, 0);
  607. rb_define_method(klass, "hash", Map_hash, 0);
  608. rb_define_method(klass, "to_h", Map_to_h, 0);
  609. rb_define_method(klass, "inspect", Map_inspect, 0);
  610. rb_define_method(klass, "merge", Map_merge, 1);
  611. rb_include_module(klass, rb_mEnumerable);
  612. }