sparsam 0.2.5 → 0.2.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c47d8f62e5244736a0f3e8e0e02f1f0104d3fb41982da0ca598940d2bfb6bc52
4
- data.tar.gz: fe43b9eb4b3167adec9d435269a14ab90b08f4518f9c242875555a144fe3a689
3
+ metadata.gz: 5df1feed622f050f564cd17dd088ae575a544b1b26511f19b2bb8cec3d46d34a
4
+ data.tar.gz: 85622057c2fd20ef6af4e325a62a61858f6c0d73d8575b3a42cbf3871c0df86b
5
5
  SHA512:
6
- metadata.gz: a62b9bc043e205badb26495651e918b6ff14c6ab3574b2fbf5cbdc00ca61cd1f1bbd7f44ea18ebd40673bde1fffbff57e981cd3db532ffba43451b7e8d71e3b5
7
- data.tar.gz: 6d6454f006da2089124019b176d5e916b2a1ff77ff67731601e18cf64275f224afc234b9bd27a5d10ff687992163743bcf804b153cc00526d51155786eb77171
6
+ metadata.gz: f872a492fd9870cac0a19bd58fb458f02a7d0bc619e0a892aa7a6415c2a2d91d161634f390167f33ee67ed870ba42bafea5678f616f40d413b6e2e23c7e181f7
7
+ data.tar.gz: bbb8fd020a8bced074581523ee6bab24669ad88f244797957deac3b774a57d3c00425e6975ae9ba40925c04b56e1e91f6ff49b5bedec7bfd0b690cc3bfc18a0d
@@ -1,7 +1,7 @@
1
- #include "stdio.h"
2
1
  #include <ruby.h>
3
2
  #include <ruby/intern.h>
4
3
  #include "serializer.h"
4
+ #include "stdio.h"
5
5
 
6
6
  VALUE Sparsam = Qnil;
7
7
  VALUE static_zero_array;
@@ -11,10 +11,10 @@ ID intern_for_DEFAULT_VALUES;
11
11
  ID intern_for_assign_defaults;
12
12
  ID intern_for_assign_from_arg;
13
13
 
14
- static void deallocate(void *data) { serializer_free(data); }
14
+ static void deallocate(void* data) { serializer_free(data); }
15
15
 
16
16
  static VALUE allocate(VALUE klass) {
17
- void *data = serializer_create();
17
+ void* data = serializer_create();
18
18
  return Data_Wrap_Struct(klass, NULL, deallocate, data);
19
19
  }
20
20
 
@@ -24,8 +24,8 @@ static VALUE sparsam_init_bang(VALUE self) {
24
24
  }
25
25
 
