sparsam 0.1.5 → 0.2.0

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
  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