sparsam 0.2.5 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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