26
26
  static VALUE initialize(VALUE self, VALUE type_arg, VALUE str_arg) {
27
- void *self_data = NULL;
28
- void *input_string = NULL;
27
+ void* self_data = NULL;
28
+ void* input_string = NULL;
29
29
 
30
30
  Check_Type(type_arg, T_FIXNUM);
31
31
  int prot = NUM2INT(type_arg);
@@ -38,7 +38,7 @@ static VALUE initialize(VALUE self, VALUE type_arg, VALUE str_arg) {
38
38
  memcpy(input_string, StringValuePtr(str_arg), len);
39
39
  }
40
40
 
41
- Data_Get_Struct(self, void *, self_data);
41
+ Data_Get_Struct(self, void*, self_data);
42
42
  serializer_init(self_data, prot, input_string, len);
43
43
 
44
44
  return self;
@@ -46,7 +46,8 @@ static VALUE initialize(VALUE self, VALUE type_arg, VALUE str_arg) {
46
46
 
47
47
  VALUE sparsam_struct_initialize(int argc, VALUE* argv, VALUE self) {
48
48
  if (argc > 1) {
49
- rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 0..1)", argc);
49
+ rb_raise(rb_eArgError,
50
+ "wrong number of arguments (given %d, expected 0..1)", argc);
50
51
  }
51
52
 
52
53
  VALUE defaults = rb_const_get(rb_obj_class(self), intern_for_DEFAULT_VALUES);
@@ -70,14 +71,16 @@ void Init_sparsam_native() {
70
71
  Sparsam = rb_define_module("Sparsam");
71
72
  rb_define_singleton_method(Sparsam, "init!", sparsam_init_bang, 0);
72
73
  rb_define_singleton_method(Sparsam, "cache_fields", cache_fields, 1);
73
- VALUE SparsamSerializer = rb_define_class_under(Sparsam, "Serializer", rb_cObject);
74
+ VALUE SparsamSerializer =
75
+ rb_define_class_under(Sparsam, "Serializer", rb_cObject);
74
76
  SparsamNativeError =
75
77
  rb_define_class_under(Sparsam, "Exception", rb_eStandardError);
76
78
  rb_define_alloc_func(SparsamSerializer, allocate);
77
79
  rb_define_method(SparsamSerializer, "initialize", initialize, 2);
78
80
  rb_define_method(SparsamSerializer, "serialize", serializer_writeStruct, 2);
79
81
  rb_define_method(SparsamSerializer, "deserialize", serializer_readStruct, 1);
80
- rb_define_method(SparsamSerializer, "deserializeUnion", serializer_readUnion, 1);
82
+ rb_define_method(SparsamSerializer, "deserializeUnion", serializer_readUnion,
83
+ 1);
81
84
  rb_define_const(Sparsam, "CompactProtocol", INT2FIX(compact));
82
85
  rb_define_const(Sparsam, "BinaryProtocol", INT2FIX(binary));
83
86
  rb_define_const(Sparsam, "UNION", INT2FIX(t_union));
@@ -90,8 +93,9 @@ void Init_sparsam_native() {
90
93
  intern_for_assign_defaults = rb_intern("assign_defaults");
91
94
  intern_for_assign_from_arg = rb_intern("assign_from_arg");
92
95
 
93
-
94
- VALUE SparsamStructInitialization = rb_define_module_under(Sparsam, "StructInitialization");
95
- rb_define_method(SparsamStructInitialization, "initialize", sparsam_struct_initialize, -1);
96
+ VALUE SparsamStructInitialization =
97
+ rb_define_module_under(Sparsam, "StructInitialization");
98
+ rb_define_method(SparsamStructInitialization, "initialize",
99
+ sparsam_struct_initialize, -1);
96
100
  initialize_constants();
97
101
  }
@@ -2,15 +2,15 @@ extern "C" {
2
2
  #include <ruby.h>
3
3
  #include <ruby/intern.h>
4
4
  }
5
- #include "serializer.h"
6
- #include <functional>
7
- #include <map>
8
5
  #include <ruby/encoding.h>
9
6
  #include <stdio.h>
10
7
  #include <thrift/protocol/TBinaryProtocol.h>
11
8
  #include <thrift/protocol/TCompactProtocol.h>
12
9
  #include <boost/make_shared.hpp>
10
+ #include <functional>
11
+ #include <map>
13
12
  #include <vector>
13
+ #include "serializer.h"
14
14
 
15
15
  using namespace std;
16
16
  using ::apache::thrift::protocol::TType;
@@ -48,7 +48,7 @@ VALUE SparsamUnknownTypeException;
48
48
 
49
49
  VALUE SetClass;
50
50
 
51
- KlassFieldsCache klassCache; // consider the memory leaked.
51
+ KlassFieldsCache klassCache; // consider the memory leaked.
52
52
  std::unordered_set<VALUE> unions;
53
53
 
54
54
  void *serializer_create() { return (void *)(new ThriftSerializer()); }
@@ -83,8 +83,10 @@ void initialize_constants() {
83
83
 
84
84
  void initialize_runtime_constants() {
85
85
  klass_for_union = rb_const_get_at(Sparsam, rb_intern("Union"));
86
- SparsamMissingMandatory = rb_const_get_at(Sparsam, rb_intern("MissingMandatory"));
87
- SparsamTypeMismatchError = rb_const_get_at(Sparsam, rb_intern("TypeMismatch"));
86
+ SparsamMissingMandatory =
87
+ rb_const_get_at(Sparsam, rb_intern("MissingMandatory"));
88
+ SparsamTypeMismatchError =
89
+ rb_const_get_at(Sparsam, rb_intern("TypeMismatch"));
88
90
  SparsamUnionException = rb_const_get_at(Sparsam, rb_intern("UnionException"));
89
91
  SparsamUnknownTypeException =
90
92
  rb_const_get_at(Sparsam, rb_intern("UnknownTypeException"));
@@ -93,19 +95,16 @@ void initialize_runtime_constants() {
93
95
 
94
96
  void serializer_init(void *serializer, int protocol, void *str_arg1,
95
97
  uint32_t len) {
96
- using ::boost::shared_ptr;
97
- using ::apache::thrift::protocol::TProtocol;
98
98
  using ::apache::thrift::protocol::TBinaryProtocol;
99
99
  using ::apache::thrift::protocol::TCompactProtocol;
100
+ using ::apache::thrift::protocol::TProtocol;
101
+ using ::boost::shared_ptr;
100
102
 
101
103
  ThriftSerializer *ts = (ThriftSerializer *)(serializer);
102
104
  shared_ptr<TMemoryBuffer> strBuffer;
103
105
  if (str_arg1 != NULL) {
104
106
  strBuffer = boost::make_shared<TMemoryBuffer>(
105
- (uint8_t *)str_arg1,
106
- len,
107
- TMemoryBuffer::TAKE_OWNERSHIP
108
- );
107
+ (uint8_t *)str_arg1, len, TMemoryBuffer::TAKE_OWNERSHIP);
109
108
  } else {
110
109
  strBuffer = boost::make_shared<TMemoryBuffer>();
111
110
  }
@@ -120,21 +119,19 @@ void serializer_init(void *serializer, int protocol, void *str_arg1,
120
119
  ts->tmb = strBuffer;
121
120
  }
122
121
 
123
- #define get_ts() \
124
- void *self_data = NULL; \
125
- Data_Get_Struct(self, void, self_data); \
122
+ #define get_ts() \
123
+ void *self_data = NULL; \
124
+ Data_Get_Struct(self, void, self_data); \
126
125
  ThriftSerializer *ts = (ThriftSerializer *)(self_data);
127
126
 
128
127
  #define watch_for_texcept() try {
129
-
130
- #define catch_thrift_and_reraise() \
131
- } \
132
- catch (::apache::thrift::TException e) { \
133
- rb_raise(SparsamNativeError, "%s", e.what()); \
134
- return Qnil; \
128
+ #define catch_thrift_and_reraise() \
129
+ } \
130
+ catch (::apache::thrift::TException e) { \
131
+ rb_raise(SparsamNativeError, "%s", e.what()); \
132
+ return Qnil; \
135
133
  }
136
134
 
137
-
138
135
  static inline VALUE make_ruby_string(const string &val) {
139
136
  return rb_enc_str_new(val.c_str(), val.size(), rb_utf8_encoding());
140
137
  }
@@ -143,43 +140,58 @@ static inline VALUE make_ruby_binary(const string &val) {
143
140
  return rb_str_new(val.c_str(), val.size());
144
141
  }
145
142
 
146
- static void raise_exc_with_struct_and_field_names(
147
- VALUE exc_class,
148
- VALUE msg_prefix,
149
- VALUE outer_struct_class,
150
- VALUE field_sym) {
143
+ static void raise_exc_with_struct_and_field_names(VALUE exc_class,
144
+ VALUE msg_prefix,
145
+ VALUE outer_struct_class,
146
+ VALUE field_sym) {
151
147
  VALUE struct_name = rb_class_name(outer_struct_class);
152
148
  VALUE field_name = rb_sym_to_s(field_sym);
153
149
 
154
- VALUE msg = rb_sprintf("%s (in %s#%s)",
155
- RSTRING_PTR(msg_prefix),
156
- RSTRING_PTR(struct_name),
157
- RSTRING_PTR(field_name));
150
+ VALUE msg = rb_sprintf("%s (in %s#%s)", RSTRING_PTR(msg_prefix),
151
+ RSTRING_PTR(struct_name), RSTRING_PTR(field_name));
158
152
  VALUE args[3] = {msg, struct_name, field_name};
159
153
  VALUE e = rb_class_new_instance(3, args, exc_class);
160
154
  rb_exc_raise(e);
161
155
  }
162
156
 
163
- static void raise_type_mismatch(VALUE outer_struct, VALUE field_sym) {
164
- raise_exc_with_struct_and_field_names(
165
- SparsamTypeMismatchError,
166
- rb_str_new2("Mismatched type"),
167
- CLASS_OF(outer_struct),
168
- field_sym);
157
+ static void raise_type_mismatch(VALUE outer_struct, VALUE field_sym,
158
+ const char *expected, VALUE actual) {
159
+ VALUE actual_name = rb_class_name(CLASS_OF(actual));
160
+ VALUE msg = rb_sprintf(
161
+ "Mismatched type (expected to be compatible with: %s, found: %s)",
162
+ expected, RSTRING_PTR(actual_name));
163
+
164
+ raise_exc_with_struct_and_field_names(SparsamTypeMismatchError, msg,
165
+ CLASS_OF(outer_struct), field_sym);
166
+ }
167
+
168
+ static void raise_type_mismatch(VALUE outer_struct, VALUE field_sym, int ttype,
169
+ VALUE actual) {
170
+ raise_type_mismatch(outer_struct, field_sym, TTypeName((size_t)ttype).c_str(),
171
+ actual);
169
172
  }
170
173
 
171
- static inline long raise_type_mismatch_as_value(VALUE outer_struct, VALUE field_sym) {
172
- raise_type_mismatch(outer_struct, field_sym);
174
+ static void raise_type_mismatch(VALUE outer_struct, VALUE field_sym,
175
+ VALUE klass, VALUE actual) {
176
+ VALUE expected_name = rb_class_name(klass);
177
+ raise_type_mismatch(outer_struct, field_sym, RSTRING_PTR(expected_name),
178
+ actual);
179
+ }
180
+
181
+ static inline long raise_type_mismatch_as_value(VALUE outer_struct,
182
+ VALUE field_sym, int ttype,
183
+ VALUE actual) {
184
+ raise_type_mismatch(outer_struct, field_sym, ttype, actual);
173
185
  return 0;
174
186
  }
175
187
 
176
- static inline void Sparsam_Check_Type(VALUE x, int t, VALUE outer_struct, VALUE field_sym) {
188
+ static inline void Sparsam_Check_Type(VALUE x, int t, VALUE outer_struct,
189
+ VALUE field_sym) {
177
190
  if (!(RB_TYPE_P(x, t))) {
178
- raise_type_mismatch(outer_struct, field_sym);
191
+ raise_type_mismatch(outer_struct, field_sym, t, x);
179
192
  }
180
193
  }
181
194
 
182
-
183
195
  static inline VALUE make_ruby_bool(bool val) { return val ? Qtrue : Qfalse; }
184
196
 
185
197
  void ThriftSerializer::skip_n_type(uint32_t n, TType ttype) {
@@ -198,18 +210,17 @@ void ThriftSerializer::skip_n_pair(uint32_t n, TType type_a, TType type_b) {
198
210
  // Blatantly copied protobuf's design
199
211
  // https://git.io/vHuUn
200
212
  // CONVERT is new here, because we're targeting ruby
201
- #define HANDLE_TYPE(TYPE, CPPTYPE, READ_METHOD, CONVERT) \
202
- case protocol::T_##TYPE: { \
203
- CPPTYPE value; \
204
- this->tprot->read##READ_METHOD(value); \
205
- ret = CONVERT(value); \
206
- break; \
213
+ #define HANDLE_TYPE(TYPE, CPPTYPE, READ_METHOD, CONVERT) \
214
+ case protocol::T_##TYPE: { \
215
+ CPPTYPE value; \
216
+ this->tprot->read##READ_METHOD(value); \
217
+ ret = CONVERT(value); \
218
+ break; \
207
219
  }
208
220
 
209
221
  VALUE ThriftSerializer::readAny(TType ttype, FieldInfo *field_info) {
210
222
  VALUE ret = Qnil;
211
223
  switch (ttype) {
212
-
213
224
  // Handle all the non-container types by marco
214
225
  HANDLE_TYPE(I16, int16_t, I16, INT2FIX)
215
226
  HANDLE_TYPE(I32, int32_t, I32, INT2FIX)
@@ -218,99 +229,100 @@ VALUE ThriftSerializer::readAny(TType ttype, FieldInfo *field_info) {
218
229
  HANDLE_TYPE(DOUBLE, double, Double, DBL2NUM)
219
230
  HANDLE_TYPE(BYTE, int8_t, Byte, INT2FIX)
220
231
 
221
- case protocol::T_STRING: {
222
- string value;
223
- if (field_info->isBinaryString) { // if (field_info[:binary])
224
- this->tprot->readBinary(value);
225
- ret = make_ruby_binary(value);
226
- } else {
227
- this->tprot->readString(value);
228
- ret = make_ruby_string(value);
232
+ case protocol::T_STRING: {
233
+ string value;
234
+ if (field_info->isBinaryString) { // if (field_info[:binary])
235
+ this->tprot->readBinary(value);
236
+ ret = make_ruby_binary(value);
237
+ } else {
238
+ this->tprot->readString(value);
239
+ ret = make_ruby_string(value);
240
+ }
241
+ break;
229
242
  }
230
- break;
231
- }
232
243
 
233
- case protocol::T_LIST: {
234
- TType element_type;
235
- uint32_t size;
244
+ case protocol::T_LIST: {
245
+ TType element_type;
246
+ uint32_t size;
236
247
 
237
- this->tprot->readListBegin(element_type, size);
238
- if (field_info->elementType == NULL ||
239
- element_type != field_info->elementType->ftype) {
240
- this->skip_n_type(size, element_type);
241
- break;
242
- }
243
- ret = rb_ary_new2(size);
248
+ this->tprot->readListBegin(element_type, size);
249
+ if (field_info->elementType == NULL ||
250
+ element_type != field_info->elementType->ftype) {
251
+ this->skip_n_type(size, element_type);
252
+ break;
253
+ }
254
+ ret = rb_ary_new2(size);
244
255
 
245
- for (uint32_t i = 0; i < size; i++) {
246
- rb_ary_store(ret, i,
247
- this->readAny(element_type, field_info->elementType));
256
+ for (uint32_t i = 0; i < size; i++) {
257
+ rb_ary_store(ret, i,
258
+ this->readAny(element_type, field_info->elementType));
259
+ }
260
+ this->tprot->readListEnd();
261
+
262
+ break;
248
263
  }
249
- this->tprot->readListEnd();
250
264
 
251
- break;
252
- }
265
+ case protocol::T_SET: {
266
+ TType element_type;
267
+ uint32_t size;
253
268
 
254
- case protocol::T_SET: {
255
- TType element_type;
256
- uint32_t size;
269
+ this->tprot->readSetBegin(element_type, size);
270
+ if (field_info->elementType == NULL ||
271
+ element_type != field_info->elementType->ftype) {
272
+ this->skip_n_type(size, element_type);
273
+ break;
274
+ }
275
+ VALUE ary = rb_ary_new2(size);
257
276
 
258
- this->tprot->readSetBegin(element_type, size);
259
- if (field_info->elementType == NULL ||
260
- element_type != field_info->elementType->ftype) {
261
- this->skip_n_type(size, element_type);
277
+ for (uint32_t i = 0; i < size; i++) {
278
+ rb_ary_store(ary, i,
279
+ this->readAny(element_type, field_info->elementType));
280
+ }
281
+ ret = rb_class_new_instance(1, &ary, klass_for_set);
282
+ this->tprot->readSetEnd();
262
283
  break;
263
284
  }
264
- VALUE ary = rb_ary_new2(size);
265
285
 
266
- for (uint32_t i = 0; i < size; i++) {
267
- rb_ary_store(ary, i,
268
- this->readAny(element_type, field_info->elementType));
286
+ case protocol::T_STRUCT: {
287
+ string cname;
288
+ this->tprot->readStructBegin(cname);
289
+ if (unions.count(field_info->klass) == 1) {
290
+ ret = this->readUnion(field_info->klass);
291
+ } else {
292
+ ret = this->readStruct(field_info->klass);
293
+ }
294
+ this->tprot->readStructEnd();
295
+ break;
269
296
  }
270
- ret = rb_class_new_instance(1, &ary, klass_for_set);
271
- this->tprot->readSetEnd();
272
- break;
273
- }
274
297
 
275
- case protocol::T_STRUCT: {
276
- string cname;
277
- this->tprot->readStructBegin(cname);
278
- if (unions.count(field_info->klass) == 1) {
279
- ret = this->readUnion(field_info->klass);
280
- } else {
281
- ret = this->readStruct(field_info->klass);
282
- }
283
- this->tprot->readStructEnd();
284
- break;
285
- }
298
+ case protocol::T_MAP: {
299
+ TType key_type, value_type;
300
+ uint32_t size;
301
+ VALUE k, v;
286
302
 
287
- case protocol::T_MAP: {
288
- TType key_type, value_type;
289
- uint32_t size;
290
- VALUE k, v;
303
+ this->tprot->readMapBegin(key_type, value_type, size);
291
304
 
292
- this->tprot->readMapBegin(key_type, value_type, size);
305
+ if (field_info->keyType == NULL ||
306
+ field_info->elementType == NULL) { // no type check to be consistent
307
+ skip_n_pair(size, key_type, value_type);
308
+ break;
309
+ }
293
310
 
294
- if (field_info->keyType == NULL ||
295
- field_info->elementType == NULL) { // no type check to be consistent
296
- skip_n_pair(size, key_type, value_type);
311
+ ret = rb_hash_new();
312
+ for (uint32_t i = 0; i < size; i++) {
313
+ k = this->readAny(key_type, field_info->keyType);
314
+ v = this->readAny(value_type, field_info->elementType);
315
+ rb_hash_aset(ret, k, v);
316
+ }
317
+ this->tprot->readMapEnd();
297
318
  break;
298
319
  }
299
320
 
300
- ret = rb_hash_new();
301
- for (uint32_t i = 0; i < size; i++) {
302
- k = this->readAny(key_type, field_info->keyType);
303
- v = this->readAny(value_type, field_info->elementType);
304
- rb_hash_aset(ret, k, v);
305
- }
306
- this->tprot->readMapEnd();
307
- break;
308
- }
309
-
310
- default:
311
- this->tprot->skip(ttype);
312
- rb_raise(SparsamUnknownTypeException, "Received unknown type with id: %d", ttype);
313
- break;
321
+ default:
322
+ this->tprot->skip(ttype);
323
+ rb_raise(SparsamUnknownTypeException, "Received unknown type with id: %d",
324
+ ttype);
325
+ break;
314
326
  }
315
327
 
316
328
  return ret;
@@ -319,12 +331,11 @@ VALUE ThriftSerializer::readAny(TType ttype, FieldInfo *field_info) {
319
331
  #undef HANDLE_TYPE
320
332
 
321
333
  VALUE ThriftSerializer::readStruct(VALUE klass) {
322
-
323
334
  string cname;
324
335
  FieldBegin fieldBegin;
325
336
  TType typeId;
326
337
  FieldInfo *fieldInfo;
327
- VALUE ret = rb_class_new_instance(0, NULL, klass); // ret = &klass.new
338
+ VALUE ret = rb_class_new_instance(0, NULL, klass); // ret = &klass.new
328
339
  auto fields = FindOrCreateFieldInfoMap(klass);
329
340
 
330
341
  while (true) {
@@ -346,10 +357,11 @@ VALUE ThriftSerializer::readStruct(VALUE klass) {
346
357
 
347
358
  if (typeId != fieldBegin.ftype) {
348
359
  raise_exc_with_struct_and_field_names(
349
- SparsamTypeMismatchError,
350
- rb_sprintf("Mismatched type (definition: %d, found: %d)", fieldBegin.ftype, typeId),
351
- klass,
352
- fieldInfo->symName);
360
+ SparsamTypeMismatchError,
361
+ rb_sprintf("Mismatched type (definition: %s, found: %s)",
362
+ TTypeName(fieldBegin.ftype).c_str(),
363
+ TTypeName(typeId).c_str()),
364
+ klass, fieldInfo->symName);
353
365
  }
354
366
 
355
367
  VALUE rb_value = this->readAny(fieldBegin.ftype, iter->second);
@@ -366,7 +378,7 @@ VALUE ThriftSerializer::readUnion(VALUE klass) {
366
378
  string cname;
367
379
  FieldBegin fieldBegin;
368
380
 
369
- VALUE ret = rb_class_new_instance(0, NULL, klass); // ret = &klass.new
381
+ VALUE ret = rb_class_new_instance(0, NULL, klass); // ret = &klass.new
370
382
  auto fields = FindOrCreateFieldInfoMap(klass);
371
383
 
372
384
  VALUE key, rb_value;
@@ -404,23 +416,22 @@ VALUE ThriftSerializer::readUnion(VALUE klass) {
404
416
  // for the unary `+` before lambda:
405
417
  // https://stackoverflow.com/a/18889029/4944625
406
418
  // explicit cast to work with signature: (int (*)(...))
407
- #define HASH_FOREACH_BEGIN(hash, ...) \
408
- void *_args[] = {__VA_ARGS__}; \
419
+ #define HASH_FOREACH_BEGIN(hash, ...) \
420
+ void *_args[] = {__VA_ARGS__}; \
409
421
  rb_hash_foreach(hash, (int (*)(ANYARGS))(+[](VALUE k, VALUE v, VALUE args) { \
410
422
  void **argv = (void **) args;
411
-
412
423
  #define HASH_FOREACH_RET() return (int)ST_CONTINUE;
413
424
 
414
425
  #define HASH_FOREACH_ABORT() return (int)ST_STOP;
415
426
 
416
- #define HASH_FOREACH_END() \
417
- HASH_FOREACH_RET() \
427
+ #define HASH_FOREACH_END() \
428
+ HASH_FOREACH_RET() \
418
429
  }), (VALUE) _args);
419
430
 
420
- #define HANDLE_TYPE(TYPE, WRITE_METHOD, CONVERT) \
421
- case protocol::T_##TYPE: { \
422
- this->tprot->write##WRITE_METHOD(CONVERT); \
423
- break; \
431
+ #define HANDLE_TYPE(TYPE, WRITE_METHOD, CONVERT) \
432
+ case protocol::T_##TYPE: { \
433
+ this->tprot->write##WRITE_METHOD(CONVERT); \
434
+ break; \
424
435
  }
425
436
 
426
437
  static inline long raise_bignum_range_error_as_value() {
@@ -428,19 +439,21 @@ static inline long raise_bignum_range_error_as_value() {
428
439
  return 0;
429
440
  }
430
441
 
431
- #define CONVERT_FIXNUM(CONVERT) \
432
- ((FIXNUM_P(actual)) ? \
433
- CONVERT(actual) : \
434
- ((RB_TYPE_P(actual, T_BIGNUM)) ? \
435
- raise_bignum_range_error_as_value() : \
436
- raise_type_mismatch_as_value(outer_struct, field_sym)))
437
-
438
- #define CONVERT_I64 \
439
- ((FIXNUM_P(actual)) ? \
440
- (LONG_LONG)FIX2LONG(actual) : \
441
- ((RB_TYPE_P(actual, T_BIGNUM)) ? \
442
- rb_big2ll(actual) : \
443
- raise_type_mismatch_as_value(outer_struct, field_sym)))
442
+ #define CONVERT_FIXNUM(CONVERT, INTENDED) \
443
+ ((FIXNUM_P(actual)) \
444
+ ? CONVERT(actual) \
445
+ : ((RB_TYPE_P(actual, T_BIGNUM)) \
446
+ ? raise_bignum_range_error_as_value() \
447
+ : raise_type_mismatch_as_value(outer_struct, field_sym, \
448
+ INTENDED, actual)))
449
+
450
+ #define CONVERT_I64 \
451
+ ((FIXNUM_P(actual)) \
452
+ ? (LONG_LONG)FIX2LONG(actual) \
453
+ : ((RB_TYPE_P(actual, T_BIGNUM)) \
454
+ ? rb_big2ll(actual) \
455
+ : raise_type_mismatch_as_value(outer_struct, field_sym, \
456
+ protocol::T_I64, actual)))
444
457
 
445
458
  #ifdef RB_FLOAT_TYPE_P
446
459
  #define FLOAT_TYPE_P(x) RB_FLOAT_TYPE_P(x)
@@ -448,19 +461,21 @@ static inline long raise_bignum_range_error_as_value() {
448
461
  #define FLOAT_TYPE_P(x) RB_TYPE_P(x, T_FLOAT)
449
462
  #endif
450
463
 
451
- #define CONVERT_FLOAT(CONVERT) \
452
- ((FLOAT_TYPE_P(actual)) ? \
453
- CONVERT(actual) : \
454
- raise_type_mismatch_as_value(outer_struct, field_sym)) \
464
+ #define CONVERT_FLOAT(CONVERT) \
465
+ ((FLOAT_TYPE_P(actual)) \
466
+ ? CONVERT(actual) \
467
+ : raise_type_mismatch_as_value(outer_struct, field_sym, \
468
+ protocol::T_DOUBLE, actual))
455
469
 
456
- static inline bool convertBool(VALUE actual, VALUE outer_struct, VALUE field_sym) {
470
+ static inline bool convertBool(VALUE actual, VALUE outer_struct,
471
+ VALUE field_sym) {
457
472
  switch (actual) {
458
473
  case Qtrue:
459
474
  return true;
460
475
  case Qfalse:
461
476
  return false;
462
477
  default:
463
- raise_type_mismatch(outer_struct, field_sym);
478
+ raise_type_mismatch(outer_struct, field_sym, protocol::T_BOOL, actual);
464
479
  }
465
480
 
466
481
  /* unreachable */
@@ -477,7 +492,7 @@ static inline char byte_convert(VALUE x) {
477
492
  short s = SHORT_CONVERT(x);
478
493
 
479
494
  if (s <= 127 && s >= -128) {
480
- return (char) s;
495
+ return (char)s;
481
496
  } else {
482
497
  rb_raise(rb_eRangeError, "integer %d out of range for char", s);
483
498
  }
@@ -487,89 +502,94 @@ static inline char byte_convert(VALUE x) {
487
502
  }
488
503
 
489
504
  void ThriftSerializer::writeAny(TType ttype, FieldInfo *field_info,
490
- VALUE actual, VALUE outer_struct, VALUE field_sym) {
505
+ VALUE actual, VALUE outer_struct,
506
+ VALUE field_sym) {
491
507
  switch (ttype) {
492
- HANDLE_TYPE(I16, I16, CONVERT_FIXNUM(SHORT_CONVERT))
493
- HANDLE_TYPE(I32, I32, CONVERT_FIXNUM(FIX2INT))
508
+ HANDLE_TYPE(I16, I16, CONVERT_FIXNUM(SHORT_CONVERT, protocol::T_I16))
509
+ HANDLE_TYPE(I32, I32, CONVERT_FIXNUM(FIX2INT, protocol::T_I32))
494
510
  HANDLE_TYPE(I64, I64, CONVERT_I64)
495
511
  HANDLE_TYPE(BOOL, Bool, convertBool(actual, outer_struct, field_sym))
496
512
  HANDLE_TYPE(DOUBLE, Double, CONVERT_FLOAT(NUM2DBL))
497
- HANDLE_TYPE(BYTE, Byte, CONVERT_FIXNUM(byte_convert))
513
+ HANDLE_TYPE(BYTE, Byte, CONVERT_FIXNUM(byte_convert, protocol::T_BYTE))
498
514
 
499
- case protocol::T_STRING: {
500
- Sparsam_Check_Type(actual, T_STRING, outer_struct, field_sym);
515
+ case protocol::T_STRING: {
516
+ Sparsam_Check_Type(actual, T_STRING, outer_struct, field_sym);
501
517
 
502
- string data = string(StringValuePtr(actual), RSTRING_LEN(actual));
503
- if (field_info->isBinaryString) {
504
- this->tprot->writeBinary(data);
505
- } else {
506
- this->tprot->writeString(data);
518
+ string data = string(StringValuePtr(actual), RSTRING_LEN(actual));
519
+ if (field_info->isBinaryString) {
520
+ this->tprot->writeBinary(data);
521
+ } else {
522
+ this->tprot->writeString(data);
523
+ }
524
+ break;
507
525
  }
508
- break;
509
- }
510
526
 
511
- case protocol::T_LIST: {
512
- Sparsam_Check_Type(actual, T_ARRAY, outer_struct, field_sym);
527
+ case protocol::T_LIST: {
528
+ Sparsam_Check_Type(actual, T_ARRAY, outer_struct, field_sym);
513
529
 
514
- long length = RARRAY_LEN(actual);
515
- TType elem = field_info->elementType->ftype;
516
- this->tprot->writeListBegin(elem, static_cast<size_t>(length));
517
- for (long i = 0; i < length; i++) {
518
- this->writeAny(elem, field_info->elementType, rb_ary_entry(actual, i), outer_struct, field_sym);
530
+ long length = RARRAY_LEN(actual);
531
+ TType elem = field_info->elementType->ftype;
532
+ this->tprot->writeListBegin(elem, static_cast<size_t>(length));
533
+ for (long i = 0; i < length; i++) {
534
+ this->writeAny(elem, field_info->elementType, rb_ary_entry(actual, i),
535
+ outer_struct, field_sym);
536
+ }
537
+ this->tprot->writeListEnd();
538
+ break;
519
539
  }
520
- this->tprot->writeListEnd();
521
- break;
522
- }
523
540
 
524
- case protocol::T_SET: {
525
- if (rb_class_real(CLASS_OF(actual)) != SetClass) {
526
- raise_type_mismatch(outer_struct, field_sym);
541
+ case protocol::T_SET: {
542
+ if (rb_class_real(CLASS_OF(actual)) != SetClass) {
543
+ raise_type_mismatch(outer_struct, field_sym, protocol::T_SET, actual);
544
+ }
545
+
546
+ VALUE ary = rb_funcall(actual, intern_for_to_a, 0);
547
+ long length = RARRAY_LEN(ary);
548
+ TType elem = field_info->elementType->ftype;
549
+ this->tprot->writeListBegin(elem, static_cast<size_t>(length));
550
+ for (long i = 0; i < length; i++) {
551
+ this->writeAny(elem, field_info->elementType, rb_ary_entry(ary, i),
552
+ outer_struct, field_sym);
553
+ }
554
+ this->tprot->writeListEnd();
555
+ break;
527
556
  }
528
557
 
529
- VALUE ary = rb_funcall(actual, intern_for_to_a, 0);
530
- long length = RARRAY_LEN(ary);
531
- TType elem = field_info->elementType->ftype;
532
- this->tprot->writeListBegin(elem, static_cast<size_t>(length));
533
- for (long i = 0; i < length; i++) {
534
- this->writeAny(elem, field_info->elementType, rb_ary_entry(ary, i), outer_struct, field_sym);
558
+ case protocol::T_MAP: {
559
+ Sparsam_Check_Type(actual, T_HASH, outer_struct, field_sym);
560
+
561
+ TType keyTType = field_info->keyType->ftype,
562
+ valueTType = field_info->elementType->ftype;
563
+ this->tprot->writeMapBegin(keyTType, valueTType,
564
+ static_cast<size_t>(RHASH_SIZE(actual)));
565
+ HASH_FOREACH_BEGIN(actual, this, field_info, &outer_struct, &field_sym)
566
+ ThriftSerializer *that = (ThriftSerializer *)argv[0];
567
+ FieldInfo *field_info = (FieldInfo *)argv[1];
568
+ VALUE *outer_struct = (VALUE *)argv[2];
569
+ VALUE *field_sym = (VALUE *)argv[3];
570
+ that->writeAny(field_info->keyType->ftype, field_info->keyType, k,
571
+ *outer_struct, *field_sym);
572
+ that->writeAny(field_info->elementType->ftype, field_info->elementType, v,
573
+ *outer_struct, *field_sym);
574
+ HASH_FOREACH_END()
575
+ this->tprot->writeMapEnd();
576
+ break;
535
577
  }
536
- this->tprot->writeListEnd();
537
- break;
538
- }
539
578
 
540
- case protocol::T_MAP: {
541
- Sparsam_Check_Type(actual, T_HASH, outer_struct, field_sym);
542
-
543
- TType keyTType = field_info->keyType->ftype,
544
- valueTType = field_info->elementType->ftype;
545
- this->tprot->writeMapBegin(keyTType, valueTType,
546
- static_cast<size_t>(RHASH_SIZE(actual)));
547
- HASH_FOREACH_BEGIN(actual, this, field_info, &outer_struct, &field_sym)
548
- ThriftSerializer *that = (ThriftSerializer *)argv[0];
549
- FieldInfo *field_info = (FieldInfo *)argv[1];
550
- VALUE *outer_struct = (VALUE *)argv[2];
551
- VALUE *field_sym = (VALUE *)argv[3];
552
- that->writeAny(field_info->keyType->ftype, field_info->keyType, k, *outer_struct, *field_sym);
553
- that->writeAny(field_info->elementType->ftype, field_info->elementType, v, *outer_struct, *field_sym);
554
- HASH_FOREACH_END()
555
- this->tprot->writeMapEnd();
556
- break;
557
- }
579
+ case protocol::T_STRUCT: {
580
+ if (rb_class_real(CLASS_OF(actual)) != field_info->klass) {
581
+ raise_type_mismatch(outer_struct, field_sym, field_info->klass, actual);
582
+ }
558
583
 
559
- case protocol::T_STRUCT: {
560
- if (rb_class_real(CLASS_OF(actual)) != field_info->klass) {
561
- raise_type_mismatch(outer_struct, field_sym);
584
+ static const string cname = "";
585
+ this->tprot->writeStructBegin(cname.c_str());
586
+ this->writeStruct(field_info->klass, actual);
587
+ this->tprot->writeFieldStop();
588
+ this->tprot->writeStructEnd();
589
+ break;
562
590
  }
563
591
 
564
- static const string cname = "";
565
- this->tprot->writeStructBegin(cname.c_str());
566
- this->writeStruct(field_info->klass, actual);
567
- this->tprot->writeFieldStop();
568
- this->tprot->writeStructEnd();
569
- break;
570
- }
571
-
572
- default: { break; }
592
+ default: { break; }
573
593
  }
574
594
  }
575
595
 
@@ -582,10 +602,8 @@ static bool checkRequiredFields(VALUE klass, VALUE data) {
582
602
  VALUE val = rb_ivar_get(data, entry.second->ivarName);
583
603
  if (NIL_P(val)) {
584
604
  raise_exc_with_struct_and_field_names(
585
- SparsamMissingMandatory,
586
- rb_str_new2("Required field missing"),
587
- klass,
588
- entry.second->symName);
605
+ SparsamMissingMandatory, rb_str_new2("Required field missing"),
606
+ klass, entry.second->symName);
589
607
  return false;
590
608
  }
591
609
  }
@@ -604,14 +622,16 @@ void ThriftSerializer::writeStruct(VALUE klass, VALUE data) {
604
622
  return;
605
623
  }
606
624
 
607
- for (auto const & entry : *fields) {
625
+ for (auto const &entry : *fields) {
608
626
  fieldBegin.fid = entry.first;
609
627
  fieldInfo = entry.second;
610
628
  fieldBegin.ftype = fieldInfo->ftype;
611
629
  VALUE actual = rb_ivar_get(data, fieldInfo->ivarName);
612
630
  if (!NIL_P(actual)) {
613
- this->tprot->writeFieldBegin(cname.c_str(), fieldBegin.ftype, fieldBegin.fid);
614
- this->writeAny(fieldBegin.ftype, entry.second, actual, data, fieldInfo->symName);
631
+ this->tprot->writeFieldBegin(cname.c_str(), fieldBegin.ftype,
632
+ fieldBegin.fid);
633
+ this->writeAny(fieldBegin.ftype, entry.second, actual, data,
634
+ fieldInfo->symName);
615
635
  this->tprot->writeFieldEnd();
616
636
  }
617
637
  }
@@ -625,13 +645,10 @@ VALUE serializer_writeStruct(VALUE self, VALUE klass, VALUE data) {
625
645
  VALUE actual_name = rb_class_name(CLASS_OF(data));
626
646
 
627
647
  raise_exc_with_struct_and_field_names(
628
- SparsamTypeMismatchError,
629
- rb_sprintf(
630
- "Mismatched type passed to serialize (expected: %s got: %s)",
631
- RSTRING_PTR(expected_name),
632
- RSTRING_PTR(actual_name)),
633
- CLASS_OF(data),
634
- ID2SYM(rb_intern("(root)")));
648
+ SparsamTypeMismatchError,
649
+ rb_sprintf("Mismatched type passed to serialize (expected: %s got: %s)",
650
+ RSTRING_PTR(expected_name), RSTRING_PTR(actual_name)),
651
+ CLASS_OF(data), ID2SYM(rb_intern("(root)")));
635
652
 
636
653
  RB_GC_GUARD(expected_name);
637
654
  RB_GC_GUARD(actual_name);
@@ -708,34 +725,36 @@ FieldInfo *CreateFieldInfo(VALUE field_map_entry) {
708
725
  R_FIX_TO_TTYPE(rb_hash_aref(field_map_entry, sym_for_type));
709
726
  fieldInfo->isOptional =
710
727
  RTEST(rb_hash_aref(field_map_entry, sym_for_optional));
711
- fieldInfo->ivarName = field_name_to_ivar_id(rb_hash_aref(field_map_entry, sym_for_name));
712
- fieldInfo->symName = field_name_to_sym(rb_hash_aref(field_map_entry, sym_for_name));
728
+ fieldInfo->ivarName =
729
+ field_name_to_ivar_id(rb_hash_aref(field_map_entry, sym_for_name));
730
+ fieldInfo->symName =
731
+ field_name_to_sym(rb_hash_aref(field_map_entry, sym_for_name));
713
732
  switch (fieldInfo->ftype) {
714
- case protocol::T_STRING: {
715
- if (RTEST(rb_hash_aref(field_map_entry, sym_for_binary))) {
716
- fieldInfo->isBinaryString = true;
733
+ case protocol::T_STRING: {
734
+ if (RTEST(rb_hash_aref(field_map_entry, sym_for_binary))) {
735
+ fieldInfo->isBinaryString = true;
736
+ }
737
+ break;
717
738
  }
718
- break;
719
- }
720
- case protocol::T_STRUCT: {
721
- fieldInfo->klass = rb_hash_aref(field_map_entry, sym_for_class);
722
- break;
723
- }
724
- case protocol::T_LIST:
725
- case protocol::T_SET: {
726
- fieldInfo->elementType =
727
- CreateFieldInfo(rb_hash_aref(field_map_entry, sym_for_element));
728
- break;
729
- }
730
- case protocol::T_MAP: {
731
- fieldInfo->keyType =
732
- CreateFieldInfo(rb_hash_aref(field_map_entry, sym_for_key));
733
- fieldInfo->elementType =
734
- CreateFieldInfo(rb_hash_aref(field_map_entry, sym_for_value));
735
- break;
736
- }
737
- default:
738
- break;
739
+ case protocol::T_STRUCT: {
740
+ fieldInfo->klass = rb_hash_aref(field_map_entry, sym_for_class);
741
+ break;
742
+ }
743
+ case protocol::T_LIST:
744
+ case protocol::T_SET: {
745
+ fieldInfo->elementType =
746
+ CreateFieldInfo(rb_hash_aref(field_map_entry, sym_for_element));
747
+ break;
748
+ }
749
+ case protocol::T_MAP: {
750
+ fieldInfo->keyType =
751
+ CreateFieldInfo(rb_hash_aref(field_map_entry, sym_for_key));
752
+ fieldInfo->elementType =
753
+ CreateFieldInfo(rb_hash_aref(field_map_entry, sym_for_value));
754
+ break;
755
+ }
756
+ default:
757
+ break;
739
758
  }
740
759
  return fieldInfo;
741
760
  }
@@ -18,9 +18,9 @@ enum TOType {
18
18
 
19
19
  enum ValidateStrictness { normal = 0, strict = 1, recursive = 2 };
20
20
 
21
- void serializer_free(void *data);
22
- void *serializer_create();
23
- void serializer_init(void *serializer, int protocol, void *str_arg1,
21
+ void serializer_free(void* data);
22
+ void* serializer_create();
23
+ void serializer_init(void* serializer, int protocol, void* str_arg1,
24
24
  uint32_t len);
25
25
 
26
26
  VALUE serializer_readStruct(VALUE self, VALUE klass);
@@ -36,18 +36,36 @@ void initialize_constants();
36
36
  void initialize_runtime_constants();
37
37
 
38
38
  #ifdef __cplusplus
39
- } // end extern "C"
39
+ } // end extern "C"
40
40
 
41
+ #include <thrift/protocol/TProtocol.h>
42
+ #include <thrift/transport/TBufferTransports.h>
41
43
  #include <boost/shared_ptr.hpp>
42
44
  #include <map>
43
45
  #include <string>
44
- #include <thrift/protocol/TProtocol.h>
45
- #include <thrift/transport/TBufferTransports.h>
46
46
  #include <unordered_set>
47
47
  #include "third-party/sparsepp/sparsepp/spp.h"
48
48
 
49
49
  using ::apache::thrift::protocol::TType;
50
50
 
51
+ // transposed from:
52
+ // https://github.com/apache/thrift/blob/0.10.0/lib/cpp/src/thrift/protocol/TProtocol.h#L176
53
+ // with: https://gist.github.com/andyfangdz/d4d52daa9f8a75223e76e92657036bb0
54
+ // fun fact: it's not sorted there
55
+ const std::string TTypeNames[] = {
56
+ "T_STOP", "T_VOID", "T_BOOL", "T_BYTE or T_I08",
57
+ "T_DOUBLE", "T_UNKNOWN", "T_I16", "T_UNKNOWN",
58
+ "T_I32", "T_U64", "T_I64", "T_STRING or T_UTF7",
59
+ "T_STRUCT", "T_MAP", "T_SET", "T_LIST",
60
+ "T_UTF8", "T_UTF16"};
61
+
62
+ const size_t TTypeMaxID = sizeof(TTypeNames) / sizeof(TTypeNames[0]);
63
+
64
+ const std::string TTypeUnknown = "T_UNKNOWN";
65
+
66
+ #define TTypeName(typeId) \
67
+ (typeId < TTypeMaxID ? TTypeNames[typeId] : TTypeUnknown)
68
+
51
69
  typedef uint16_t FieldIdIndex;
52
70
  typedef uint16_t KlassIndex;
53
71
 
@@ -60,38 +78,41 @@ typedef struct FieldBegin {
60
78
 
61
79
  typedef struct FieldInfo {
62
80
  TType ftype;
63
- VALUE klass; // set if TTYPE is struct or union
64
- ID ivarName; // set if field is on struct
65
- VALUE symName; // set if field is on struct/union
81
+ VALUE klass; // set if TTYPE is struct or union
82
+ ID ivarName; // set if field is on struct
83
+ VALUE symName; // set if field is on struct/union
66
84
  bool isOptional;
67
85
  bool isBinaryString;
68
- FieldInfo *elementType; // element of list or set, or map
69
- FieldInfo *keyType; // type of key in maps
86
+ FieldInfo* elementType; // element of list or set, or map
87
+ FieldInfo* keyType; // type of key in maps
70
88
  } FieldInfo;
71
89
 
72
- typedef std::map<FieldID, FieldInfo *> FieldInfoMap;
73
- typedef spp::sparse_hash_map<VALUE, FieldInfoMap *> KlassFieldsCache;
90
+ typedef std::map<FieldID, FieldInfo*> FieldInfoMap;
91
+ typedef spp::sparse_hash_map<VALUE, FieldInfoMap*> KlassFieldsCache;
74
92
 
75
93
  class ThriftSerializer {
76
- public:
94
+ public:
77
95
  ThriftSerializer(){};
96
+ // clang-format off
78
97
  boost::shared_ptr< ::apache::thrift::protocol::TProtocol > tprot;
79
98
  boost::shared_ptr< ::apache::thrift::transport::TMemoryBuffer > tmb;
99
+ // clang-format on
80
100
 
81
101
  VALUE readStruct(VALUE klass);
82
102
  VALUE readUnion(VALUE klass);
83
103
  void writeStruct(VALUE klass, VALUE data);
84
104
 
85
- private:
86
- VALUE readAny(TType ttype, FieldInfo *field_info);
87
- void writeAny(TType ttype, FieldInfo *field_info, VALUE data, VALUE outer_struct, VALUE field_sym);
105
+ private:
106
+ VALUE readAny(TType ttype, FieldInfo* field_info);
107
+ void writeAny(TType ttype, FieldInfo* field_info, VALUE data,
108
+ VALUE outer_struct, VALUE field_sym);
88
109
  void skip_n_type(uint32_t n, TType ttype);
89
110
  void skip_n_pair(uint32_t n, TType type_a, TType type_b);
90
111
  };
91
112
 
92
- FieldInfoMap *FindOrCreateFieldInfoMap(VALUE klass);
93
- FieldInfo *CreateFieldInfo(VALUE field_map_entry);
94
- FieldInfoMap *CreateFieldInfoMap(VALUE klass);
113
+ FieldInfoMap* FindOrCreateFieldInfoMap(VALUE klass);
114
+ FieldInfo* CreateFieldInfo(VALUE field_map_entry);
115
+ FieldInfoMap* CreateFieldInfoMap(VALUE klass);
95
116
 
96
117
  #endif
97
118
  #endif
@@ -227,6 +227,44 @@ describe 'Sparsam' do
227
227
  e.field_name.should == "id_i32"
228
228
  end
229
229
 
230
+ it "includes additional information on serializing mismatched types" do
231
+ data = MiniRequired.new
232
+ data.id_i32 = "not an i32"
233
+
234
+ e = nil
235
+ begin
236
+ data.serialize
237
+ rescue Sparsam::TypeMismatch => exception
238
+ e = exception
239
+ end
240
+ e.message.should include("T_I32", "String")
241
+
242
+ data = EveryType.new
243
+ data.a_struct = EveryType.new
244
+
245
+ e = nil
246
+ begin
247
+ data.serialize
248
+ rescue Sparsam::TypeMismatch => exception
249
+ e = exception
250
+ end
251
+ e.message.should include("US", "EveryType")
252
+ end
253
+
254
+ it "includes additional information on deserializing mismatched types" do
255
+ data = NotSS.new
256
+ data.id_s = "not an i32"
257
+
258
+ serialized = data.serialize
259
+
260
+ begin
261
+ Sparsam::Deserializer.deserialize(SS, serialized)
262
+ rescue Sparsam::TypeMismatch => exception
263
+ e = exception
264
+ end
265
+ e.message.should include("T_I32", "T_STRING")
266
+ end
267
+
230
268
  it "will throw errors when given junk data" do
231
269
  expect {
232
270
  Sparsam::Deserializer.deserialize(SS, "wolololololol")
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sparsam
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 0.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Airbnb Thrift Developers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-07-07 00:00:00.000000000 Z
11
+ date: 2018-07-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec