sparsam 0.1.5 → 0.2.0

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
  SHA1:
3
- metadata.gz: 82b851a7cec00fa3805571f1cd89d43077b86ed5
4
- data.tar.gz: c4617c449ccd26bb73896e49ceb430b15f6f973c
3
+ metadata.gz: 87e15b3482d526230c19c17ae70ab49f6648d9a3
4
+ data.tar.gz: c807cb67e084c9a7ab0ab17e18fb8ee6ea3abfe9
5
5
  SHA512:
6
- metadata.gz: 73aff3bcae386d83adb457c63ef35ec0d0281e2bab33436b4f05c7fa8b79f80e5110d7600cfa3427cfbd5eeb222f01cf997ce8f312cd3be72dbb6f7d6fbebdc1
7
- data.tar.gz: 6f060447c4d06c8abd9f014dcdbafe5e3e1e8ffc8ce0a23c999c7c445138ac019a0257eccf48bdfc5af4cf722ccd64e44155574190c65f67dadc026b1f223317
6
+ metadata.gz: 4d4efd67ffeca9291b57f9f1727b7234ed64a94325c430b2edce04c2204b1fc4d78e2d4aab06700fb91bd0a01f2e9c81ecbe4a98656f2bd343ca1962365f1458
7
+ data.tar.gz: b6c6d48b793f6b9dea35565a634f9d26f85238eedc93343612d7913dec113b761d3e7490f3be0e099f49faeecaae5f2ff11ed02f75fc79c233665e834d2fdc13
data/ext/ruby_hooks.c CHANGED
@@ -69,7 +69,6 @@ void Init_sparsam_native() {
69
69
  Sparsam = rb_define_module("Sparsam");
70
70
  rb_define_singleton_method(Sparsam, "init!", sparsam_init_bang, 0);
71
71
  rb_define_singleton_method(Sparsam, "cache_fields", cache_fields, 1);
72
- rb_define_singleton_method(Sparsam, "validate", serializer_validate, 3);
73
72
  VALUE SparsamSerializer = rb_define_class_under(Sparsam, "Serializer", rb_cObject);
74
73
  SparsamNativeError =
75
74
  rb_define_class_under(Sparsam, "Exception", rb_eStandardError);
data/ext/serializer.cpp CHANGED
@@ -42,6 +42,8 @@ VALUE SparsamMissingMandatory;
42
42
  VALUE SparsamUnionException;
43
43
  VALUE SparsamUnknownTypeException;
44
44
 
45
+ VALUE SetClass;
46
+
45
47
  KlassFieldsCache klassCache; // consider the memory leaked.
46
48
  std::unordered_set<VALUE> unions;
47
49
 
@@ -82,6 +84,7 @@ void initialize_runtime_constants() {
82
84
  SparsamUnionException = rb_const_get_at(Sparsam, rb_intern("UnionException"));
83
85
  SparsamUnknownTypeException =
84
86
  rb_const_get_at(Sparsam, rb_intern("UnknownTypeException"));
87
+ SetClass = rb_const_get_at(rb_cObject, rb_intern("Set"));
85
88
  }
86
89
 
87
90
  void serializer_init(void *serializer, int protocol, void *str_arg1,
@@ -138,16 +141,41 @@ static inline VALUE make_ruby_binary(const string &val) {
138
141
 
139
142
  static void raise_exc_with_struct_and_field_names(
140
143
  VALUE exc_class,
141
- VALUE msg,
144
+ VALUE msg_prefix,
142
145
  VALUE outer_struct_class,
143
146
  VALUE field_sym) {
144
147
  VALUE struct_name = rb_class_name(outer_struct_class);
145
148
  VALUE field_name = rb_sym_to_s(field_sym);
149
+
150
+ VALUE msg = rb_sprintf("%s (in %s#%s)",
151
+ RSTRING_PTR(msg_prefix),
152
+ RSTRING_PTR(struct_name),
153
+ RSTRING_PTR(field_name));
146
154
  VALUE args[3] = {msg, struct_name, field_name};
147
155
  VALUE e = rb_class_new_instance(3, args, exc_class);
148
156
  rb_exc_raise(e);
149
157
  }
150
158
 
159
+ static void raise_type_mismatch(VALUE outer_struct, VALUE field_sym) {
160
+ raise_exc_with_struct_and_field_names(
161
+ SparsamTypeMismatchError,
162
+ rb_str_new2("Mismatched type"),
163
+ CLASS_OF(outer_struct),
164
+ field_sym);
165
+ }
166
+
167
+ static inline long raise_type_mismatch_as_value(VALUE outer_struct, VALUE field_sym) {
168
+ raise_type_mismatch(outer_struct, field_sym);
169
+ return 0;
170
+ }
171
+
172
+ static inline void Sparsam_Check_Type(VALUE x, int t, VALUE outer_struct, VALUE field_sym) {
173
+ if (!(RB_TYPE_P(x, t))) {
174
+ raise_type_mismatch(outer_struct, field_sym);
175
+ }
176
+ }
177
+
178
+
151
179
  static inline VALUE make_ruby_bool(bool val) { return val ? Qtrue : Qfalse; }
152
180
 
153
181
  void ThriftSerializer::skip_n_type(uint32_t n, TType ttype) {
@@ -315,7 +343,7 @@ VALUE ThriftSerializer::readStruct(VALUE klass) {
315
343
  if (typeId != fieldBegin.ftype) {
316
344
  raise_exc_with_struct_and_field_names(
317
345
  SparsamTypeMismatchError,
318
- rb_sprintf("Type Mismatch. Defenition: %d, Actual: %d", fieldBegin.ftype, typeId),
346
+ rb_sprintf("Mismatched type (definition: %d, found: %d)", fieldBegin.ftype, typeId),
319
347
  klass,
320
348
  fieldInfo->symName);
321
349
  }
@@ -387,22 +415,85 @@ VALUE ThriftSerializer::readUnion(VALUE klass) {
387
415
 
388
416
  #define HANDLE_TYPE(TYPE, WRITE_METHOD, CONVERT) \
389
417
  case protocol::T_##TYPE: { \
390
- this->tprot->write##WRITE_METHOD(CONVERT(actual)); \
418
+ this->tprot->write##WRITE_METHOD(CONVERT); \
391
419
  break; \
392
420
  }
393
421
 
422
+ static inline long raise_bignum_range_error_as_value() {
423
+ rb_raise(rb_eRangeError, "bignum too big to convert");
424
+ return 0;
425
+ }
426
+
427
+ #define CONVERT_FIXNUM(CONVERT) \
428
+ ((FIXNUM_P(actual)) ? \
429
+ CONVERT(actual) : \
430
+ ((RB_TYPE_P(actual, T_BIGNUM)) ? \
431
+ raise_bignum_range_error_as_value() : \
432
+ raise_type_mismatch_as_value(outer_struct, field_sym)))
433
+
434
+ #define CONVERT_I64 \
435
+ ((FIXNUM_P(actual)) ? \
436
+ (LONG_LONG)FIX2LONG(actual) : \
437
+ ((RB_TYPE_P(actual, T_BIGNUM)) ? \
438
+ rb_big2ll(actual) : \
439
+ raise_type_mismatch_as_value(outer_struct, field_sym)))
440
+
441
+ #ifdef RB_FLOAT_TYPE_P
442
+ #define FLOAT_TYPE_P(x) RB_FLOAT_TYPE_P(x)
443
+ #else
444
+ #define FLOAT_TYPE_P(x) RB_TYPE_P(x, T_FLOAT)
445
+ #endif
446
+
447
+ #define CONVERT_FLOAT(CONVERT) \
448
+ ((FLOAT_TYPE_P(actual)) ? \
449
+ CONVERT(actual) : \
450
+ raise_type_mismatch_as_value(outer_struct, field_sym)) \
451
+
452
+ static inline bool convertBool(VALUE actual, VALUE outer_struct, VALUE field_sym) {
453
+ switch (actual) {
454
+ case Qtrue:
455
+ return true;
456
+ case Qfalse:
457
+ return false;
458
+ default:
459
+ raise_type_mismatch(outer_struct, field_sym);
460
+ }
461
+
462
+ /* unreachable */
463
+ return false;
464
+ }
465
+
466
+ #ifdef FIX2SHORT
467
+ #define SHORT_CONVERT(x) FIX2SHORT(x)
468
+ #else
469
+ #define SHORT_CONVERT(x) ((short)FIX2INT(x))
470
+ #endif
471
+
472
+ static inline char byte_convert(VALUE x) {
473
+ short s = SHORT_CONVERT(x);
474
+
475
+ if (s <= 127 && s >= -128) {
476
+ return (char) s;
477
+ } else {
478
+ rb_raise(rb_eRangeError, "integer %d out of range for char", s);
479
+ }
480
+
481
+ /* unreachable */
482
+ return 0;
483
+ }
484
+
394
485
  void ThriftSerializer::writeAny(TType ttype, FieldInfo *field_info,
395
- VALUE actual) {
486
+ VALUE actual, VALUE outer_struct, VALUE field_sym) {
396
487
  switch (ttype) {
397
- HANDLE_TYPE(I16, I16, NUM2SHORT)
398
- HANDLE_TYPE(I32, I32, NUM2INT)
399
- HANDLE_TYPE(I64, I64, NUM2LL)
400
- HANDLE_TYPE(BOOL, Bool, RTEST)
401
- HANDLE_TYPE(DOUBLE, Double, NUM2DBL)
402
- HANDLE_TYPE(BYTE, Byte, NUM2SHORT)
488
+ HANDLE_TYPE(I16, I16, CONVERT_FIXNUM(SHORT_CONVERT))
489
+ HANDLE_TYPE(I32, I32, CONVERT_FIXNUM(FIX2INT))
490
+ HANDLE_TYPE(I64, I64, CONVERT_I64)
491
+ HANDLE_TYPE(BOOL, Bool, convertBool(actual, outer_struct, field_sym))
492
+ HANDLE_TYPE(DOUBLE, Double, CONVERT_FLOAT(NUM2DBL))
493
+ HANDLE_TYPE(BYTE, Byte, CONVERT_FIXNUM(byte_convert))
403
494
 
404
495
  case protocol::T_STRING: {
405
- Check_Type(actual, T_STRING);
496
+ Sparsam_Check_Type(actual, T_STRING, outer_struct, field_sym);
406
497
 
407
498
  string data = string(StringValuePtr(actual), RSTRING_LEN(actual));
408
499
  if (field_info->isBinaryString) {
@@ -414,48 +505,58 @@ void ThriftSerializer::writeAny(TType ttype, FieldInfo *field_info,
414
505
  }
415
506
 
416
507
  case protocol::T_LIST: {
417
- Check_Type(actual, T_ARRAY);
508
+ Sparsam_Check_Type(actual, T_ARRAY, outer_struct, field_sym);
418
509
 
419
510
  long length = RARRAY_LEN(actual);
420
511
  TType elem = field_info->elementType->ftype;
421
512
  this->tprot->writeListBegin(elem, static_cast<size_t>(length));
422
513
  for (long i = 0; i < length; i++) {
423
- this->writeAny(elem, field_info->elementType, rb_ary_entry(actual, i));
514
+ this->writeAny(elem, field_info->elementType, rb_ary_entry(actual, i), outer_struct, field_sym);
424
515
  }
425
516
  this->tprot->writeListEnd();
426
517
  break;
427
518
  }
428
519
 
429
520
  case protocol::T_SET: {
521
+ if (CLASS_OF(actual) != SetClass) {
522
+ raise_type_mismatch(outer_struct, field_sym);
523
+ }
524
+
430
525
  VALUE ary = rb_funcall(actual, intern_for_to_a, 0);
431
526
  long length = RARRAY_LEN(ary);
432
527
  TType elem = field_info->elementType->ftype;
433
528
  this->tprot->writeListBegin(elem, static_cast<size_t>(length));
434
529
  for (long i = 0; i < length; i++) {
435
- this->writeAny(elem, field_info->elementType, rb_ary_entry(ary, i));
530
+ this->writeAny(elem, field_info->elementType, rb_ary_entry(ary, i), outer_struct, field_sym);
436
531
  }
437
532
  this->tprot->writeListEnd();
438
533
  break;
439
534
  }
440
535
 
441
536
  case protocol::T_MAP: {
442
- Check_Type(actual, T_HASH);
537
+ Sparsam_Check_Type(actual, T_HASH, outer_struct, field_sym);
443
538
 
444
539
  TType keyTType = field_info->keyType->ftype,
445
540
  valueTType = field_info->elementType->ftype;
446
541
  this->tprot->writeMapBegin(keyTType, valueTType,
447
542
  static_cast<size_t>(RHASH_SIZE(actual)));
448
- HASH_FOREACH_BEGIN(actual, this, field_info)
543
+ HASH_FOREACH_BEGIN(actual, this, field_info, &outer_struct, &field_sym)
449
544
  ThriftSerializer *that = (ThriftSerializer *)argv[0];
450
545
  FieldInfo *field_info = (FieldInfo *)argv[1];
451
- that->writeAny(field_info->keyType->ftype, field_info->keyType, k);
452
- that->writeAny(field_info->elementType->ftype, field_info->elementType, v);
546
+ VALUE *outer_struct = (VALUE *)argv[2];
547
+ VALUE *field_sym = (VALUE *)argv[3];
548
+ that->writeAny(field_info->keyType->ftype, field_info->keyType, k, *outer_struct, *field_sym);
549
+ that->writeAny(field_info->elementType->ftype, field_info->elementType, v, *outer_struct, *field_sym);
453
550
  HASH_FOREACH_END()
454
551
  this->tprot->writeMapEnd();
455
552
  break;
456
553
  }
457
554
 
458
555
  case protocol::T_STRUCT: {
556
+ if (CLASS_OF(actual) != field_info->klass) {
557
+ raise_type_mismatch(outer_struct, field_sym);
558
+ }
559
+
459
560
  static const string cname = "";
460
561
  this->tprot->writeStructBegin(cname.c_str());
461
562
  this->writeStruct(field_info->klass, actual);
@@ -470,13 +571,32 @@ void ThriftSerializer::writeAny(TType ttype, FieldInfo *field_info,
470
571
 
471
572
  #undef HANDLE_TYPE
472
573
 
574
+ static bool checkRequiredFields(VALUE klass, VALUE data) {
575
+ auto fields = FindOrCreateFieldInfoMap(klass);
576
+ for (auto const &entry : *fields) {
577
+ if (!entry.second->isOptional) {
578
+ VALUE val = rb_ivar_get(data, entry.second->ivarName);
579
+ if (NIL_P(val)) {
580
+ raise_exc_with_struct_and_field_names(
581
+ SparsamMissingMandatory,
582
+ rb_str_new2("Required field missing"),
583
+ klass,
584
+ entry.second->symName);
585
+ return false;
586
+ }
587
+ }
588
+ }
589
+
590
+ return true;
591
+ }
592
+
473
593
  void ThriftSerializer::writeStruct(VALUE klass, VALUE data) {
474
594
  static const string cname = "";
475
595
  FieldBegin fieldBegin;
476
596
  FieldInfo *fieldInfo;
477
597
  auto fields = FindOrCreateFieldInfoMap(klass);
478
598
 
479
- if (!validateStruct(klass, data, false, false)) {
599
+ if (!checkRequiredFields(klass, data)) {
480
600
  return;
481
601
  }
482
602
 
@@ -487,7 +607,7 @@ void ThriftSerializer::writeStruct(VALUE klass, VALUE data) {
487
607
  VALUE actual = rb_ivar_get(data, fieldInfo->ivarName);
488
608
  if (!NIL_P(actual)) {
489
609
  this->tprot->writeFieldBegin(cname.c_str(), fieldBegin.ftype, fieldBegin.fid);
490
- this->writeAny(fieldBegin.ftype, entry.second, actual);
610
+ this->writeAny(fieldBegin.ftype, entry.second, actual, data, fieldInfo->symName);
491
611
  this->tprot->writeFieldEnd();
492
612
  }
493
613
  }
@@ -495,6 +615,24 @@ void ThriftSerializer::writeStruct(VALUE klass, VALUE data) {
495
615
 
496
616
  VALUE serializer_writeStruct(VALUE self, VALUE klass, VALUE data) {
497
617
  watch_for_texcept() get_ts();
618
+
619
+ if (CLASS_OF(data) != klass) {
620
+ VALUE expected_name = rb_class_name(klass);
621
+ VALUE actual_name = rb_class_name(CLASS_OF(data));
622
+
623
+ raise_exc_with_struct_and_field_names(
624
+ SparsamTypeMismatchError,
625
+ rb_sprintf(
626
+ "Mismatched type passed to serialize (expected: %s got: %s)",
627
+ RSTRING_PTR(expected_name),
628
+ RSTRING_PTR(actual_name)),
629
+ data,
630
+ ID2SYM(rb_intern("(root)")));
631
+
632
+ RB_GC_GUARD(expected_name);
633
+ RB_GC_GUARD(actual_name);
634
+ }
635
+
498
636
  static const string cname = "";
499
637
  ts->tprot->writeStructBegin(cname.c_str());
500
638
  ts->writeStruct(klass, data);
@@ -516,159 +654,6 @@ VALUE serializer_readStruct(VALUE self, VALUE klass) {
516
654
  catch_thrift_and_reraise();
517
655
  }
518
656
 
519
- static void raise_type_mismatch(VALUE outer_struct, VALUE field_sym) {
520
- raise_exc_with_struct_and_field_names(
521
- SparsamTypeMismatchError,
522
- rb_str_new2("Type mismatch in field data"),
523
- CLASS_OF(outer_struct),
524
- field_sym);
525
- }
526
-
527
- bool validateArray(
528
- FieldInfo *type,
529
- VALUE arr,
530
- bool recursive,
531
- VALUE outer_struct,
532
- VALUE field_sym) {
533
- long length = RARRAY_LEN(arr);
534
- for (long i = 0; i < length; i++) {
535
- if (!validateAny(type, rb_ary_entry(arr, i), recursive, outer_struct, field_sym)) {
536
- return false;
537
- }
538
- }
539
- return true;
540
- }
541
-
542
- #define TEST_RB_VAL_FOR_CLASS(VAL, KLASS) \
543
- if (!RTEST(rb_obj_is_kind_of(VAL, KLASS))) { \
544
- raise_type_mismatch(outer_struct, field_sym); \
545
- ret = false; \
546
- }
547
-
548
- #define HANDLE_TYPE(TYPE, KLASS) \
549
- case protocol::T_##TYPE: { \
550
- TEST_RB_VAL_FOR_CLASS(val, KLASS) \
551
- break; \
552
- }
553
-
554
- bool validateAny(FieldInfo *type, VALUE val, bool recursive, VALUE outer_struct, VALUE field_sym) {
555
- bool ret = true;
556
- switch (type->ftype) {
557
-
558
- HANDLE_TYPE(BYTE, klass_for_integer)
559
- HANDLE_TYPE(I16, klass_for_integer)
560
- HANDLE_TYPE(I32, klass_for_integer)
561
- HANDLE_TYPE(I64, klass_for_integer)
562
- HANDLE_TYPE(DOUBLE, klass_for_float)
563
- HANDLE_TYPE(STRING, klass_for_string)
564
-
565
- case protocol::T_BOOL: {
566
- if ( !(val == Qtrue || val == Qfalse) ) {
567
- raise_type_mismatch(outer_struct, field_sym);
568
- ret = false;
569
- }
570
- break;
571
- }
572
-
573
- case protocol::T_STRUCT: {
574
- TEST_RB_VAL_FOR_CLASS(val, type->klass)
575
- if (ret && recursive) {
576
- ret = validateStruct(type->klass, val, true, recursive);
577
- }
578
- break;
579
- }
580
-
581
- case protocol::T_SET: {
582
- TEST_RB_VAL_FOR_CLASS(val, klass_for_set)
583
- if (ret) {
584
- VALUE ary = rb_funcall(val, intern_for_to_a, 0);
585
- ret = validateArray(type->elementType, ary, recursive, outer_struct, field_sym);
586
- }
587
- break;
588
- }
589
- case protocol::T_LIST: {
590
- TEST_RB_VAL_FOR_CLASS(val, klass_for_array)
591
- if (ret) {
592
- ret = validateArray(type->elementType, val, recursive, outer_struct, field_sym);
593
- }
594
- break;
595
- }
596
-
597
- case protocol::T_MAP: {
598
- TEST_RB_VAL_FOR_CLASS(val, klass_for_hash)
599
- if (ret) {
600
- bool flag = true;
601
- HASH_FOREACH_BEGIN(val, &flag, type->keyType, type->elementType,
602
- &recursive, &outer_struct, &field_sym)
603
- bool *flag = (bool *)argv[0], *recursive = (bool *)argv[3];
604
- VALUE *outer_struct = (VALUE *)argv[4], *field_sym = (VALUE *)argv[5];
605
- FieldInfo *field_info_key = (FieldInfo *)argv[1];
606
- FieldInfo *field_info_value = (FieldInfo *)argv[2];
607
- if (!validateAny(field_info_key, k, *recursive, *outer_struct, *field_sym) ||
608
- !validateAny(field_info_value, v, *recursive, *outer_struct, *field_sym)) {
609
- *flag = false;
610
- HASH_FOREACH_ABORT()
611
- }
612
- HASH_FOREACH_RET()
613
- HASH_FOREACH_END()
614
- }
615
- break;
616
- }
617
-
618
- default: {
619
- rb_raise(SparsamUnknownTypeException, "Unknown type received.");
620
- ret = false;
621
- break;
622
- }
623
- }
624
- return ret;
625
- }
626
- #undef HANDLE_TYPE
627
- #undef TEST_RB_VAL_FOR_CLASS
628
-
629
- bool validateStruct(VALUE klass, VALUE data, bool validateContainerTypes,
630
- bool recursive) {
631
- if (!RTEST(rb_obj_is_kind_of(data, klass))) {
632
- rb_raise(SparsamTypeMismatchError, "Wrong type of struct given for data");
633
- return false;
634
- }
635
- auto fields = FindOrCreateFieldInfoMap(klass);
636
- for (auto const &entry : *fields) {
637
- VALUE val = rb_ivar_get(data, entry.second->ivarName);
638
- if (NIL_P(val)) {
639
- if (!entry.second->isOptional) {
640
- raise_exc_with_struct_and_field_names(
641
- SparsamMissingMandatory,
642
- rb_sprintf("Missing: fieldID %d", entry.first),
643
- klass,
644
- entry.second->symName);
645
- return false;
646
- }
647
- continue;
648
- }
649
- if (validateContainerTypes &&
650
- !validateAny(entry.second, val, recursive, data, entry.second->symName)) {
651
- return false;
652
- }
653
- }
654
- return true;
655
- }
656
-
657
- VALUE serializer_validate(VALUE self, VALUE klass, VALUE data,
658
- VALUE strictness) {
659
- switch (static_cast<ValidateStrictness>(FIX2INT(strictness))) {
660
- case strict: {
661
- return validateStruct(klass, data, true, false) ? Qtrue : Qfalse;
662
- }
663
- case recursive: {
664
- return validateStruct(klass, data, true, true) ? Qtrue : Qfalse;
665
- }
666
- default: {
667
- return validateStruct(klass, data, false, false) ? Qtrue : Qfalse;
668
- }
669
- }
670
- }
671
-
672
657
  #define R_FIX_TO_TTYPE(x) (static_cast<TType>(FIX2INT(x)))
673
658
 
674
659
  FieldInfoMap *FindOrCreateFieldInfoMap(VALUE klass) {
@@ -689,7 +674,7 @@ ID field_name_to_ivar_id(VALUE str_name) {
689
674
  if (str_name != Qnil) {
690
675
  return rb_intern_str(rb_str_concat(rb_str_new2("@"), str_name));
691
676
  } else {
692
- return NULL;
677
+ return 0;
693
678
  }
694
679
  }
695
680
 
@@ -697,7 +682,7 @@ VALUE field_name_to_sym(VALUE str_name) {
697
682
  if (str_name != Qnil) {
698
683
  return ID2SYM(rb_intern_str(str_name));
699
684
  } else {
700
- return NULL;
685
+ return 0;
701
686
  }
702
687
  }
703
688
 
data/ext/serializer.h CHANGED
@@ -85,14 +85,11 @@ public:
85
85
  private:
86
86
  VALUE readUnion(VALUE klass);
87
87
  VALUE readAny(TType ttype, FieldInfo *field_info);
88
- void writeAny(TType ttype, FieldInfo *field_info, VALUE data);
88
+ void writeAny(TType ttype, FieldInfo *field_info, VALUE data, VALUE outer_struct, VALUE field_sym);
89
89
  void skip_n_type(uint32_t n, TType ttype);
90
90
  void skip_n_pair(uint32_t n, TType type_a, TType type_b);
91
91
  };
92
92
 
93
- bool validateStruct(VALUE klass, VALUE data, bool validateContainerTypes,
94
- bool recursive);
95
- bool validateAny(FieldInfo *type, VALUE val, bool recursive, VALUE outer_struct, VALUE field_sym);
96
93
  FieldInfoMap *FindOrCreateFieldInfoMap(VALUE klass);
97
94
  FieldInfo *CreateFieldInfo(VALUE field_map_entry);
98
95
  FieldInfoMap *CreateFieldInfoMap(VALUE klass);
data/lib/sparsam.rb CHANGED
@@ -8,3 +8,11 @@ require 'sparsam/union'
8
8
  require 'sparsam/deserializer'
9
9
 
10
10
  Sparsam.init!
11
+
12
+ module Sparsam
13
+ # Deprecated
14
+ def self.validate(klass, data, strictness)
15
+ data.serialize
16
+ true
17
+ end
18
+ end
@@ -23,22 +23,9 @@ module Sparsam
23
23
  def self.generate_accessors(klass)
24
24
  klass::FIELDS.each do |field_key, field_info|
25
25
  field_accessor(klass, field_key, field_info)
26
- qmark_isset_method(klass, field_info)
27
26
  end
28
27
  end
29
28
 
30
- # TODO(Ben Hughes): Do we ever use those, these are an unexpected
31
- # definition of predicate accessors
32
- def self.qmark_isset_method(klass, field_info)
33
- field_name = field_info[:name]
34
-
35
- klass.class_eval(<<-EOF, __FILE__, __LINE__)
36
- def #{field_name}?
37
- !#{field_name}.nil?
38
- end
39
- EOF
40
- end
41
-
42
29
  def self.generate_default_values(klass)
43
30
  fields_with_default_values = {}
44
31
  klass::FIELDS.each do |fid, field_def|
data/lib/sparsam/types.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  # -*- coding: UTF-8 -*-
2
2
  require 'set'
3
- require 'sparsam/exceptions'
4
3
 
5
4
  module Sparsam
6
5
  module Types
@@ -25,64 +24,6 @@ module Sparsam
25
24
  ]).freeze
26
25
  end
27
26
 
28
- # Deprecated type checking
29
-
30
- def self.check_type(value, field, name, skip_nil = true)
31
- return if value.nil? && skip_nil
32
-
33
- valid =
34
- case field[:type]
35
- when Types::VOID
36
- nil === value
37
- when Types::BOOL
38
- true === value || false === value
39
- when Types::BYTE, Types::I16, Types::I32, Types::I64
40
- Integer === value
41
- when Types::DOUBLE
42
- Float === value
43
- when Types::STRING
44
- String === value
45
- when Types::STRUCT
46
- Struct === value || Union === value
47
- when Types::MAP
48
- Hash === value
49
- when Types::SET
50
- Set === value
51
- when Types::LIST
52
- Array === value
53
- else
54
- false
55
- end
56
-
57
- unless valid
58
- raise TypeMismatch, "Expected #{type_name(field[:type])}, " \
59
- "received #{value.class} for field #{name}"
60
- end
61
-
62
- # check elements now
63
- case field[:type]
64
- when Types::MAP
65
- # This is still allocations per MAP, but better than per map entry
66
- key_str = "#{name}.key"
67
- value_str = "#{name}.value"
68
-
69
- value.each_pair do |k, v|
70
- check_type(k, field[:key], key_str, false)
71
- check_type(v, field[:value], value_str, false)
72
- end
73
- when Types::SET, Types::LIST
74
- element_str = "#{name}.element"
75
-
76
- value.each do |el|
77
- check_type(el, field[:element], element_str, false)
78
- end
79
- when Types::STRUCT
80
- unless field[:class] == value.class
81
- raise TypeMismatch, "Expected #{field[:class]}, received #{value.class} for field #{name}"
82
- end
83
- end
84
- end
85
-
86
27
  TYPE_NAME_SYM_MAPPING = Types.constants.each_with_object({}) do |const, h|
87
28
  h[Types.const_get(const)] = const.to_sym
88
29
  end
@@ -98,11 +39,4 @@ module Sparsam
98
39
  def self.type_name(type)
99
40
  TYPE_NAME_MAPPING[type]
100
41
  end
101
-
102
- module MessageTypes
103
- CALL = 1
104
- REPLY = 2
105
- EXCEPTION = 3
106
- ONEWAY = 4
107
- end
108
42
  end
data/spec/sparsam_spec.rb CHANGED
@@ -361,7 +361,6 @@ describe 'Sparsam' do
361
361
  struct: US.new(id_i32: 10),
362
362
  union: UN.new(id_s: "woo"),
363
363
  complex: Complex(1),
364
- bigint: 2**128,
365
364
  rational: Rational(2, 3),
366
365
  }
367
366
 
@@ -398,9 +397,47 @@ describe 'Sparsam' do
398
397
  )
399
398
  end
400
399
 
401
- begin
400
+ expect {
402
401
  s.serialize
403
- rescue TypeError, RangeError, NoMethodError, Sparsam::TypeMismatch
402
+ }.to(
403
+ raise_error(Sparsam::TypeMismatch),
404
+ "assigning #{field} : #{type} a value of " \
405
+ "#{val.inspect} : #{val_type} did not raise TypeMismatch"
406
+ )
407
+ end
408
+ end
409
+ end
410
+
411
+ unless RUBY_VERSION =~ /^1\.9/
412
+ it "handles integer ranges" do
413
+ fields = {
414
+ a_byte: 8,
415
+ an_i16: 16,
416
+ an_i32: 32,
417
+ an_i64: 64,
418
+ }
419
+
420
+ fields.each do |field, size|
421
+ s = EveryType.new
422
+
423
+ max_val = 2**(size - 1) - 1
424
+
425
+ [max_val, ~max_val].each do |val|
426
+ s.send(:"#{field}=", val)
427
+
428
+ expect {
429
+ s.serialize
430
+ }.not_to raise_error, "#{field} of #{size} bits unable to hold #{val}"
431
+ end
432
+
433
+ [max_val + 1, ~(max_val + 1)].each do |val|
434
+ s.send(:"#{field}=", val)
435
+ expect {
436
+ s.serialize
437
+ }.to(
438
+ raise_error(RangeError),
439
+ "#{field} of #{size} bits apparently able to hold value #{val} in defiance of nature"
440
+ )
404
441
  end
405
442
  end
406
443
  end
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.1.5
4
+ version: 0.2.0
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: 2017-08-04 00:00:00.000000000 Z
11
+ date: 2017-08-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec