google-protobuf 3.14.0 → 3.15.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of google-protobuf might be problematic. Click here for more details.

@@ -0,0 +1,145 @@
1
+ /* Copyright 2020 王一 Wang Yi <godspeed_china@yeah.net>
2
+ This is free and unencumbered software released into the public domain. http://unlicense.org/
3
+ See github.com/wangyi-fudan/wyhash/ LICENSE
4
+ */
5
+ #ifndef wyhash_final_version
6
+ #define wyhash_final_version
7
+ //defines that change behavior
8
+ #ifndef WYHASH_CONDOM
9
+ #define WYHASH_CONDOM 1 //0: read 8 bytes before and after boundaries, dangerous but fastest. 1: normal valid behavior 2: extra protection against entropy loss (probability=2^-63), aka. "blind multiplication"
10
+ #endif
11
+ #define WYHASH_32BIT_MUM 0 //faster on 32 bit system
12
+ //includes
13
+ #include <stdint.h>
14
+ #include <string.h>
15
+ #if defined(_MSC_VER) && defined(_M_X64)
16
+ #include <intrin.h>
17
+ #pragma intrinsic(_umul128)
18
+ #endif
19
+ #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
20
+ #define _likely_(x) __builtin_expect(x,1)
21
+ #define _unlikely_(x) __builtin_expect(x,0)
22
+ #else
23
+ #define _likely_(x) (x)
24
+ #define _unlikely_(x) (x)
25
+ #endif
26
+ //mum function
27
+ static inline uint64_t _wyrot(uint64_t x) { return (x>>32)|(x<<32); }
28
+ static inline void _wymum(uint64_t *A, uint64_t *B){
29
+ #if(WYHASH_32BIT_MUM)
30
+ uint64_t hh=(*A>>32)*(*B>>32), hl=(*A>>32)*(unsigned)*B, lh=(unsigned)*A*(*B>>32), ll=(uint64_t)(unsigned)*A*(unsigned)*B;
31
+ #if(WYHASH_CONDOM>1)
32
+ *A^=_wyrot(hl)^hh; *B^=_wyrot(lh)^ll;
33
+ #else
34
+ *A=_wyrot(hl)^hh; *B=_wyrot(lh)^ll;
35
+ #endif
36
+ #elif defined(__SIZEOF_INT128__)
37
+ __uint128_t r=*A; r*=*B;
38
+ #if(WYHASH_CONDOM>1)
39
+ *A^=(uint64_t)r; *B^=(uint64_t)(r>>64);
40
+ #else
41
+ *A=(uint64_t)r; *B=(uint64_t)(r>>64);
42
+ #endif
43
+ #elif defined(_MSC_VER) && defined(_M_X64)
44
+ #if(WYHASH_CONDOM>1)
45
+ uint64_t a, b;
46
+ a=_umul128(*A,*B,&b);
47
+ *A^=a; *B^=b;
48
+ #else
49
+ *A=_umul128(*A,*B,B);
50
+ #endif
51
+ #else
52
+ uint64_t ha=*A>>32, hb=*B>>32, la=(uint32_t)*A, lb=(uint32_t)*B, hi, lo;
53
+ uint64_t rh=ha*hb, rm0=ha*lb, rm1=hb*la, rl=la*lb, t=rl+(rm0<<32), c=t<rl;
54
+ lo=t+(rm1<<32); c+=lo<t; hi=rh+(rm0>>32)+(rm1>>32)+c;
55
+ #if(WYHASH_CONDOM>1)
56
+ *A^=lo; *B^=hi;
57
+ #else
58
+ *A=lo; *B=hi;
59
+ #endif
60
+ #endif
61
+ }
62
+ static inline uint64_t _wymix(uint64_t A, uint64_t B){ _wymum(&A,&B); return A^B; }
63
+ //read functions
64
+ #ifndef WYHASH_LITTLE_ENDIAN
65
+ #if defined(_WIN32) || defined(__LITTLE_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
66
+ #define WYHASH_LITTLE_ENDIAN 1
67
+ #elif defined(__BIG_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
68
+ #define WYHASH_LITTLE_ENDIAN 0
69
+ #endif
70
+ #endif
71
+ #if (WYHASH_LITTLE_ENDIAN)
72
+ static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return v;}
73
+ static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return v;}
74
+ #elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
75
+ static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return __builtin_bswap64(v);}
76
+ static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return __builtin_bswap32(v);}
77
+ #elif defined(_MSC_VER)
78
+ static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return _byteswap_uint64(v);}
79
+ static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return _byteswap_ulong(v);}
80
+ #endif
81
+ static inline uint64_t _wyr3(const uint8_t *p, unsigned k) { return (((uint64_t)p[0])<<16)|(((uint64_t)p[k>>1])<<8)|p[k-1];}
82
+ //wyhash function
83
+ static inline uint64_t _wyfinish16(const uint8_t *p, uint64_t len, uint64_t seed, const uint64_t *secret, uint64_t i){
84
+ #if(WYHASH_CONDOM>0)
85
+ uint64_t a, b;
86
+ if(_likely_(i<=8)){
87
+ if(_likely_(i>=4)){ a=_wyr4(p); b=_wyr4(p+i-4); }
88
+ else if (_likely_(i)){ a=_wyr3(p,i); b=0; }
89
+ else a=b=0;
90
+ }
91
+ else{ a=_wyr8(p); b=_wyr8(p+i-8); }
92
+ return _wymix(secret[1]^len,_wymix(a^secret[1], b^seed));
93
+ #else
94
+ #define oneshot_shift ((i<8)*((8-i)<<3))
95
+ return _wymix(secret[1]^len,_wymix((_wyr8(p)<<oneshot_shift)^secret[1],(_wyr8(p+i-8)>>oneshot_shift)^seed));
96
+ #endif
97
+ }
98
+
99
+ static inline uint64_t _wyfinish(const uint8_t *p, uint64_t len, uint64_t seed, const uint64_t *secret, uint64_t i){
100
+ if(_likely_(i<=16)) return _wyfinish16(p,len,seed,secret,i);
101
+ return _wyfinish(p+16,len,_wymix(_wyr8(p)^secret[1],_wyr8(p+8)^seed),secret,i-16);
102
+ }
103
+
104
+ static inline uint64_t wyhash(const void *key, uint64_t len, uint64_t seed, const uint64_t *secret){
105
+ const uint8_t *p=(const uint8_t *)key;
106
+ uint64_t i=len; seed^=*secret;
107
+ if(_unlikely_(i>64)){
108
+ uint64_t see1=seed;
109
+ do{
110
+ seed=_wymix(_wyr8(p)^secret[1],_wyr8(p+8)^seed)^_wymix(_wyr8(p+16)^secret[2],_wyr8(p+24)^seed);
111
+ see1=_wymix(_wyr8(p+32)^secret[3],_wyr8(p+40)^see1)^_wymix(_wyr8(p+48)^secret[4],_wyr8(p+56)^see1);
112
+ p+=64; i-=64;
113
+ }while(i>64);
114
+ seed^=see1;
115
+ }
116
+ return _wyfinish(p,len,seed,secret,i);
117
+ }
118
+ //utility functions
119
+ static const uint64_t _wyp[5] = {0xa0761d6478bd642full, 0xe7037ed1a0b428dbull, 0x8ebc6af09c88c6e3ull, 0x589965cc75374cc3ull, 0x1d8e4e27c47d124full};
120
+ static inline uint64_t wyhash64(uint64_t A, uint64_t B){ A^=_wyp[0]; B^=_wyp[1]; _wymum(&A,&B); return _wymix(A^_wyp[0],B^_wyp[1]);}
121
+ static inline uint64_t wyrand(uint64_t *seed){ *seed+=_wyp[0]; return _wymix(*seed,*seed^_wyp[1]);}
122
+ static inline double wy2u01(uint64_t r){ const double _wynorm=1.0/(1ull<<52); return (r>>12)*_wynorm;}
123
+ static inline double wy2gau(uint64_t r){ const double _wynorm=1.0/(1ull<<20); return ((r&0x1fffff)+((r>>21)&0x1fffff)+((r>>42)&0x1fffff))*_wynorm-3.0;}
124
+ static inline uint64_t wy2u0k(uint64_t r, uint64_t k){ _wymum(&r,&k); return k; }
125
+
126
+ static inline void make_secret(uint64_t seed, uint64_t *secret){
127
+ uint8_t c[] = {15, 23, 27, 29, 30, 39, 43, 45, 46, 51, 53, 54, 57, 58, 60, 71, 75, 77, 78, 83, 85, 86, 89, 90, 92, 99, 101, 102, 105, 106, 108, 113, 114, 116, 120, 135, 139, 141, 142, 147, 149, 150, 153, 154, 156, 163, 165, 166, 169, 170, 172, 177, 178, 180, 184, 195, 197, 198, 201, 202, 204, 209, 210, 212, 216, 225, 226, 228, 232, 240 };
128
+ for(size_t i=0;i<5;i++){
129
+ uint8_t ok;
130
+ do{
131
+ ok=1; secret[i]=0;
132
+ for(size_t j=0;j<64;j+=8) secret[i]|=((uint64_t)c[wyrand(&seed)%sizeof(c)])<<j;
133
+ if(secret[i]%2==0){ ok=0; continue; }
134
+ for(size_t j=0;j<i;j++)
135
+ #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
136
+ if(__builtin_popcountll(secret[j]^secret[i])!=32){ ok=0; break; }
137
+ #elif defined(_MSC_VER) && defined(_M_X64)
138
+ if(_mm_popcnt_u64(secret[j]^secret[i])!=32){ ok=0; break; }
139
+ #endif
140
+ if(!ok)continue;
141
+ for(uint64_t j=3;j<0x100000000ull;j+=2) if(secret[i]%j==0){ ok=0; break; }
142
+ }while(!ok);
143
+ }
144
+ }
145
+ #endif
data/tests/basic.rb CHANGED
@@ -216,7 +216,7 @@ module BasicTest
216
216
  m.map_string_int32 = {}
217
217
  end
218
218
 
219
- assert_raise TypeError do
219
+ assert_raise Google::Protobuf::TypeError do
220
220
  m = MapMessage.new(:map_string_int32 => { 1 => "I am not a number" })
221
221
  end
222
222
  end
@@ -241,8 +241,12 @@ module BasicTest
241
241
  :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
242
242
  "b" => TestMessage2.new(:foo => 2)},
243
243
  :map_string_enum => {"a" => :A, "b" => :B})
244
- expected = "<BasicTest::MapMessage: map_string_int32: {\"b\"=>2, \"a\"=>1}, map_string_msg: {\"b\"=><BasicTest::TestMessage2: foo: 2>, \"a\"=><BasicTest::TestMessage2: foo: 1>}, map_string_enum: {\"b\"=>:B, \"a\"=>:A}>"
245
- assert_equal expected, m.inspect
244
+
245
+ # JRuby doesn't keep consistent ordering so check for either version
246
+ expected_a = "<BasicTest::MapMessage: map_string_int32: {\"b\"=>2, \"a\"=>1}, map_string_msg: {\"b\"=><BasicTest::TestMessage2: foo: 2>, \"a\"=><BasicTest::TestMessage2: foo: 1>}, map_string_enum: {\"b\"=>:B, \"a\"=>:A}>"
247
+ expected_b = "<BasicTest::MapMessage: map_string_int32: {\"a\"=>1, \"b\"=>2}, map_string_msg: {\"a\"=><BasicTest::TestMessage2: foo: 1>, \"b\"=><BasicTest::TestMessage2: foo: 2>}, map_string_enum: {\"a\"=>:A, \"b\"=>:B}>"
248
+ inspect_result = m.inspect
249
+ assert expected_a == inspect_result || expected_b == inspect_result, "Incorrect inspect result: #{inspect_result}"
246
250
  end
247
251
 
248
252
  def test_map_corruption
@@ -443,6 +447,7 @@ module BasicTest
443
447
  :optional_int32=>0,
444
448
  :optional_int64=>0,
445
449
  :optional_msg=>nil,
450
+ :optional_msg2=>nil,
446
451
  :optional_string=>"foo",
447
452
  :optional_uint32=>0,
448
453
  :optional_uint64=>0,
@@ -480,9 +485,9 @@ module BasicTest
480
485
  m = MapMessage.new(:map_string_int32 => {"a" => 1})
481
486
  expected = {mapStringInt32: {a: 1}, mapStringMsg: {}, mapStringEnum: {}}
482
487
  expected_preserve = {map_string_int32: {a: 1}, map_string_msg: {}, map_string_enum: {}}
483
- assert_equal JSON.parse(MapMessage.encode_json(m), :symbolize_names => true), expected
488
+ assert_equal JSON.parse(MapMessage.encode_json(m, :emit_defaults=>true), :symbolize_names => true), expected
484
489
 
485
- json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true)
490
+ json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true, :emit_defaults=>true)
486
491
  assert_equal JSON.parse(json, :symbolize_names => true), expected_preserve
487
492
 
488
493
  m2 = MapMessage.decode_json(MapMessage.encode_json(m))
@@ -492,7 +497,7 @@ module BasicTest
492
497
  def test_json_maps_emit_defaults_submsg
493
498
  # TODO: Fix JSON in JRuby version.
494
499
  return if RUBY_PLATFORM == "java"
495
- m = MapMessage.new(:map_string_msg => {"a" => TestMessage2.new})
500
+ m = MapMessage.new(:map_string_msg => {"a" => TestMessage2.new(foo: 0)})
496
501
  expected = {mapStringInt32: {}, mapStringMsg: {a: {foo: 0}}, mapStringEnum: {}}
497
502
 
498
503
  actual = MapMessage.encode_json(m, :emit_defaults => true)
@@ -500,6 +505,30 @@ module BasicTest
500
505
  assert_equal JSON.parse(actual, :symbolize_names => true), expected
501
506
  end
502
507
 
508
+ def test_json_emit_defaults_submsg
509
+ # TODO: Fix JSON in JRuby version.
510
+ return if RUBY_PLATFORM == "java"
511
+ m = TestSingularFields.new(singular_msg: proto_module::TestMessage2.new)
512
+
513
+ expected = {
514
+ singularInt32: 0,
515
+ singularInt64: "0",
516
+ singularUint32: 0,
517
+ singularUint64: "0",
518
+ singularBool: false,
519
+ singularFloat: 0,
520
+ singularDouble: 0,
521
+ singularString: "",
522
+ singularBytes: "",
523
+ singularMsg: {},
524
+ singularEnum: "Default",
525
+ }
526
+
527
+ actual = proto_module::TestMessage.encode_json(m, :emit_defaults => true)
528
+
529
+ assert_equal expected, JSON.parse(actual, :symbolize_names => true)
530
+ end
531
+
503
532
  def test_respond_to
504
533
  # This test fails with JRuby 1.7.23, likely because of an old JRuby bug.
505
534
  return if RUBY_PLATFORM == "java"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: google-protobuf
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.14.0
4
+ version: 3.15.0.rc.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Protobuf Authors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-11-13 00:00:00.000000000 Z
11
+ date: 2021-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler-dock
@@ -16,7 +16,7 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 1.0.1
19
+ version: 1.1.0
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
22
  version: '2.0'
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: 1.0.1
29
+ version: 1.1.0
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: '2.0'
@@ -85,17 +85,22 @@ extensions:
85
85
  - ext/google/protobuf_c/extconf.rb
86
86
  extra_rdoc_files: []
87
87
  files:
88
+ - ext/google/protobuf_c/convert.c
89
+ - ext/google/protobuf_c/convert.h
88
90
  - ext/google/protobuf_c/defs.c
89
- - ext/google/protobuf_c/encode_decode.c
91
+ - ext/google/protobuf_c/defs.h
90
92
  - ext/google/protobuf_c/extconf.rb
91
93
  - ext/google/protobuf_c/map.c
94
+ - ext/google/protobuf_c/map.h
92
95
  - ext/google/protobuf_c/message.c
96
+ - ext/google/protobuf_c/message.h
93
97
  - ext/google/protobuf_c/protobuf.c
94
98
  - ext/google/protobuf_c/protobuf.h
95
99
  - ext/google/protobuf_c/repeated_field.c
96
- - ext/google/protobuf_c/storage.c
97
- - ext/google/protobuf_c/upb.c
98
- - ext/google/protobuf_c/upb.h
100
+ - ext/google/protobuf_c/repeated_field.h
101
+ - ext/google/protobuf_c/ruby-upb.c
102
+ - ext/google/protobuf_c/ruby-upb.h
103
+ - ext/google/protobuf_c/third_party/wyhash/wyhash.h
99
104
  - ext/google/protobuf_c/wrap_memcpy.c
100
105
  - lib/google/protobuf.rb
101
106
  - lib/google/protobuf/any_pb.rb
@@ -118,7 +123,7 @@ homepage: https://developers.google.com/protocol-buffers
118
123
  licenses:
119
124
  - BSD-3-Clause
120
125
  metadata:
121
- source_code_uri: https://github.com/protocolbuffers/protobuf/tree/v3.14.0/ruby
126
+ source_code_uri: https://github.com/protocolbuffers/protobuf/tree/v3.15.0-rc1/ruby
122
127
  post_install_message:
123
128
  rdoc_options: []
124
129
  require_paths:
@@ -130,11 +135,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
130
135
  version: '2.3'
131
136
  required_rubygems_version: !ruby/object:Gem::Requirement
132
137
  requirements:
133
- - - ">="
138
+ - - ">"
134
139
  - !ruby/object:Gem::Version
135
- version: '0'
140
+ version: 1.3.1
136
141
  requirements: []
137
- rubygems_version: 3.1.4
142
+ rubygems_version: 3.2.8
138
143
  signing_key:
139
144
  specification_version: 4
140
145
  summary: Protocol Buffers
@@ -1,1795 +0,0 @@
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 "protobuf.h"
32
-
33
- VALUE initialize_rb_class_with_no_args(VALUE klass) {
34
- return rb_funcall(klass, rb_intern("new"), 0);
35
- }
36
-
37
- // This function is equivalent to rb_str_cat(), but unlike the real
38
- // rb_str_cat(), it doesn't leak memory in some versions of Ruby.
39
- // For more information, see:
40
- // https://bugs.ruby-lang.org/issues/11328
41
- VALUE noleak_rb_str_cat(VALUE rb_str, const char *str, long len) {
42
- char *p;
43
- size_t oldlen = RSTRING_LEN(rb_str);
44
- rb_str_modify_expand(rb_str, len);
45
- p = RSTRING_PTR(rb_str);
46
- memcpy(p + oldlen, str, len);
47
- rb_str_set_len(rb_str, oldlen + len);
48
- return rb_str;
49
- }
50
-
51
- bool is_wrapper(const upb_msgdef* m) {
52
- switch (upb_msgdef_wellknowntype(m)) {
53
- case UPB_WELLKNOWN_DOUBLEVALUE:
54
- case UPB_WELLKNOWN_FLOATVALUE:
55
- case UPB_WELLKNOWN_INT64VALUE:
56
- case UPB_WELLKNOWN_UINT64VALUE:
57
- case UPB_WELLKNOWN_INT32VALUE:
58
- case UPB_WELLKNOWN_UINT32VALUE:
59
- case UPB_WELLKNOWN_STRINGVALUE:
60
- case UPB_WELLKNOWN_BYTESVALUE:
61
- case UPB_WELLKNOWN_BOOLVALUE:
62
- return true;
63
- default:
64
- return false;
65
- }
66
- }
67
-
68
- // The code below also comes from upb's prototype Ruby binding, developed by
69
- // haberman@.
70
-
71
- /* stringsink *****************************************************************/
72
-
73
- static void *stringsink_start(void *_sink, const void *hd, size_t size_hint) {
74
- stringsink *sink = _sink;
75
- sink->len = 0;
76
- return sink;
77
- }
78
-
79
- static size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
80
- size_t len, const upb_bufhandle *handle) {
81
- stringsink *sink = _sink;
82
- size_t new_size = sink->size;
83
-
84
- UPB_UNUSED(hd);
85
- UPB_UNUSED(handle);
86
-
87
- while (sink->len + len > new_size) {
88
- new_size *= 2;
89
- }
90
-
91
- if (new_size != sink->size) {
92
- sink->ptr = realloc(sink->ptr, new_size);
93
- sink->size = new_size;
94
- }
95
-
96
- memcpy(sink->ptr + sink->len, ptr, len);
97
- sink->len += len;
98
-
99
- return len;
100
- }
101
-
102
- void stringsink_init(stringsink *sink) {
103
- upb_byteshandler_init(&sink->handler);
104
- upb_byteshandler_setstartstr(&sink->handler, stringsink_start, NULL);
105
- upb_byteshandler_setstring(&sink->handler, stringsink_string, NULL);
106
-
107
- upb_bytessink_reset(&sink->sink, &sink->handler, sink);
108
-
109
- sink->size = 32;
110
- sink->ptr = malloc(sink->size);
111
- sink->len = 0;
112
- }
113
-
114
- void stringsink_uninit(stringsink *sink) {
115
- free(sink->ptr);
116
- }
117
-
118
- // -----------------------------------------------------------------------------
119
- // Parsing.
120
- // -----------------------------------------------------------------------------
121
-
122
- #define DEREF(msg, ofs, type) *(type*)(((uint8_t *)msg) + ofs)
123
-
124
- typedef struct {
125
- size_t ofs;
126
- int32_t hasbit;
127
- } field_handlerdata_t;
128
-
129
- // Creates a handlerdata that contains the offset and the hasbit for the field
130
- static const void* newhandlerdata(upb_handlers* h, uint32_t ofs, int32_t hasbit) {
131
- field_handlerdata_t *hd = ALLOC(field_handlerdata_t);
132
- hd->ofs = ofs;
133
- hd->hasbit = hasbit;
134
- upb_handlers_addcleanup(h, hd, xfree);
135
- return hd;
136
- }
137
-
138
- typedef struct {
139
- size_t ofs;
140
- int32_t hasbit;
141
- upb_fieldtype_t wrapped_type; // Only for wrappers.
142
- VALUE subklass;
143
- } submsg_handlerdata_t;
144
-
145
- // Creates a handlerdata that contains offset and submessage type information.
146
- static const void *newsubmsghandlerdata(upb_handlers* h,
147
- const upb_fielddef *f,
148
- uint32_t ofs,
149
- int32_t hasbit,
150
- VALUE subklass) {
151
- submsg_handlerdata_t *hd = ALLOC(submsg_handlerdata_t);
152
- const upb_msgdef *subm = upb_fielddef_msgsubdef(f);
153
- hd->ofs = ofs;
154
- hd->hasbit = hasbit;
155
- hd->subklass = subklass;
156
- upb_handlers_addcleanup(h, hd, xfree);
157
- if (is_wrapper(subm)) {
158
- const upb_fielddef *value_f = upb_msgdef_itof(subm, 1);
159
- hd->wrapped_type = upb_fielddef_type(value_f);
160
- }
161
- return hd;
162
- }
163
-
164
- typedef struct {
165
- size_t ofs; // union data slot
166
- size_t case_ofs; // oneof_case field
167
- uint32_t oneof_case_num; // oneof-case number to place in oneof_case field
168
- VALUE subklass;
169
- } oneof_handlerdata_t;
170
-
171
- static const void *newoneofhandlerdata(upb_handlers *h,
172
- uint32_t ofs,
173
- uint32_t case_ofs,
174
- const upb_fielddef *f,
175
- const Descriptor* desc) {
176
- oneof_handlerdata_t *hd = ALLOC(oneof_handlerdata_t);
177
- hd->ofs = ofs;
178
- hd->case_ofs = case_ofs;
179
- // We reuse the field tag number as a oneof union discriminant tag. Note that
180
- // we don't expose these numbers to the user, so the only requirement is that
181
- // we have some unique ID for each union case/possibility. The field tag
182
- // numbers are already present and are easy to use so there's no reason to
183
- // create a separate ID space. In addition, using the field tag number here
184
- // lets us easily look up the field in the oneof accessor.
185
- hd->oneof_case_num = upb_fielddef_number(f);
186
- if (is_value_field(f)) {
187
- hd->oneof_case_num |= ONEOF_CASE_MASK;
188
- }
189
- hd->subklass = field_type_class(desc->layout, f);
190
- upb_handlers_addcleanup(h, hd, xfree);
191
- return hd;
192
- }
193
-
194
- // A handler that starts a repeated field. Gets the Repeated*Field instance for
195
- // this field (such an instance always exists even in an empty message).
196
- static void *startseq_handler(void* closure, const void* hd) {
197
- MessageHeader* msg = closure;
198
- const size_t *ofs = hd;
199
- return (void*)DEREF(msg, *ofs, VALUE);
200
- }
201
-
202
- // Handlers that append primitive values to a repeated field.
203
- #define DEFINE_APPEND_HANDLER(type, ctype) \
204
- static bool append##type##_handler(void *closure, const void *hd, \
205
- ctype val) { \
206
- VALUE ary = (VALUE)closure; \
207
- RepeatedField_push_native(ary, &val); \
208
- return true; \
209
- }
210
-
211
- DEFINE_APPEND_HANDLER(bool, bool)
212
- DEFINE_APPEND_HANDLER(int32, int32_t)
213
- DEFINE_APPEND_HANDLER(uint32, uint32_t)
214
- DEFINE_APPEND_HANDLER(float, float)
215
- DEFINE_APPEND_HANDLER(int64, int64_t)
216
- DEFINE_APPEND_HANDLER(uint64, uint64_t)
217
- DEFINE_APPEND_HANDLER(double, double)
218
-
219
- // Appends a string to a repeated field.
220
- static void* appendstr_handler(void *closure,
221
- const void *hd,
222
- size_t size_hint) {
223
- VALUE ary = (VALUE)closure;
224
- VALUE str = rb_str_new2("");
225
- rb_enc_associate(str, kRubyStringUtf8Encoding);
226
- RepeatedField_push_native(ary, &str);
227
- return (void*)str;
228
- }
229
-
230
- static void set_hasbit(void *closure, int32_t hasbit) {
231
- if (hasbit > 0) {
232
- uint8_t* storage = closure;
233
- storage[hasbit/8] |= 1 << (hasbit % 8);
234
- }
235
- }
236
-
237
- // Appends a 'bytes' string to a repeated field.
238
- static void* appendbytes_handler(void *closure,
239
- const void *hd,
240
- size_t size_hint) {
241
- VALUE ary = (VALUE)closure;
242
- VALUE str = rb_str_new2("");
243
- rb_enc_associate(str, kRubyString8bitEncoding);
244
- RepeatedField_push_native(ary, &str);
245
- return (void*)str;
246
- }
247
-
248
- // Sets a non-repeated string field in a message.
249
- static void* str_handler(void *closure,
250
- const void *hd,
251
- size_t size_hint) {
252
- MessageHeader* msg = closure;
253
- const field_handlerdata_t *fieldhandler = hd;
254
-
255
- VALUE str = rb_str_new2("");
256
- rb_enc_associate(str, kRubyStringUtf8Encoding);
257
- DEREF(msg, fieldhandler->ofs, VALUE) = str;
258
- set_hasbit(closure, fieldhandler->hasbit);
259
- return (void*)str;
260
- }
261
-
262
- // Sets a non-repeated 'bytes' field in a message.
263
- static void* bytes_handler(void *closure,
264
- const void *hd,
265
- size_t size_hint) {
266
- MessageHeader* msg = closure;
267
- const field_handlerdata_t *fieldhandler = hd;
268
-
269
- VALUE str = rb_str_new2("");
270
- rb_enc_associate(str, kRubyString8bitEncoding);
271
- DEREF(msg, fieldhandler->ofs, VALUE) = str;
272
- set_hasbit(closure, fieldhandler->hasbit);
273
- return (void*)str;
274
- }
275
-
276
- static size_t stringdata_handler(void* closure, const void* hd,
277
- const char* str, size_t len,
278
- const upb_bufhandle* handle) {
279
- VALUE rb_str = (VALUE)closure;
280
- noleak_rb_str_cat(rb_str, str, len);
281
- return len;
282
- }
283
-
284
- static bool stringdata_end_handler(void* closure, const void* hd) {
285
- VALUE rb_str = (VALUE)closure;
286
- rb_obj_freeze(rb_str);
287
- return true;
288
- }
289
-
290
- static bool appendstring_end_handler(void* closure, const void* hd) {
291
- VALUE rb_str = (VALUE)closure;
292
- rb_obj_freeze(rb_str);
293
- return true;
294
- }
295
-
296
- // Appends a submessage to a repeated field (a regular Ruby array for now).
297
- static void *appendsubmsg_handler(void *closure, const void *hd) {
298
- VALUE ary = (VALUE)closure;
299
- const submsg_handlerdata_t *submsgdata = hd;
300
- MessageHeader* submsg;
301
-
302
- VALUE submsg_rb = initialize_rb_class_with_no_args(submsgdata->subklass);
303
- RepeatedField_push(ary, submsg_rb);
304
-
305
- TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
306
- return submsg;
307
- }
308
-
309
- // Appends a wrapper to a repeated field (a regular Ruby array for now).
310
- static void *appendwrapper_handler(void *closure, const void *hd) {
311
- VALUE ary = (VALUE)closure;
312
- int size = RepeatedField_size(ary);
313
- (void)hd;
314
-
315
- RepeatedField_push(ary, Qnil);
316
-
317
- return RepeatedField_index_native(ary, size);
318
- }
319
-
320
- // Sets a non-repeated submessage field in a message.
321
- static void *submsg_handler(void *closure, const void *hd) {
322
- MessageHeader* msg = closure;
323
- const submsg_handlerdata_t* submsgdata = hd;
324
- VALUE submsg_rb;
325
- MessageHeader* submsg;
326
-
327
- if (DEREF(msg, submsgdata->ofs, VALUE) == Qnil) {
328
- DEREF(msg, submsgdata->ofs, VALUE) =
329
- initialize_rb_class_with_no_args(submsgdata->subklass);
330
- }
331
-
332
- set_hasbit(closure, submsgdata->hasbit);
333
-
334
- submsg_rb = DEREF(msg, submsgdata->ofs, VALUE);
335
- TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
336
-
337
- return submsg;
338
- }
339
-
340
- static void* startwrapper(void* closure, const void* hd) {
341
- const submsg_handlerdata_t* submsgdata = hd;
342
- char* msg = closure;
343
- VALUE* field = (VALUE*)(msg + submsgdata->ofs);
344
-
345
- set_hasbit(closure, submsgdata->hasbit);
346
-
347
- switch (submsgdata->wrapped_type) {
348
- case UPB_TYPE_FLOAT:
349
- case UPB_TYPE_DOUBLE:
350
- *field = DBL2NUM(0);
351
- break;
352
- case UPB_TYPE_BOOL:
353
- *field = Qfalse;
354
- break;
355
- case UPB_TYPE_STRING:
356
- *field = get_frozen_string(NULL, 0, false);
357
- break;
358
- case UPB_TYPE_BYTES:
359
- *field = get_frozen_string(NULL, 0, true);
360
- break;
361
- case UPB_TYPE_ENUM:
362
- case UPB_TYPE_INT32:
363
- case UPB_TYPE_INT64:
364
- case UPB_TYPE_UINT32:
365
- case UPB_TYPE_UINT64:
366
- *field = INT2NUM(0);
367
- break;
368
- case UPB_TYPE_MESSAGE:
369
- rb_raise(rb_eRuntimeError,
370
- "Internal logic error with well-known types.");
371
- }
372
-
373
- return field;
374
- }
375
-
376
- // Handler data for startmap/endmap handlers.
377
- typedef struct {
378
- size_t ofs;
379
- upb_fieldtype_t key_field_type;
380
- upb_fieldtype_t value_field_type;
381
- VALUE subklass;
382
- } map_handlerdata_t;
383
-
384
- // Temporary frame for map parsing: at the beginning of a map entry message, a
385
- // submsg handler allocates a frame to hold (i) a reference to the Map object
386
- // into which this message will be inserted and (ii) storage slots to
387
- // temporarily hold the key and value for this map entry until the end of the
388
- // submessage. When the submessage ends, another handler is called to insert the
389
- // value into the map.
390
- typedef struct {
391
- VALUE map;
392
- const map_handlerdata_t* handlerdata;
393
- char key_storage[NATIVE_SLOT_MAX_SIZE];
394
- char value_storage[NATIVE_SLOT_MAX_SIZE];
395
- } map_parse_frame_t;
396
-
397
- static void MapParseFrame_mark(void* _self) {
398
- map_parse_frame_t* frame = _self;
399
-
400
- // This shouldn't strictly be necessary since this should be rooted by the
401
- // message itself, but it can't hurt.
402
- rb_gc_mark(frame->map);
403
-
404
- native_slot_mark(frame->handlerdata->key_field_type, &frame->key_storage);
405
- native_slot_mark(frame->handlerdata->value_field_type, &frame->value_storage);
406
- }
407
-
408
- void MapParseFrame_free(void* self) {
409
- xfree(self);
410
- }
411
-
412
- rb_data_type_t MapParseFrame_type = {
413
- "MapParseFrame",
414
- { MapParseFrame_mark, MapParseFrame_free, NULL },
415
- };
416
-
417
- // Handler to begin a map entry: allocates a temporary frame. This is the
418
- // 'startsubmsg' handler on the msgdef that contains the map field.
419
- static void *startmap_handler(void *closure, const void *hd) {
420
- MessageHeader* msg = closure;
421
- const map_handlerdata_t* mapdata = hd;
422
- map_parse_frame_t* frame = ALLOC(map_parse_frame_t);
423
- VALUE map_rb = DEREF(msg, mapdata->ofs, VALUE);
424
-
425
- frame->handlerdata = mapdata;
426
- frame->map = map_rb;
427
- native_slot_init(mapdata->key_field_type, &frame->key_storage);
428
- native_slot_init(mapdata->value_field_type, &frame->value_storage);
429
-
430
- Map_set_frame(map_rb,
431
- TypedData_Wrap_Struct(rb_cObject, &MapParseFrame_type, frame));
432
-
433
- return frame;
434
- }
435
-
436
- static bool endmap_handler(void *closure, const void *hd) {
437
- map_parse_frame_t* frame = closure;
438
- Map_set_frame(frame->map, Qnil);
439
- return true;
440
- }
441
-
442
- // Handler to end a map entry: inserts the value defined during the message into
443
- // the map. This is the 'endmsg' handler on the map entry msgdef.
444
- static bool endmapentry_handler(void* closure, const void* hd, upb_status* s) {
445
- map_parse_frame_t* frame = closure;
446
- const map_handlerdata_t* mapdata = hd;
447
-
448
- VALUE key = native_slot_get(
449
- mapdata->key_field_type, Qnil,
450
- &frame->key_storage);
451
-
452
- VALUE value = native_slot_get(
453
- mapdata->value_field_type, mapdata->subklass,
454
- &frame->value_storage);
455
-
456
- Map_index_set(frame->map, key, value);
457
-
458
- return true;
459
- }
460
-
461
- // Allocates a new map_handlerdata_t given the map entry message definition. If
462
- // the offset of the field within the parent message is also given, that is
463
- // added to the handler data as well. Note that this is called *twice* per map
464
- // field: once in the parent message handler setup when setting the startsubmsg
465
- // handler and once in the map entry message handler setup when setting the
466
- // key/value and endmsg handlers. The reason is that there is no easy way to
467
- // pass the handlerdata down to the sub-message handler setup.
468
- static map_handlerdata_t* new_map_handlerdata(
469
- size_t ofs,
470
- const upb_msgdef* mapentry_def,
471
- const Descriptor* desc) {
472
- const upb_fielddef* key_field;
473
- const upb_fielddef* value_field;
474
- map_handlerdata_t* hd = ALLOC(map_handlerdata_t);
475
- hd->ofs = ofs;
476
- key_field = upb_msgdef_itof(mapentry_def, MAP_KEY_FIELD);
477
- assert(key_field != NULL);
478
- hd->key_field_type = upb_fielddef_type(key_field);
479
- value_field = upb_msgdef_itof(mapentry_def, MAP_VALUE_FIELD);
480
- assert(value_field != NULL);
481
- hd->value_field_type = upb_fielddef_type(value_field);
482
- hd->subklass = field_type_class(desc->layout, value_field);
483
-
484
- return hd;
485
- }
486
-
487
- // Handlers that set primitive values in oneofs.
488
- #define DEFINE_ONEOF_HANDLER(type, ctype) \
489
- static bool oneof##type##_handler(void *closure, const void *hd, \
490
- ctype val) { \
491
- const oneof_handlerdata_t *oneofdata = hd; \
492
- DEREF(closure, oneofdata->case_ofs, uint32_t) = \
493
- oneofdata->oneof_case_num; \
494
- DEREF(closure, oneofdata->ofs, ctype) = val; \
495
- return true; \
496
- }
497
-
498
- DEFINE_ONEOF_HANDLER(bool, bool)
499
- DEFINE_ONEOF_HANDLER(int32, int32_t)
500
- DEFINE_ONEOF_HANDLER(uint32, uint32_t)
501
- DEFINE_ONEOF_HANDLER(float, float)
502
- DEFINE_ONEOF_HANDLER(int64, int64_t)
503
- DEFINE_ONEOF_HANDLER(uint64, uint64_t)
504
- DEFINE_ONEOF_HANDLER(double, double)
505
-
506
- #undef DEFINE_ONEOF_HANDLER
507
-
508
- // Handlers for strings in a oneof.
509
- static void *oneofstr_handler(void *closure,
510
- const void *hd,
511
- size_t size_hint) {
512
- MessageHeader* msg = closure;
513
- const oneof_handlerdata_t *oneofdata = hd;
514
- VALUE str = rb_str_new2("");
515
- rb_enc_associate(str, kRubyStringUtf8Encoding);
516
- DEREF(msg, oneofdata->case_ofs, uint32_t) =
517
- oneofdata->oneof_case_num;
518
- DEREF(msg, oneofdata->ofs, VALUE) = str;
519
- return (void*)str;
520
- }
521
-
522
- static void *oneofbytes_handler(void *closure,
523
- const void *hd,
524
- size_t size_hint) {
525
- MessageHeader* msg = closure;
526
- const oneof_handlerdata_t *oneofdata = hd;
527
- VALUE str = rb_str_new2("");
528
- rb_enc_associate(str, kRubyString8bitEncoding);
529
- DEREF(msg, oneofdata->case_ofs, uint32_t) =
530
- oneofdata->oneof_case_num;
531
- DEREF(msg, oneofdata->ofs, VALUE) = str;
532
- return (void*)str;
533
- }
534
-
535
- static bool oneofstring_end_handler(void* closure, const void* hd) {
536
- VALUE rb_str = rb_str_new2("");
537
- rb_obj_freeze(rb_str);
538
- return true;
539
- }
540
-
541
- // Handler for a submessage field in a oneof.
542
- static void *oneofsubmsg_handler(void *closure,
543
- const void *hd) {
544
- MessageHeader* msg = closure;
545
- const oneof_handlerdata_t *oneofdata = hd;
546
- uint32_t oldcase = DEREF(msg, oneofdata->case_ofs, uint32_t);
547
-
548
- VALUE submsg_rb;
549
- MessageHeader* submsg;
550
-
551
- if (oldcase != oneofdata->oneof_case_num ||
552
- DEREF(msg, oneofdata->ofs, VALUE) == Qnil) {
553
- DEREF(msg, oneofdata->ofs, VALUE) =
554
- initialize_rb_class_with_no_args(oneofdata->subklass);
555
- }
556
- // Set the oneof case *after* allocating the new class instance -- otherwise,
557
- // if the Ruby GC is invoked as part of a call into the VM, it might invoke
558
- // our mark routines, and our mark routines might see the case value
559
- // indicating a VALUE is present and expect a valid VALUE. See comment in
560
- // layout_set() for more detail: basically, the change to the value and the
561
- // case must be atomic w.r.t. the Ruby VM.
562
- DEREF(msg, oneofdata->case_ofs, uint32_t) = oneofdata->oneof_case_num;
563
-
564
- submsg_rb = DEREF(msg, oneofdata->ofs, VALUE);
565
- TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
566
- return submsg;
567
- }
568
-
569
- static void* oneof_startwrapper(void* closure, const void* hd) {
570
- char* msg = closure;
571
- const oneof_handlerdata_t *oneofdata = hd;
572
-
573
- DEREF(msg, oneofdata->case_ofs, uint32_t) = oneofdata->oneof_case_num;
574
-
575
- return msg + oneofdata->ofs;
576
- }
577
-
578
- // Set up handlers for a repeated field.
579
- static void add_handlers_for_repeated_field(upb_handlers *h,
580
- const Descriptor* desc,
581
- const upb_fielddef *f,
582
- size_t offset) {
583
- upb_handlerattr attr = UPB_HANDLERATTR_INIT;
584
- attr.handler_data = newhandlerdata(h, offset, -1);
585
- upb_handlers_setstartseq(h, f, startseq_handler, &attr);
586
-
587
- switch (upb_fielddef_type(f)) {
588
-
589
- #define SET_HANDLER(utype, ltype) \
590
- case utype: \
591
- upb_handlers_set##ltype(h, f, append##ltype##_handler, NULL); \
592
- break;
593
-
594
- SET_HANDLER(UPB_TYPE_BOOL, bool);
595
- SET_HANDLER(UPB_TYPE_INT32, int32);
596
- SET_HANDLER(UPB_TYPE_UINT32, uint32);
597
- SET_HANDLER(UPB_TYPE_ENUM, int32);
598
- SET_HANDLER(UPB_TYPE_FLOAT, float);
599
- SET_HANDLER(UPB_TYPE_INT64, int64);
600
- SET_HANDLER(UPB_TYPE_UINT64, uint64);
601
- SET_HANDLER(UPB_TYPE_DOUBLE, double);
602
-
603
- #undef SET_HANDLER
604
-
605
- case UPB_TYPE_STRING:
606
- case UPB_TYPE_BYTES: {
607
- bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
608
- upb_handlers_setstartstr(h, f, is_bytes ?
609
- appendbytes_handler : appendstr_handler,
610
- NULL);
611
- upb_handlers_setstring(h, f, stringdata_handler, NULL);
612
- upb_handlers_setendstr(h, f, appendstring_end_handler, NULL);
613
- break;
614
- }
615
- case UPB_TYPE_MESSAGE: {
616
- VALUE subklass = field_type_class(desc->layout, f);
617
- upb_handlerattr attr = UPB_HANDLERATTR_INIT;
618
- attr.handler_data = newsubmsghandlerdata(h, f, 0, -1, subklass);
619
- if (is_wrapper(upb_fielddef_msgsubdef(f))) {
620
- upb_handlers_setstartsubmsg(h, f, appendwrapper_handler, &attr);
621
- } else {
622
- upb_handlers_setstartsubmsg(h, f, appendsubmsg_handler, &attr);
623
- }
624
- break;
625
- }
626
- }
627
- }
628
-
629
- static bool doublewrapper_handler(void* closure, const void* hd, double val) {
630
- VALUE* rbval = closure;
631
- *rbval = DBL2NUM(val);
632
- return true;
633
- }
634
-
635
- static bool floatwrapper_handler(void* closure, const void* hd, float val) {
636
- VALUE* rbval = closure;
637
- *rbval = DBL2NUM(val);
638
- return true;
639
- }
640
-
641
- static bool int64wrapper_handler(void* closure, const void* hd, int64_t val) {
642
- VALUE* rbval = closure;
643
- *rbval = LL2NUM(val);
644
- return true;
645
- }
646
-
647
- static bool uint64wrapper_handler(void* closure, const void* hd, uint64_t val) {
648
- VALUE* rbval = closure;
649
- *rbval = ULL2NUM(val);
650
- return true;
651
- }
652
-
653
- static bool int32wrapper_handler(void* closure, const void* hd, int32_t val) {
654
- VALUE* rbval = closure;
655
- *rbval = INT2NUM(val);
656
- return true;
657
- }
658
-
659
- static bool uint32wrapper_handler(void* closure, const void* hd, uint32_t val) {
660
- VALUE* rbval = closure;
661
- *rbval = UINT2NUM(val);
662
- return true;
663
- }
664
-
665
- static void* startstringwrapper_handler(void* closure, const void* hd,
666
- size_t size_hint) {
667
- VALUE* rbval = closure;
668
- (void)size_hint;
669
- *rbval = rb_str_new(NULL, 0);
670
- rb_enc_associate(*rbval, kRubyStringUtf8Encoding);
671
- return closure;
672
- }
673
-
674
- static size_t stringwrapper_handler(void* closure, const void* hd,
675
- const char* ptr, size_t len,
676
- const upb_bufhandle* handle) {
677
- VALUE* rbval = closure;
678
- *rbval = noleak_rb_str_cat(*rbval, ptr, len);
679
- return len;
680
- }
681
-
682
- static void* startbyteswrapper_handler(void* closure, const void* hd,
683
- size_t size_hint) {
684
- VALUE* rbval = closure;
685
- (void)size_hint;
686
- *rbval = rb_str_new(NULL, 0);
687
- rb_enc_associate(*rbval, kRubyString8bitEncoding);
688
- return closure;
689
- }
690
-
691
- static size_t byteswrapper_handler(void* closure, const void* hd,
692
- const char* ptr, size_t len,
693
- const upb_bufhandle* handle) {
694
- VALUE* rbval = closure;
695
- *rbval = noleak_rb_str_cat(*rbval, ptr, len);
696
- return len;
697
- }
698
-
699
- static bool boolwrapper_handler(void* closure, const void* hd, bool val) {
700
- VALUE* rbval = closure;
701
- if (val) {
702
- *rbval = Qtrue;
703
- } else {
704
- *rbval = Qfalse;
705
- }
706
- return true;
707
- }
708
-
709
- // Set up handlers for a singular field.
710
- static void add_handlers_for_singular_field(const Descriptor* desc,
711
- upb_handlers* h,
712
- const upb_fielddef* f,
713
- size_t offset, size_t hasbit_off) {
714
- // The offset we pass to UPB points to the start of the Message,
715
- // rather than the start of where our data is stored.
716
- int32_t hasbit = -1;
717
- if (hasbit_off != MESSAGE_FIELD_NO_HASBIT) {
718
- hasbit = hasbit_off + sizeof(MessageHeader) * 8;
719
- }
720
-
721
- switch (upb_fielddef_type(f)) {
722
- case UPB_TYPE_BOOL:
723
- case UPB_TYPE_INT32:
724
- case UPB_TYPE_UINT32:
725
- case UPB_TYPE_ENUM:
726
- case UPB_TYPE_FLOAT:
727
- case UPB_TYPE_INT64:
728
- case UPB_TYPE_UINT64:
729
- case UPB_TYPE_DOUBLE:
730
- upb_msg_setscalarhandler(h, f, offset, hasbit);
731
- break;
732
- case UPB_TYPE_STRING:
733
- case UPB_TYPE_BYTES: {
734
- bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
735
- upb_handlerattr attr = UPB_HANDLERATTR_INIT;
736
- attr.handler_data = newhandlerdata(h, offset, hasbit);
737
- upb_handlers_setstartstr(h, f,
738
- is_bytes ? bytes_handler : str_handler,
739
- &attr);
740
- upb_handlers_setstring(h, f, stringdata_handler, &attr);
741
- upb_handlers_setendstr(h, f, stringdata_end_handler, &attr);
742
- break;
743
- }
744
- case UPB_TYPE_MESSAGE: {
745
- upb_handlerattr attr = UPB_HANDLERATTR_INIT;
746
- attr.handler_data = newsubmsghandlerdata(
747
- h, f, offset, hasbit, field_type_class(desc->layout, f));
748
- if (is_wrapper(upb_fielddef_msgsubdef(f))) {
749
- upb_handlers_setstartsubmsg(h, f, startwrapper, &attr);
750
- } else {
751
- upb_handlers_setstartsubmsg(h, f, submsg_handler, &attr);
752
- }
753
- }
754
- }
755
- }
756
-
757
- // Adds handlers to a map field.
758
- static void add_handlers_for_mapfield(upb_handlers* h,
759
- const upb_fielddef* fielddef,
760
- size_t offset,
761
- const Descriptor* desc) {
762
- const upb_msgdef* map_msgdef = upb_fielddef_msgsubdef(fielddef);
763
- map_handlerdata_t* hd = new_map_handlerdata(offset, map_msgdef, desc);
764
- upb_handlerattr attr = UPB_HANDLERATTR_INIT;
765
-
766
- upb_handlers_addcleanup(h, hd, xfree);
767
- attr.handler_data = hd;
768
- upb_handlers_setstartsubmsg(h, fielddef, startmap_handler, &attr);
769
- upb_handlers_setendsubmsg(h, fielddef, endmap_handler, &attr);
770
- }
771
-
772
- // Adds handlers to a map-entry msgdef.
773
- static void add_handlers_for_mapentry(const upb_msgdef* msgdef, upb_handlers* h,
774
- const Descriptor* desc) {
775
- const upb_fielddef* key_field = map_entry_key(msgdef);
776
- const upb_fielddef* value_field = map_entry_value(msgdef);
777
- map_handlerdata_t* hd = new_map_handlerdata(0, msgdef, desc);
778
- upb_handlerattr attr = UPB_HANDLERATTR_INIT;
779
-
780
- upb_handlers_addcleanup(h, hd, xfree);
781
- attr.handler_data = hd;
782
- upb_handlers_setendmsg(h, endmapentry_handler, &attr);
783
-
784
- add_handlers_for_singular_field(
785
- desc, h, key_field,
786
- offsetof(map_parse_frame_t, key_storage),
787
- MESSAGE_FIELD_NO_HASBIT);
788
- add_handlers_for_singular_field(
789
- desc, h, value_field,
790
- offsetof(map_parse_frame_t, value_storage),
791
- MESSAGE_FIELD_NO_HASBIT);
792
- }
793
-
794
- static void add_handlers_for_wrapper(const upb_msgdef* msgdef,
795
- upb_handlers* h) {
796
- const upb_fielddef* f = upb_msgdef_itof(msgdef, 1);
797
- switch (upb_msgdef_wellknowntype(msgdef)) {
798
- case UPB_WELLKNOWN_DOUBLEVALUE:
799
- upb_handlers_setdouble(h, f, doublewrapper_handler, NULL);
800
- break;
801
- case UPB_WELLKNOWN_FLOATVALUE:
802
- upb_handlers_setfloat(h, f, floatwrapper_handler, NULL);
803
- break;
804
- case UPB_WELLKNOWN_INT64VALUE:
805
- upb_handlers_setint64(h, f, int64wrapper_handler, NULL);
806
- break;
807
- case UPB_WELLKNOWN_UINT64VALUE:
808
- upb_handlers_setuint64(h, f, uint64wrapper_handler, NULL);
809
- break;
810
- case UPB_WELLKNOWN_INT32VALUE:
811
- upb_handlers_setint32(h, f, int32wrapper_handler, NULL);
812
- break;
813
- case UPB_WELLKNOWN_UINT32VALUE:
814
- upb_handlers_setuint32(h, f, uint32wrapper_handler, NULL);
815
- break;
816
- case UPB_WELLKNOWN_STRINGVALUE:
817
- upb_handlers_setstartstr(h, f, startstringwrapper_handler, NULL);
818
- upb_handlers_setstring(h, f, stringwrapper_handler, NULL);
819
- break;
820
- case UPB_WELLKNOWN_BYTESVALUE:
821
- upb_handlers_setstartstr(h, f, startbyteswrapper_handler, NULL);
822
- upb_handlers_setstring(h, f, byteswrapper_handler, NULL);
823
- break;
824
- case UPB_WELLKNOWN_BOOLVALUE:
825
- upb_handlers_setbool(h, f, boolwrapper_handler, NULL);
826
- return;
827
- default:
828
- rb_raise(rb_eRuntimeError,
829
- "Internal logic error with well-known types.");
830
- }
831
- }
832
-
833
- // Set up handlers for a oneof field.
834
- static void add_handlers_for_oneof_field(upb_handlers *h,
835
- const upb_fielddef *f,
836
- size_t offset,
837
- size_t oneof_case_offset,
838
- const Descriptor* desc) {
839
- upb_handlerattr attr = UPB_HANDLERATTR_INIT;
840
- attr.handler_data =
841
- newoneofhandlerdata(h, offset, oneof_case_offset, f, desc);
842
-
843
- switch (upb_fielddef_type(f)) {
844
-
845
- #define SET_HANDLER(utype, ltype) \
846
- case utype: \
847
- upb_handlers_set##ltype(h, f, oneof##ltype##_handler, &attr); \
848
- break;
849
-
850
- SET_HANDLER(UPB_TYPE_BOOL, bool);
851
- SET_HANDLER(UPB_TYPE_INT32, int32);
852
- SET_HANDLER(UPB_TYPE_UINT32, uint32);
853
- SET_HANDLER(UPB_TYPE_ENUM, int32);
854
- SET_HANDLER(UPB_TYPE_FLOAT, float);
855
- SET_HANDLER(UPB_TYPE_INT64, int64);
856
- SET_HANDLER(UPB_TYPE_UINT64, uint64);
857
- SET_HANDLER(UPB_TYPE_DOUBLE, double);
858
-
859
- #undef SET_HANDLER
860
-
861
- case UPB_TYPE_STRING:
862
- case UPB_TYPE_BYTES: {
863
- bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
864
- upb_handlers_setstartstr(h, f, is_bytes ?
865
- oneofbytes_handler : oneofstr_handler,
866
- &attr);
867
- upb_handlers_setstring(h, f, stringdata_handler, NULL);
868
- upb_handlers_setendstr(h, f, oneofstring_end_handler, &attr);
869
- break;
870
- }
871
- case UPB_TYPE_MESSAGE: {
872
- if (is_wrapper(upb_fielddef_msgsubdef(f))) {
873
- upb_handlers_setstartsubmsg(h, f, oneof_startwrapper, &attr);
874
- } else {
875
- upb_handlers_setstartsubmsg(h, f, oneofsubmsg_handler, &attr);
876
- }
877
- break;
878
- }
879
- }
880
- }
881
-
882
- static bool unknown_field_handler(void* closure, const void* hd,
883
- const char* buf, size_t size) {
884
- MessageHeader* msg = (MessageHeader*)closure;
885
- UPB_UNUSED(hd);
886
-
887
- if (msg->unknown_fields == NULL) {
888
- msg->unknown_fields = malloc(sizeof(stringsink));
889
- stringsink_init(msg->unknown_fields);
890
- }
891
-
892
- stringsink_string(msg->unknown_fields, NULL, buf, size, NULL);
893
-
894
- return true;
895
- }
896
-
897
- size_t get_field_offset(MessageLayout* layout, const upb_fielddef* f) {
898
- return layout->fields[upb_fielddef_index(f)].offset + sizeof(MessageHeader);
899
- }
900
-
901
- void add_handlers_for_message(const void *closure, upb_handlers *h) {
902
- const VALUE descriptor_pool = (VALUE)closure;
903
- const upb_msgdef* msgdef = upb_handlers_msgdef(h);
904
- Descriptor* desc =
905
- ruby_to_Descriptor(get_msgdef_obj(descriptor_pool, msgdef));
906
- upb_msg_field_iter i;
907
- upb_handlerattr attr = UPB_HANDLERATTR_INIT;
908
-
909
- // Ensure layout exists. We may be invoked to create handlers for a given
910
- // message if we are included as a submsg of another message type before our
911
- // class is actually built, so to work around this, we just create the layout
912
- // (and handlers, in the class-building function) on-demand.
913
- if (desc->layout == NULL) {
914
- create_layout(desc);
915
- }
916
-
917
- // If this is a mapentry message type, set up a special set of handlers and
918
- // bail out of the normal (user-defined) message type handling.
919
- if (upb_msgdef_mapentry(msgdef)) {
920
- add_handlers_for_mapentry(msgdef, h, desc);
921
- return;
922
- }
923
-
924
- // If this is a wrapper type, use special handlers and bail.
925
- if (is_wrapper(msgdef)) {
926
- add_handlers_for_wrapper(msgdef, h);
927
- return;
928
- }
929
-
930
- upb_handlers_setunknown(h, unknown_field_handler, &attr);
931
-
932
- for (upb_msg_field_begin(&i, desc->msgdef);
933
- !upb_msg_field_done(&i);
934
- upb_msg_field_next(&i)) {
935
- const upb_fielddef *f = upb_msg_iter_field(&i);
936
- const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(f);
937
- size_t offset = get_field_offset(desc->layout, f);
938
-
939
- if (oneof) {
940
- size_t oneof_case_offset =
941
- desc->layout->oneofs[upb_oneofdef_index(oneof)].case_offset +
942
- sizeof(MessageHeader);
943
- add_handlers_for_oneof_field(h, f, offset, oneof_case_offset, desc);
944
- } else if (is_map_field(f)) {
945
- add_handlers_for_mapfield(h, f, offset, desc);
946
- } else if (upb_fielddef_isseq(f)) {
947
- add_handlers_for_repeated_field(h, desc, f, offset);
948
- } else {
949
- add_handlers_for_singular_field(
950
- desc, h, f, offset,
951
- desc->layout->fields[upb_fielddef_index(f)].hasbit);
952
- }
953
- }
954
- }
955
-
956
- // Constructs the handlers for filling a message's data into an in-memory
957
- // object.
958
- const upb_handlers* get_fill_handlers(Descriptor* desc) {
959
- DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool);
960
- return upb_handlercache_get(pool->fill_handler_cache, desc->msgdef);
961
- }
962
-
963
- static const upb_pbdecodermethod *msgdef_decodermethod(Descriptor* desc) {
964
- DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool);
965
- return upb_pbcodecache_get(pool->fill_method_cache, desc->msgdef);
966
- }
967
-
968
- static const upb_json_parsermethod *msgdef_jsonparsermethod(Descriptor* desc) {
969
- DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool);
970
- return upb_json_codecache_get(pool->json_fill_method_cache, desc->msgdef);
971
- }
972
-
973
- static const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) {
974
- DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool);
975
- return upb_handlercache_get(pool->pb_serialize_handler_cache, desc->msgdef);
976
- }
977
-
978
- static const upb_handlers* msgdef_json_serialize_handlers(
979
- Descriptor* desc, bool preserve_proto_fieldnames) {
980
- DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool);
981
- if (preserve_proto_fieldnames) {
982
- return upb_handlercache_get(pool->json_serialize_handler_preserve_cache,
983
- desc->msgdef);
984
- } else {
985
- return upb_handlercache_get(pool->json_serialize_handler_cache,
986
- desc->msgdef);
987
- }
988
- }
989
-
990
-
991
- // Stack-allocated context during an encode/decode operation. Contains the upb
992
- // environment and its stack-based allocator, an initial buffer for allocations
993
- // to avoid malloc() when possible, and a template for Ruby exception messages
994
- // if any error occurs.
995
- #define STACK_ENV_STACKBYTES 4096
996
- typedef struct {
997
- upb_arena *arena;
998
- upb_status status;
999
- const char* ruby_error_template;
1000
- char allocbuf[STACK_ENV_STACKBYTES];
1001
- } stackenv;
1002
-
1003
- static void stackenv_init(stackenv* se, const char* errmsg);
1004
- static void stackenv_uninit(stackenv* se);
1005
-
1006
- static void stackenv_init(stackenv* se, const char* errmsg) {
1007
- se->ruby_error_template = errmsg;
1008
- se->arena =
1009
- upb_arena_init(se->allocbuf, sizeof(se->allocbuf), &upb_alloc_global);
1010
- upb_status_clear(&se->status);
1011
- }
1012
-
1013
- static void stackenv_uninit(stackenv* se) {
1014
- upb_arena_free(se->arena);
1015
-
1016
- if (!upb_ok(&se->status)) {
1017
- // TODO(haberman): have a way to verify that this is actually a parse error,
1018
- // instead of just throwing "parse error" unconditionally.
1019
- VALUE errmsg = rb_str_new2(upb_status_errmsg(&se->status));
1020
- rb_raise(cParseError, se->ruby_error_template, errmsg);
1021
- }
1022
- }
1023
-
1024
- /*
1025
- * call-seq:
1026
- * MessageClass.decode(data) => message
1027
- *
1028
- * Decodes the given data (as a string containing bytes in protocol buffers wire
1029
- * format) under the interpretration given by this message class's definition
1030
- * and returns a message object with the corresponding field values.
1031
- */
1032
- VALUE Message_decode(VALUE klass, VALUE data) {
1033
- VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
1034
- Descriptor* desc = ruby_to_Descriptor(descriptor);
1035
- VALUE msgklass = Descriptor_msgclass(descriptor);
1036
- VALUE msg_rb;
1037
- MessageHeader* msg;
1038
-
1039
- if (TYPE(data) != T_STRING) {
1040
- rb_raise(rb_eArgError, "Expected string for binary protobuf data.");
1041
- }
1042
-
1043
- msg_rb = initialize_rb_class_with_no_args(msgklass);
1044
- TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
1045
-
1046
- {
1047
- const upb_pbdecodermethod* method = msgdef_decodermethod(desc);
1048
- const upb_handlers* h = upb_pbdecodermethod_desthandlers(method);
1049
- const upb_msgdef* m = upb_handlers_msgdef(h);
1050
- VALUE wrapper = Qnil;
1051
- void* ptr = msg;
1052
- stackenv se;
1053
- upb_sink sink;
1054
- upb_pbdecoder* decoder;
1055
- stackenv_init(&se, "Error occurred during parsing: %" PRIsVALUE);
1056
-
1057
- if (is_wrapper(m)) {
1058
- ptr = &wrapper;
1059
- }
1060
-
1061
- upb_sink_reset(&sink, h, ptr);
1062
- decoder = upb_pbdecoder_create(se.arena, method, sink, &se.status);
1063
- upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data),
1064
- upb_pbdecoder_input(decoder));
1065
-
1066
- stackenv_uninit(&se);
1067
-
1068
- if (is_wrapper(m)) {
1069
- msg_rb = ruby_wrapper_type(msgklass, wrapper);
1070
- }
1071
- }
1072
-
1073
- return msg_rb;
1074
- }
1075
-
1076
- /*
1077
- * call-seq:
1078
- * MessageClass.decode_json(data, options = {}) => message
1079
- *
1080
- * Decodes the given data (as a string containing bytes in protocol buffers wire
1081
- * format) under the interpretration given by this message class's definition
1082
- * and returns a message object with the corresponding field values.
1083
- *
1084
- * @param options [Hash] options for the decoder
1085
- * ignore_unknown_fields: set true to ignore unknown fields (default is to
1086
- * raise an error)
1087
- */
1088
- VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
1089
- VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
1090
- Descriptor* desc = ruby_to_Descriptor(descriptor);
1091
- VALUE msgklass = Descriptor_msgclass(descriptor);
1092
- VALUE msg_rb;
1093
- VALUE data = argv[0];
1094
- VALUE ignore_unknown_fields = Qfalse;
1095
- MessageHeader* msg;
1096
-
1097
- if (argc < 1 || argc > 2) {
1098
- rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
1099
- }
1100
-
1101
- if (argc == 2) {
1102
- VALUE hash_args = argv[1];
1103
- if (TYPE(hash_args) != T_HASH) {
1104
- rb_raise(rb_eArgError, "Expected hash arguments.");
1105
- }
1106
-
1107
- ignore_unknown_fields = rb_hash_lookup2(
1108
- hash_args, ID2SYM(rb_intern("ignore_unknown_fields")), Qfalse);
1109
- }
1110
-
1111
- if (TYPE(data) != T_STRING) {
1112
- rb_raise(rb_eArgError, "Expected string for JSON data.");
1113
- }
1114
-
1115
- // TODO(cfallin): Check and respect string encoding. If not UTF-8, we need to
1116
- // convert, because string handlers pass data directly to message string
1117
- // fields.
1118
-
1119
- msg_rb = initialize_rb_class_with_no_args(msgklass);
1120
- TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
1121
-
1122
- {
1123
- const upb_json_parsermethod* method = msgdef_jsonparsermethod(desc);
1124
- const upb_handlers* h = get_fill_handlers(desc);
1125
- const upb_msgdef* m = upb_handlers_msgdef(h);
1126
- stackenv se;
1127
- upb_sink sink;
1128
- upb_json_parser* parser;
1129
- DescriptorPool* pool = ruby_to_DescriptorPool(generated_pool);
1130
- stackenv_init(&se, "Error occurred during parsing: %" PRIsVALUE);
1131
-
1132
- if (is_wrapper(m)) {
1133
- rb_raise(
1134
- rb_eRuntimeError,
1135
- "Parsing a wrapper type from JSON at the top level does not work.");
1136
- }
1137
-
1138
- upb_sink_reset(&sink, h, msg);
1139
- parser = upb_json_parser_create(se.arena, method, pool->symtab, sink,
1140
- &se.status, RTEST(ignore_unknown_fields));
1141
- upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data),
1142
- upb_json_parser_input(parser));
1143
-
1144
- stackenv_uninit(&se);
1145
- }
1146
-
1147
- return msg_rb;
1148
- }
1149
-
1150
- // -----------------------------------------------------------------------------
1151
- // Serializing.
1152
- // -----------------------------------------------------------------------------
1153
-
1154
- /* msgvisitor *****************************************************************/
1155
-
1156
- static void putmsg(VALUE msg, const Descriptor* desc, upb_sink sink, int depth,
1157
- bool emit_defaults, bool is_json, bool open_msg);
1158
-
1159
- static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) {
1160
- upb_selector_t ret;
1161
- bool ok = upb_handlers_getselector(f, type, &ret);
1162
- UPB_ASSERT(ok);
1163
- return ret;
1164
- }
1165
-
1166
- static void putstr(VALUE str, const upb_fielddef *f, upb_sink sink) {
1167
- upb_sink subsink;
1168
-
1169
- if (str == Qnil) return;
1170
-
1171
- assert(BUILTIN_TYPE(str) == RUBY_T_STRING);
1172
-
1173
- // We should be guaranteed that the string has the correct encoding because
1174
- // we ensured this at assignment time and then froze the string.
1175
- if (upb_fielddef_type(f) == UPB_TYPE_STRING) {
1176
- assert(rb_enc_from_index(ENCODING_GET(str)) == kRubyStringUtf8Encoding);
1177
- } else {
1178
- assert(rb_enc_from_index(ENCODING_GET(str)) == kRubyString8bitEncoding);
1179
- }
1180
-
1181
- upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), RSTRING_LEN(str),
1182
- &subsink);
1183
- upb_sink_putstring(subsink, getsel(f, UPB_HANDLER_STRING), RSTRING_PTR(str),
1184
- RSTRING_LEN(str), NULL);
1185
- upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR));
1186
- }
1187
-
1188
- static void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink sink,
1189
- int depth, bool emit_defaults, bool is_json) {
1190
- upb_sink subsink;
1191
- VALUE descriptor;
1192
- Descriptor* subdesc;
1193
-
1194
- if (submsg == Qnil) return;
1195
-
1196
- descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned);
1197
- subdesc = ruby_to_Descriptor(descriptor);
1198
-
1199
- upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink);
1200
- putmsg(submsg, subdesc, subsink, depth + 1, emit_defaults, is_json, true);
1201
- upb_sink_endsubmsg(sink, subsink, getsel(f, UPB_HANDLER_ENDSUBMSG));
1202
- }
1203
-
1204
- static void putary(VALUE ary, const upb_fielddef* f, upb_sink sink, int depth,
1205
- bool emit_defaults, bool is_json) {
1206
- upb_sink subsink;
1207
- upb_fieldtype_t type = upb_fielddef_type(f);
1208
- upb_selector_t sel = 0;
1209
- int size;
1210
- int i;
1211
- VALUE type_class = ruby_to_RepeatedField(ary)->field_type_class;
1212
-
1213
- if (ary == Qnil) return;
1214
- if (!emit_defaults && NUM2INT(RepeatedField_length(ary)) == 0) return;
1215
-
1216
- size = NUM2INT(RepeatedField_length(ary));
1217
- if (size == 0 && !emit_defaults) return;
1218
-
1219
- upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
1220
-
1221
- if (upb_fielddef_isprimitive(f)) {
1222
- sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
1223
- }
1224
-
1225
- for (i = 0; i < size; i++) {
1226
- void* memory = RepeatedField_index_native(ary, i);
1227
- switch (type) {
1228
- #define T(upbtypeconst, upbtype, ctype) \
1229
- case upbtypeconst: \
1230
- upb_sink_put##upbtype(subsink, sel, *((ctype*)memory)); \
1231
- break;
1232
-
1233
- T(UPB_TYPE_FLOAT, float, float)
1234
- T(UPB_TYPE_DOUBLE, double, double)
1235
- T(UPB_TYPE_BOOL, bool, int8_t)
1236
- case UPB_TYPE_ENUM:
1237
- T(UPB_TYPE_INT32, int32, int32_t)
1238
- T(UPB_TYPE_UINT32, uint32, uint32_t)
1239
- T(UPB_TYPE_INT64, int64, int64_t)
1240
- T(UPB_TYPE_UINT64, uint64, uint64_t)
1241
-
1242
- case UPB_TYPE_STRING:
1243
- case UPB_TYPE_BYTES:
1244
- putstr(*((VALUE *)memory), f, subsink);
1245
- break;
1246
- case UPB_TYPE_MESSAGE: {
1247
- VALUE val = native_slot_get(UPB_TYPE_MESSAGE, type_class, memory);
1248
- putsubmsg(val, f, subsink, depth, emit_defaults, is_json);
1249
- break;
1250
- }
1251
-
1252
- #undef T
1253
-
1254
- }
1255
- }
1256
- upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
1257
- }
1258
-
1259
- static void put_ruby_value(VALUE value, const upb_fielddef* f, VALUE type_class,
1260
- int depth, upb_sink sink, bool emit_defaults,
1261
- bool is_json) {
1262
- upb_selector_t sel = 0;
1263
-
1264
- if (depth > ENCODE_MAX_NESTING) {
1265
- rb_raise(rb_eRuntimeError,
1266
- "Maximum recursion depth exceeded during encoding.");
1267
- }
1268
-
1269
- if (upb_fielddef_isprimitive(f)) {
1270
- sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
1271
- }
1272
-
1273
- switch (upb_fielddef_type(f)) {
1274
- case UPB_TYPE_INT32:
1275
- upb_sink_putint32(sink, sel, NUM2INT(value));
1276
- break;
1277
- case UPB_TYPE_INT64:
1278
- upb_sink_putint64(sink, sel, NUM2LL(value));
1279
- break;
1280
- case UPB_TYPE_UINT32:
1281
- upb_sink_putuint32(sink, sel, NUM2UINT(value));
1282
- break;
1283
- case UPB_TYPE_UINT64:
1284
- upb_sink_putuint64(sink, sel, NUM2ULL(value));
1285
- break;
1286
- case UPB_TYPE_FLOAT:
1287
- upb_sink_putfloat(sink, sel, NUM2DBL(value));
1288
- break;
1289
- case UPB_TYPE_DOUBLE:
1290
- upb_sink_putdouble(sink, sel, NUM2DBL(value));
1291
- break;
1292
- case UPB_TYPE_ENUM: {
1293
- if (TYPE(value) == T_SYMBOL) {
1294
- value = rb_funcall(type_class, rb_intern("resolve"), 1, value);
1295
- }
1296
- upb_sink_putint32(sink, sel, NUM2INT(value));
1297
- break;
1298
- }
1299
- case UPB_TYPE_BOOL:
1300
- upb_sink_putbool(sink, sel, value == Qtrue);
1301
- break;
1302
- case UPB_TYPE_STRING:
1303
- case UPB_TYPE_BYTES:
1304
- putstr(value, f, sink);
1305
- break;
1306
- case UPB_TYPE_MESSAGE:
1307
- putsubmsg(value, f, sink, depth, emit_defaults, is_json);
1308
- }
1309
- }
1310
-
1311
- static void putmap(VALUE map, const upb_fielddef* f, upb_sink sink, int depth,
1312
- bool emit_defaults, bool is_json) {
1313
- Map* self;
1314
- upb_sink subsink;
1315
- const upb_fielddef* key_field;
1316
- const upb_fielddef* value_field;
1317
- Map_iter it;
1318
-
1319
- if (map == Qnil) return;
1320
- if (!emit_defaults && Map_length(map) == 0) return;
1321
-
1322
- self = ruby_to_Map(map);
1323
-
1324
- upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
1325
-
1326
- assert(upb_fielddef_type(f) == UPB_TYPE_MESSAGE);
1327
- key_field = map_field_key(f);
1328
- value_field = map_field_value(f);
1329
-
1330
- for (Map_begin(map, &it); !Map_done(&it); Map_next(&it)) {
1331
- VALUE key = Map_iter_key(&it);
1332
- VALUE value = Map_iter_value(&it);
1333
- upb_status status;
1334
-
1335
- upb_sink entry_sink;
1336
- upb_sink_startsubmsg(subsink, getsel(f, UPB_HANDLER_STARTSUBMSG),
1337
- &entry_sink);
1338
- upb_sink_startmsg(entry_sink);
1339
-
1340
- put_ruby_value(key, key_field, Qnil, depth + 1, entry_sink, emit_defaults,
1341
- is_json);
1342
- put_ruby_value(value, value_field, self->value_type_class, depth + 1,
1343
- entry_sink, emit_defaults, is_json);
1344
-
1345
- upb_sink_endmsg(entry_sink, &status);
1346
- upb_sink_endsubmsg(subsink, entry_sink, getsel(f, UPB_HANDLER_ENDSUBMSG));
1347
- }
1348
-
1349
- upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
1350
- }
1351
-
1352
- static const upb_handlers* msgdef_json_serialize_handlers(
1353
- Descriptor* desc, bool preserve_proto_fieldnames);
1354
-
1355
- static void putjsonany(VALUE msg_rb, const Descriptor* desc, upb_sink sink,
1356
- int depth, bool emit_defaults) {
1357
- upb_status status;
1358
- MessageHeader* msg = NULL;
1359
- const upb_fielddef* type_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_TYPE);
1360
- const upb_fielddef* value_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_VALUE);
1361
-
1362
- size_t type_url_offset;
1363
- VALUE type_url_str_rb;
1364
- const upb_msgdef *payload_type = NULL;
1365
-
1366
- TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
1367
-
1368
- upb_sink_startmsg(sink);
1369
-
1370
- /* Handle type url */
1371
- type_url_offset = desc->layout->fields[upb_fielddef_index(type_field)].offset;
1372
- type_url_str_rb = DEREF(Message_data(msg), type_url_offset, VALUE);
1373
- if (RSTRING_LEN(type_url_str_rb) > 0) {
1374
- putstr(type_url_str_rb, type_field, sink);
1375
- }
1376
-
1377
- {
1378
- const char* type_url_str = RSTRING_PTR(type_url_str_rb);
1379
- size_t type_url_len = RSTRING_LEN(type_url_str_rb);
1380
- DescriptorPool* pool = ruby_to_DescriptorPool(generated_pool);
1381
-
1382
- if (type_url_len <= 20 ||
1383
- strncmp(type_url_str, "type.googleapis.com/", 20) != 0) {
1384
- rb_raise(rb_eRuntimeError, "Invalid type url: %s", type_url_str);
1385
- return;
1386
- }
1387
-
1388
- /* Resolve type url */
1389
- type_url_str += 20;
1390
- type_url_len -= 20;
1391
-
1392
- payload_type = upb_symtab_lookupmsg2(
1393
- pool->symtab, type_url_str, type_url_len);
1394
- if (payload_type == NULL) {
1395
- rb_raise(rb_eRuntimeError, "Unknown type: %s", type_url_str);
1396
- return;
1397
- }
1398
- }
1399
-
1400
- {
1401
- uint32_t value_offset;
1402
- VALUE value_str_rb;
1403
- size_t value_len;
1404
-
1405
- value_offset = desc->layout->fields[upb_fielddef_index(value_field)].offset;
1406
- value_str_rb = DEREF(Message_data(msg), value_offset, VALUE);
1407
- value_len = RSTRING_LEN(value_str_rb);
1408
-
1409
- if (value_len > 0) {
1410
- VALUE payload_desc_rb = get_msgdef_obj(generated_pool, payload_type);
1411
- Descriptor* payload_desc = ruby_to_Descriptor(payload_desc_rb);
1412
- VALUE payload_class = Descriptor_msgclass(payload_desc_rb);
1413
- upb_sink subsink;
1414
- bool is_wellknown;
1415
-
1416
- VALUE payload_msg_rb = Message_decode(payload_class, value_str_rb);
1417
-
1418
- is_wellknown =
1419
- upb_msgdef_wellknowntype(payload_desc->msgdef) !=
1420
- UPB_WELLKNOWN_UNSPECIFIED;
1421
- if (is_wellknown) {
1422
- upb_sink_startstr(sink, getsel(value_field, UPB_HANDLER_STARTSTR), 0,
1423
- &subsink);
1424
- }
1425
-
1426
- subsink.handlers =
1427
- msgdef_json_serialize_handlers(payload_desc, true);
1428
- subsink.closure = sink.closure;
1429
- putmsg(payload_msg_rb, payload_desc, subsink, depth, emit_defaults, true,
1430
- is_wellknown);
1431
- }
1432
- }
1433
-
1434
- upb_sink_endmsg(sink, &status);
1435
- }
1436
-
1437
- static void putjsonlistvalue(
1438
- VALUE msg_rb, const Descriptor* desc,
1439
- upb_sink sink, int depth, bool emit_defaults) {
1440
- upb_status status;
1441
- upb_sink subsink;
1442
- MessageHeader* msg = NULL;
1443
- const upb_fielddef* f = upb_msgdef_itof(desc->msgdef, 1);
1444
- uint32_t offset =
1445
- desc->layout->fields[upb_fielddef_index(f)].offset +
1446
- sizeof(MessageHeader);
1447
- VALUE ary;
1448
-
1449
- TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
1450
-
1451
- upb_sink_startmsg(sink);
1452
-
1453
- ary = DEREF(msg, offset, VALUE);
1454
-
1455
- if (ary == Qnil || RepeatedField_size(ary) == 0) {
1456
- upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
1457
- upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
1458
- } else {
1459
- putary(ary, f, sink, depth, emit_defaults, true);
1460
- }
1461
-
1462
- upb_sink_endmsg(sink, &status);
1463
- }
1464
-
1465
- static void putmsg(VALUE msg_rb, const Descriptor* desc,
1466
- upb_sink sink, int depth, bool emit_defaults,
1467
- bool is_json, bool open_msg) {
1468
- MessageHeader* msg;
1469
- upb_msg_field_iter i;
1470
- upb_status status;
1471
- bool json_wrapper = is_wrapper(desc->msgdef) && is_json;
1472
-
1473
- if (is_json &&
1474
- upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_ANY) {
1475
- putjsonany(msg_rb, desc, sink, depth, emit_defaults);
1476
- return;
1477
- }
1478
-
1479
- if (is_json &&
1480
- upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_LISTVALUE) {
1481
- putjsonlistvalue(msg_rb, desc, sink, depth, emit_defaults);
1482
- return;
1483
- }
1484
-
1485
- if (open_msg) {
1486
- upb_sink_startmsg(sink);
1487
- }
1488
-
1489
- // Protect against cycles (possible because users may freely reassign message
1490
- // and repeated fields) by imposing a maximum recursion depth.
1491
- if (depth > ENCODE_MAX_NESTING) {
1492
- rb_raise(rb_eRuntimeError,
1493
- "Maximum recursion depth exceeded during encoding.");
1494
- }
1495
-
1496
- TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
1497
-
1498
- if (desc != msg->descriptor) {
1499
- rb_raise(rb_eArgError,
1500
- "The type of given msg is '%s', expect '%s'.",
1501
- upb_msgdef_fullname(msg->descriptor->msgdef),
1502
- upb_msgdef_fullname(desc->msgdef));
1503
- }
1504
-
1505
- for (upb_msg_field_begin(&i, desc->msgdef);
1506
- !upb_msg_field_done(&i);
1507
- upb_msg_field_next(&i)) {
1508
- upb_fielddef *f = upb_msg_iter_field(&i);
1509
- const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(f);
1510
- bool is_matching_oneof = false;
1511
- uint32_t offset =
1512
- desc->layout->fields[upb_fielddef_index(f)].offset +
1513
- sizeof(MessageHeader);
1514
-
1515
- if (oneof) {
1516
- uint32_t oneof_case =
1517
- slot_read_oneof_case(desc->layout, Message_data(msg), oneof);
1518
- // For a oneof, check that this field is actually present -- skip all the
1519
- // below if not.
1520
- if (oneof_case != upb_fielddef_number(f)) {
1521
- continue;
1522
- }
1523
- // Otherwise, fall through to the appropriate singular-field handler
1524
- // below.
1525
- is_matching_oneof = true;
1526
- }
1527
-
1528
- if (is_map_field(f)) {
1529
- VALUE map = DEREF(msg, offset, VALUE);
1530
- if (map != Qnil || emit_defaults) {
1531
- putmap(map, f, sink, depth, emit_defaults, is_json);
1532
- }
1533
- } else if (upb_fielddef_isseq(f)) {
1534
- VALUE ary = DEREF(msg, offset, VALUE);
1535
- if (ary != Qnil) {
1536
- putary(ary, f, sink, depth, emit_defaults, is_json);
1537
- }
1538
- } else if (upb_fielddef_isstring(f)) {
1539
- VALUE str = DEREF(msg, offset, VALUE);
1540
- bool is_default = false;
1541
-
1542
- if (upb_msgdef_syntax(desc->msgdef) == UPB_SYNTAX_PROTO2) {
1543
- is_default = layout_has(desc->layout, Message_data(msg), f) == Qfalse;
1544
- } else if (upb_msgdef_syntax(desc->msgdef) == UPB_SYNTAX_PROTO3) {
1545
- is_default = RSTRING_LEN(str) == 0;
1546
- }
1547
-
1548
- if (is_matching_oneof || emit_defaults || !is_default || json_wrapper) {
1549
- putstr(str, f, sink);
1550
- }
1551
- } else if (upb_fielddef_issubmsg(f)) {
1552
- // OPT: could try to avoid the layout_get() (which will expand lazy
1553
- // wrappers).
1554
- VALUE val = layout_get(desc->layout, Message_data(msg), f);
1555
- putsubmsg(val, f, sink, depth, emit_defaults, is_json);
1556
- } else {
1557
- upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
1558
-
1559
- #define T(upbtypeconst, upbtype, ctype, default_value) \
1560
- case upbtypeconst: { \
1561
- ctype value = DEREF(msg, offset, ctype); \
1562
- bool is_default = false; \
1563
- if (upb_fielddef_haspresence(f)) { \
1564
- is_default = layout_has(desc->layout, Message_data(msg), f) == Qfalse; \
1565
- } else if (upb_msgdef_syntax(desc->msgdef) == UPB_SYNTAX_PROTO3) { \
1566
- is_default = default_value == value; \
1567
- } \
1568
- if (is_matching_oneof || emit_defaults || !is_default || json_wrapper) { \
1569
- upb_sink_put##upbtype(sink, sel, value); \
1570
- } \
1571
- } break;
1572
-
1573
- switch (upb_fielddef_type(f)) {
1574
- T(UPB_TYPE_FLOAT, float, float, 0.0)
1575
- T(UPB_TYPE_DOUBLE, double, double, 0.0)
1576
- T(UPB_TYPE_BOOL, bool, uint8_t, 0)
1577
- case UPB_TYPE_ENUM:
1578
- T(UPB_TYPE_INT32, int32, int32_t, 0)
1579
- T(UPB_TYPE_UINT32, uint32, uint32_t, 0)
1580
- T(UPB_TYPE_INT64, int64, int64_t, 0)
1581
- T(UPB_TYPE_UINT64, uint64, uint64_t, 0)
1582
-
1583
- case UPB_TYPE_STRING:
1584
- case UPB_TYPE_BYTES:
1585
- case UPB_TYPE_MESSAGE: rb_raise(rb_eRuntimeError, "Internal error.");
1586
- }
1587
-
1588
- #undef T
1589
- }
1590
- }
1591
-
1592
- {
1593
- stringsink* unknown = msg->unknown_fields;
1594
- if (unknown != NULL) {
1595
- upb_sink_putunknown(sink, unknown->ptr, unknown->len);
1596
- }
1597
- }
1598
-
1599
- if (open_msg) {
1600
- upb_sink_endmsg(sink, &status);
1601
- }
1602
- }
1603
-
1604
- /*
1605
- * call-seq:
1606
- * MessageClass.encode(msg) => bytes
1607
- *
1608
- * Encodes the given message object to its serialized form in protocol buffers
1609
- * wire format.
1610
- */
1611
- VALUE Message_encode(VALUE klass, VALUE msg_rb) {
1612
- VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
1613
- Descriptor* desc = ruby_to_Descriptor(descriptor);
1614
-
1615
- stringsink sink;
1616
- stringsink_init(&sink);
1617
-
1618
- {
1619
- const upb_handlers* serialize_handlers =
1620
- msgdef_pb_serialize_handlers(desc);
1621
-
1622
- stackenv se;
1623
- upb_pb_encoder* encoder;
1624
- VALUE ret;
1625
-
1626
- stackenv_init(&se, "Error occurred during encoding: %" PRIsVALUE);
1627
- encoder = upb_pb_encoder_create(se.arena, serialize_handlers, sink.sink);
1628
-
1629
- putmsg(msg_rb, desc, upb_pb_encoder_input(encoder), 0, false, false, true);
1630
-
1631
- ret = rb_str_new(sink.ptr, sink.len);
1632
-
1633
- stackenv_uninit(&se);
1634
- stringsink_uninit(&sink);
1635
-
1636
- return ret;
1637
- }
1638
- }
1639
-
1640
- /*
1641
- * call-seq:
1642
- * MessageClass.encode_json(msg, options = {}) => json_string
1643
- *
1644
- * Encodes the given message object into its serialized JSON representation.
1645
- * @param options [Hash] options for the decoder
1646
- * preserve_proto_fieldnames: set true to use original fieldnames (default is to camelCase)
1647
- * emit_defaults: set true to emit 0/false values (default is to omit them)
1648
- */
1649
- VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
1650
- VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
1651
- Descriptor* desc = ruby_to_Descriptor(descriptor);
1652
- VALUE msg_rb;
1653
- VALUE preserve_proto_fieldnames = Qfalse;
1654
- VALUE emit_defaults = Qfalse;
1655
- stringsink sink;
1656
-
1657
- if (argc < 1 || argc > 2) {
1658
- rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
1659
- }
1660
-
1661
- msg_rb = argv[0];
1662
-
1663
- if (argc == 2) {
1664
- VALUE hash_args = argv[1];
1665
- if (TYPE(hash_args) != T_HASH) {
1666
- rb_raise(rb_eArgError, "Expected hash arguments.");
1667
- }
1668
- preserve_proto_fieldnames = rb_hash_lookup2(
1669
- hash_args, ID2SYM(rb_intern("preserve_proto_fieldnames")), Qfalse);
1670
-
1671
- emit_defaults = rb_hash_lookup2(
1672
- hash_args, ID2SYM(rb_intern("emit_defaults")), Qfalse);
1673
- }
1674
-
1675
- stringsink_init(&sink);
1676
-
1677
- {
1678
- const upb_handlers* serialize_handlers =
1679
- msgdef_json_serialize_handlers(desc, RTEST(preserve_proto_fieldnames));
1680
- upb_json_printer* printer;
1681
- stackenv se;
1682
- VALUE ret;
1683
-
1684
- stackenv_init(&se, "Error occurred during encoding: %" PRIsVALUE);
1685
- printer = upb_json_printer_create(se.arena, serialize_handlers, sink.sink);
1686
-
1687
- putmsg(msg_rb, desc, upb_json_printer_input(printer), 0,
1688
- RTEST(emit_defaults), true, true);
1689
-
1690
- ret = rb_enc_str_new(sink.ptr, sink.len, rb_utf8_encoding());
1691
-
1692
- stackenv_uninit(&se);
1693
- stringsink_uninit(&sink);
1694
-
1695
- return ret;
1696
- }
1697
- }
1698
-
1699
- static void discard_unknown(VALUE msg_rb, const Descriptor* desc) {
1700
- MessageHeader* msg;
1701
- upb_msg_field_iter it;
1702
-
1703
- TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
1704
-
1705
- {
1706
- stringsink* unknown = msg->unknown_fields;
1707
- if (unknown != NULL) {
1708
- stringsink_uninit(unknown);
1709
- msg->unknown_fields = NULL;
1710
- }
1711
- }
1712
-
1713
- for (upb_msg_field_begin(&it, desc->msgdef);
1714
- !upb_msg_field_done(&it);
1715
- upb_msg_field_next(&it)) {
1716
- upb_fielddef *f = upb_msg_iter_field(&it);
1717
- const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(f);
1718
- uint32_t offset =
1719
- desc->layout->fields[upb_fielddef_index(f)].offset +
1720
- sizeof(MessageHeader);
1721
-
1722
- if (oneof) {
1723
- uint32_t oneof_case =
1724
- slot_read_oneof_case(desc->layout, Message_data(msg), oneof);
1725
- // For a oneof, check that this field is actually present -- skip all the
1726
- // below if not.
1727
- if (oneof_case != upb_fielddef_number(f)) {
1728
- continue;
1729
- }
1730
- // Otherwise, fall through to the appropriate singular-field handler
1731
- // below.
1732
- }
1733
-
1734
- if (!upb_fielddef_issubmsg(f)) {
1735
- continue;
1736
- }
1737
-
1738
- if (is_map_field(f)) {
1739
- VALUE map;
1740
- Map_iter map_it;
1741
-
1742
- if (!upb_fielddef_issubmsg(map_field_value(f))) continue;
1743
- map = DEREF(msg, offset, VALUE);
1744
- if (map == Qnil) continue;
1745
- for (Map_begin(map, &map_it); !Map_done(&map_it); Map_next(&map_it)) {
1746
- VALUE submsg = Map_iter_value(&map_it);
1747
- VALUE descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned);
1748
- const Descriptor* subdesc = ruby_to_Descriptor(descriptor);
1749
- discard_unknown(submsg, subdesc);
1750
- }
1751
- } else if (upb_fielddef_isseq(f)) {
1752
- VALUE ary = DEREF(msg, offset, VALUE);
1753
- int size;
1754
- int i;
1755
-
1756
- if (ary == Qnil) continue;
1757
- size = NUM2INT(RepeatedField_length(ary));
1758
- for (i = 0; i < size; i++) {
1759
- void* memory = RepeatedField_index_native(ary, i);
1760
- VALUE submsg = *((VALUE *)memory);
1761
- VALUE descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned);
1762
- const Descriptor* subdesc = ruby_to_Descriptor(descriptor);
1763
- discard_unknown(submsg, subdesc);
1764
- }
1765
- } else {
1766
- VALUE submsg = DEREF(msg, offset, VALUE);
1767
- VALUE descriptor;
1768
- const Descriptor* subdesc;
1769
-
1770
- if (submsg == Qnil) continue;
1771
- descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned);
1772
- subdesc = ruby_to_Descriptor(descriptor);
1773
- discard_unknown(submsg, subdesc);
1774
- }
1775
- }
1776
- }
1777
-
1778
- /*
1779
- * call-seq:
1780
- * Google::Protobuf.discard_unknown(msg)
1781
- *
1782
- * Discard unknown fields in the given message object and recursively discard
1783
- * unknown fields in submessages.
1784
- */
1785
- VALUE Google_Protobuf_discard_unknown(VALUE self, VALUE msg_rb) {
1786
- VALUE klass = CLASS_OF(msg_rb);
1787
- VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
1788
- Descriptor* desc = ruby_to_Descriptor(descriptor);
1789
- if (klass == cRepeatedField || klass == cMap) {
1790
- rb_raise(rb_eArgError, "Expected proto msg for discard unknown.");
1791
- } else {
1792
- discard_unknown(msg_rb, desc);
1793
- }
1794
- return Qnil;
1795
- }