subnets 1.0.0pre1 → 1.0.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
  SHA256:
3
- metadata.gz: 54f0c79b3c0859e0d9cd2758276652d48fd0ceeece739695691b76c5cb8d01a7
4
- data.tar.gz: 69b64044d769ede44735081a0411b088cf3016bf6a4a732238c5996c105e5e19
3
+ metadata.gz: 17cca826fc5397edbbf19b80546c22487603991ce8138b71905cccebb2ddb9dd
4
+ data.tar.gz: c13ca13ebc0cf9821555974921c6d9e8ac80e779a087d9a43703b4c74f9dde37
5
5
  SHA512:
6
- metadata.gz: ceebcd95e1fb22ee86acf2c4eb606c3deda2a97c04a7f57d0e97f5493974441855f3e7a04e2525e6b4ff1a88f6508df29b548bebcfca36dceb0ee4384ab76f82
7
- data.tar.gz: ac0e808b3e42227f53881eed50a807e136a0b2602f0402bda120a42f9cc78d16ce64029cd2d5aa2e6fd9456dfb797411fe5496c6fda5321528e4cd39a828e591
6
+ metadata.gz: 4403041659c6f4420a47f042f97e349df8493885bbb7a2b640ddb87889bb3ebec8fb910a4c02d23bbaecf03abefc97339bb220eeb6d693a9826330ccdb51b570
7
+ data.tar.gz: daa48990aab7c42e05b41428dbaf2dbbdc94831ca60634ec2b42cd36772ea67b4c15a4fdab3f92f0a1d2b558e985c144eddf026057469aec37b15a13350b239a
data/README.md CHANGED
@@ -72,9 +72,9 @@ This has not been used in production.
72
72
  ## Safe?
73
73
 
74
74
  The IPv4 and IPv6 parsers are written in C. In addition to the unit
75
- test suite, the parsers have had minimal (8+ hours) of fuzzing with
76
- [American fuzzy lop](http://lcamtuf.coredump.cx/afl/). There is low
77
- confidence in the parsers.
75
+ test suite, the parsers have had minimal (16+ hours) of fuzzing with
76
+ [American fuzzy lop](http://lcamtuf.coredump.cx/afl/). There is medium
77
+ confidence that the parsers will not read out-of-bounds.
78
78
 
79
79
  ## Correct?
80
80
 
@@ -24,22 +24,23 @@ VALUE rb_intern_xor = Qnil;
24
24
  } \
25
25
  } while (0)
26
26
 
27
+ #define MIN(a,b) ((a) > (b) ? (b) : (a))
28
+
27
29
  /**
28
30
  * ParseError indicates the input string could not be parsed as the
29
31
  * requested type.
30
32
  */
31
33
  VALUE ParseError = Qnil;
32
34
 
33
- VALUE
34
- raise_parse_error(const char *type, const char *data) {
35
- /* 49 is longest possible ip6 cidr */
36
- /* ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128 */
37
- if (strlen(data) > 49) {
38
- rb_raise(ParseError, "failed to parse as %s: '%.45s...'", type, data);
39
- } else {
40
- rb_raise(ParseError, "failed to parse as %s: '%s'", type, data);
41
- }
42
- }
35
+ /* 49 is longest possible ip6 cidr */
36
+ /* ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128 */
37
+ #define raise_parse_error(type, data) do { \
38
+ if (strlen(data) > 49) { \
39
+ rb_raise(ParseError, "failed to parse as %s: '%.45s...'", (type), (data)); \
40
+ } else { \
41
+ rb_raise(ParseError, "failed to parse as %s: '%s'", (type), (data)); \
42
+ } \
43
+ } while (0)
43
44
 
44
45
  VALUE
45
46
  ip4_new(VALUE class, ip4_t src) {
@@ -82,6 +83,21 @@ method_ip4_new(VALUE class, VALUE address) {
82
83
  return ip4_new(class, RB_NUM2UINT(address));
83
84
  }
84
85
 
86
+ VALUE
87
+ method_ip6_new(VALUE class, VALUE hextets) {
88
+ ip6_t ip;
89
+
90
+ if (RARRAY_LEN(hextets) != 8) {
91
+ rb_raise(rb_eArgError, "hextets must be size=8, was %ld", RARRAY_LEN(hextets));
92
+ }
93
+
94
+ for (ssize_t i = 0; i < RARRAY_LEN(hextets); i++) {
95
+ ip.x[i] = NUM2INT(RARRAY_AREF(hextets, i)) & 0xffff;
96
+ }
97
+
98
+ return ip6_new(class, ip);
99
+ }
100
+
85
101
  VALUE
86
102
  method_net4_new(VALUE class, VALUE address, VALUE prefixlen) {
87
103
  net4_t net;
@@ -171,14 +187,14 @@ method_net6_parse(VALUE class, VALUE s) {
171
187
  VALUE
172
188
  method_ip4_random(int argc, VALUE *argv, VALUE class) {
173
189
  ip4_t ip;
174
- VALUE rng;
190
+ VALUE rng, rand;
175
191
 
176
192
  rb_scan_args(argc, argv, "01", &rng);
177
193
  if (Qnil == rng) {
178
194
  rng = rb_funcall(rb_cRandom, rb_intern("new"), 0);
179
195
  }
180
196
 
181
- VALUE rand = rb_intern("rand");
197
+ rand = rb_intern("rand");
182
198
  ip = FIX2INT(rb_funcall(rng, rand, 1, INT2FIX(0xffff+1)));
183
199
  ip |= FIX2INT(rb_funcall(rng, rand, 1, INT2FIX(0xffff+1))) << 16;
184
200
 
@@ -193,14 +209,14 @@ method_ip4_random(int argc, VALUE *argv, VALUE class) {
193
209
  VALUE
194
210
  method_net4_random(int argc, VALUE *argv, VALUE class) {
195
211
  net4_t net;
196
- VALUE rng;
212
+ VALUE rng, rand;
197
213
 
198
214
  rb_scan_args(argc, argv, "01", &rng);
199
215
  if (Qnil == rng) {
200
216
  rng = rb_funcall(rb_cRandom, rb_intern("new"), 0);
201
217
  }
202
218
 
203
- VALUE rand = rb_intern("rand");
219
+ rand = rb_intern("rand");
204
220
  net.address = FIX2INT(rb_funcall(rng, rand, 1, INT2FIX(0xffff+1)));
205
221
  net.address |= FIX2INT(rb_funcall(rng, rand, 1, INT2FIX(0xffff+1))) << 16;
206
222
  net.prefixlen = FIX2INT(rb_funcall(rng, rb_intern("rand"), 1, INT2FIX(32+1)));
@@ -211,13 +227,15 @@ method_net4_random(int argc, VALUE *argv, VALUE class) {
211
227
 
212
228
  void
213
229
  ip6_fill_random(ip6_t *ip, VALUE rng, VALUE opts) {
230
+ VALUE rand;
231
+ int pre, zeros;
232
+
214
233
  if (Qnil == rng) {
215
234
  rng = rb_funcall(rb_cRandom, rb_intern("new"), 0);
216
235
  }
217
236
 
218
- VALUE rand = rb_intern("rand");
219
- int pre, zeros;
220
-
237
+ rand = rb_intern("rand");
238
+
221
239
  if (Qnil != opts && RTEST(rb_hash_aref(opts, ID2SYM(rb_intern("zeros"))))) {
222
240
  pre = FIX2INT(rb_funcall(rng, rand, 1, INT2FIX(8+1)));
223
241
  zeros = FIX2INT(rb_funcall(rng, rand, 1, INT2FIX(8+1 - pre)));
@@ -276,6 +294,9 @@ method_net6_random(int argc, VALUE *argv, VALUE class) {
276
294
  return net6_new(class, net);
277
295
  }
278
296
 
297
+ /**
298
+ * @return [IP4] bitwise NOT of +self+
299
+ */
279
300
  VALUE
280
301
  method_ip4_not(VALUE self) {
281
302
  ip4_t *ip;
@@ -283,6 +304,10 @@ method_ip4_not(VALUE self) {
283
304
  return ip4_new(IP4, ~ *ip);
284
305
  }
285
306
 
307
+ /**
308
+ * @param other [Subnets::IP4]
309
+ * @return [Subnets::IP4] bitwise OR of +self+ and +other+
310
+ */
286
311
  VALUE
287
312
  method_ip4_bor(VALUE self, VALUE other) {
288
313
  ip4_t *a, *b;
@@ -294,6 +319,10 @@ method_ip4_bor(VALUE self, VALUE other) {
294
319
  return ip4_new(IP4, *a | *b);
295
320
  }
296
321
 
322
+ /**
323
+ * @param other [Subnets::IP4]
324
+ * @return [Subnets::IP4] bitwise exclusive XOR of +self+ and +other+
325
+ */
297
326
  VALUE
298
327
  method_ip4_xor(VALUE self, VALUE other) {
299
328
  ip4_t *a, *b;
@@ -305,6 +334,10 @@ method_ip4_xor(VALUE self, VALUE other) {
305
334
  return ip4_new(IP4, *a ^ *b);
306
335
  }
307
336
 
337
+ /**
338
+ * @param other [Subnets::IP4]
339
+ * @return [Subnets::IP4] bitwise AND of +self+ and +other+
340
+ */
308
341
  VALUE
309
342
  method_ip4_band(VALUE self, VALUE other) {
310
343
  ip4_t *a, *b;
@@ -316,6 +349,9 @@ method_ip4_band(VALUE self, VALUE other) {
316
349
  return ip4_new(IP4, *a & *b);
317
350
  }
318
351
 
352
+ /**
353
+ * @return [Subnets::IP6] bitwise NOT of +self+
354
+ */
319
355
  VALUE
320
356
  method_ip6_not(VALUE self) {
321
357
  ip6_t *ip;
@@ -323,6 +359,10 @@ method_ip6_not(VALUE self) {
323
359
  return ip6_new(IP6, ip6_not(*ip));
324
360
  }
325
361
 
362
+ /**
363
+ * @param other [Subnets::IP6]
364
+ * @return [Subnets::IP4] bitwise OR of +self+ and +other+
365
+ */
326
366
  VALUE
327
367
  method_ip6_bor(VALUE self, VALUE other) {
328
368
  ip6_t *a, *b;
@@ -335,6 +375,10 @@ method_ip6_bor(VALUE self, VALUE other) {
335
375
  return ip6_new(IP6, ip6_bor(*a, *b));
336
376
  }
337
377
 
378
+ /**
379
+ * @param other [Subnets::IP6]
380
+ * @return [Subnets::IP4] bitwise XOR of +self+ and +other+
381
+ */
338
382
  VALUE
339
383
  method_ip6_xor(VALUE self, VALUE other) {
340
384
  ip6_t *a, *b;
@@ -347,6 +391,10 @@ method_ip6_xor(VALUE self, VALUE other) {
347
391
  return ip6_new(IP6, ip6_xor(*a, *b));
348
392
  }
349
393
 
394
+ /**
395
+ * @param other [Subnets::IP6]
396
+ * @return [Subnets::IP4] bitwise AND of +self+ and +other+
397
+ */
350
398
  VALUE
351
399
  method_ip6_band(VALUE self, VALUE other) {
352
400
  ip6_t *a, *b;
@@ -480,10 +528,9 @@ method_net6_include_p(VALUE self, VALUE v) {
480
528
  VALUE
481
529
  method_ip4_to_s(VALUE self) {
482
530
  ip4_t *ip;
483
- Data_Get_Struct(self, ip4_t, ip);
484
-
485
531
  char buf[16];
486
532
 
533
+ Data_Get_Struct(self, ip4_t, ip);
487
534
  ip4_snprint(*ip, buf, 16);
488
535
  return rb_str_new2(buf);
489
536
  }
@@ -497,10 +544,9 @@ method_ip4_to_s(VALUE self) {
497
544
  VALUE
498
545
  method_ip6_to_s(VALUE self) {
499
546
  ip6_t *ip;
500
- Data_Get_Struct(self, ip6_t, ip);
501
-
502
547
  char buf[64];
503
548
 
549
+ Data_Get_Struct(self, ip6_t, ip);
504
550
  ip6_snprint(*ip, buf, 64);
505
551
  return rb_str_new2(buf);
506
552
  }
@@ -513,10 +559,9 @@ method_ip6_to_s(VALUE self) {
513
559
  VALUE
514
560
  method_net4_to_s(VALUE self) {
515
561
  net4_t *net;
516
- Data_Get_Struct(self, net4_t, net);
517
-
518
562
  char buf[32];
519
563
 
564
+ Data_Get_Struct(self, net4_t, net);
520
565
  net4_snprint(*net, buf, 32);
521
566
  return rb_str_new2(buf);
522
567
  }
@@ -529,14 +574,16 @@ method_net4_to_s(VALUE self) {
529
574
  VALUE
530
575
  method_net6_to_s(VALUE self) {
531
576
  net6_t *net;
532
- Data_Get_Struct(self, net6_t, net);
533
-
534
577
  char buf[64];
535
578
 
579
+ Data_Get_Struct(self, net6_t, net);
536
580
  net6_snprint(*net, buf, 64);
537
581
  return rb_str_new2(buf);
538
582
  }
539
583
 
584
+ /**
585
+ * @return [Numeric] the 32 bit integer representing this address
586
+ */
540
587
  VALUE
541
588
  method_ip4_to_i(VALUE self) {
542
589
  ip4_t *ip;
@@ -544,14 +591,19 @@ method_ip4_to_i(VALUE self) {
544
591
  return RB_UINT2NUM(*ip);
545
592
  }
546
593
 
594
+ /**
595
+ * @return [Numeric] the 128 bit integer representing this address
596
+ */
547
597
  VALUE
548
598
  method_ip6_to_i(VALUE self) {
549
599
  VALUE ret;
550
600
  ip6_t *ip;
601
+ ID lshift, plus;
602
+
551
603
  Data_Get_Struct(self, ip6_t, ip);
552
604
 
553
- ID lshift = rb_intern("<<");
554
- ID plus = rb_intern("+");
605
+ lshift = rb_intern("<<");
606
+ plus = rb_intern("+");
555
607
 
556
608
  ret = RB_INT2NUM(0);
557
609
 
@@ -569,18 +621,16 @@ method_ip6_to_i(VALUE self) {
569
621
  */
570
622
  VALUE
571
623
  method_ip4_eql_p(VALUE self, VALUE other) {
624
+ ip4_t *a, *b;
625
+
572
626
  if (CLASS_OF(other) != CLASS_OF(self)) {
573
627
  return Qfalse;
574
628
  }
575
629
 
576
- ip4_t *a, *b;
577
630
  Data_Get_Struct(self, ip4_t, a);
578
631
  Data_Get_Struct(other, ip4_t, b);
579
632
 
580
- if (a != b) {
581
- return Qfalse;
582
- }
583
- return Qtrue;
633
+ return (*a == *b) ? Qtrue : Qfalse;
584
634
  }
585
635
 
586
636
  /**
@@ -588,11 +638,12 @@ method_ip4_eql_p(VALUE self, VALUE other) {
588
638
  */
589
639
  VALUE
590
640
  method_net4_eql_p(VALUE self, VALUE other) {
641
+ net4_t *a, *b;
642
+
591
643
  if (CLASS_OF(other) != CLASS_OF(self)) {
592
644
  return Qfalse;
593
645
  }
594
646
 
595
- net4_t *a, *b;
596
647
  Data_Get_Struct(self, net4_t, a);
597
648
  Data_Get_Struct(other, net4_t, b);
598
649
 
@@ -610,11 +661,12 @@ method_net4_eql_p(VALUE self, VALUE other) {
610
661
  */
611
662
  VALUE
612
663
  method_ip6_eql_p(VALUE self, VALUE other) {
664
+ ip6_t *a, *b;
665
+
613
666
  if (CLASS_OF(other) != CLASS_OF(self)) {
614
667
  return Qfalse;
615
668
  }
616
669
 
617
- ip6_t *a, *b;
618
670
  Data_Get_Struct(self, ip6_t, a);
619
671
  Data_Get_Struct(other, ip6_t, b);
620
672
 
@@ -626,11 +678,12 @@ method_ip6_eql_p(VALUE self, VALUE other) {
626
678
  */
627
679
  VALUE
628
680
  method_net6_eql_p(VALUE self, VALUE other) {
681
+ net6_t *a, *b;
682
+
629
683
  if (CLASS_OF(other) != CLASS_OF(self)) {
630
684
  return Qfalse;
631
685
  }
632
686
 
633
- net6_t *a, *b;
634
687
  Data_Get_Struct(self, net6_t, a);
635
688
  Data_Get_Struct(other, net6_t, b);
636
689
 
@@ -651,7 +704,7 @@ VALUE
651
704
  method_ip4_hash(VALUE self) {
652
705
  ip4_t *ip;
653
706
  Data_Get_Struct(self, ip4_t, ip);
654
- return hash(UINT2NUM(ip));
707
+ return hash(UINT2NUM(*ip));
655
708
  }
656
709
 
657
710
  /**
@@ -670,9 +723,11 @@ method_net4_hash(VALUE self) {
670
723
  VALUE
671
724
  method_ip6_hash(VALUE self) {
672
725
  ip6_t *ip;
726
+ VALUE ret;
727
+
673
728
  Data_Get_Struct(self, ip6_t, ip);
674
729
 
675
- VALUE ret = hash(INT2FIX(ip->x[0]));
730
+ ret = hash(INT2FIX(ip->x[0]));
676
731
  for (int i=1; i<8; i++) {
677
732
  ret = xor(ret, hash(INT2FIX(ip->x[i])));
678
733
  }
@@ -685,9 +740,11 @@ method_ip6_hash(VALUE self) {
685
740
  VALUE
686
741
  method_net6_hash(VALUE self) {
687
742
  net6_t *net;
743
+ VALUE ret;
744
+
688
745
  Data_Get_Struct(self, net6_t, net);
689
746
 
690
- VALUE ret = hash(INT2FIX(net->prefixlen));
747
+ ret = hash(INT2FIX(net->prefixlen));
691
748
  for (int i=0; i<8; i++) {
692
749
  ret = xor(ret, hash(INT2FIX(net->address.x[i])));
693
750
  }
@@ -736,9 +793,11 @@ method_net6_mask(VALUE self) {
736
793
  VALUE
737
794
  method_ip6_hextets(VALUE self) {
738
795
  ip6_t *ip;
796
+ VALUE hextets;
797
+
739
798
  Data_Get_Struct(self, ip6_t, ip);
740
799
 
741
- VALUE hextets = rb_ary_new();
800
+ hextets = rb_ary_new();
742
801
  for (int i=0; i<8; i++) {
743
802
  rb_ary_push(hextets, INT2FIX(ip->x[i]));
744
803
  }
@@ -751,9 +810,11 @@ method_ip6_hextets(VALUE self) {
751
810
  VALUE
752
811
  method_net6_hextets(VALUE self) {
753
812
  net6_t *net;
813
+ VALUE hextets;
814
+
754
815
  Data_Get_Struct(self, net6_t, net);
755
816
 
756
- VALUE hextets = rb_ary_new();
817
+ hextets = rb_ary_new();
757
818
  for (int i=0; i<8; i++) {
758
819
  rb_ary_push(hextets, INT2FIX(net->address.x[i]));
759
820
  }
@@ -771,11 +832,11 @@ method_net4_summarize(VALUE class, VALUE nets) {
771
832
  net4_t result;
772
833
 
773
834
  for (ssize_t i = 0; i < RARRAY_LEN(nets); i++) {
835
+ const net4_t *net;
774
836
  VALUE rbnet = RARRAY_AREF(nets, i);
775
837
 
776
838
  assert_kind_of(rbnet, Net4);
777
839
 
778
- const net4_t *net;
779
840
  Data_Get_Struct(rbnet, net4_t, net);
780
841
 
781
842
  if (i == 0) {
@@ -783,14 +844,9 @@ method_net4_summarize(VALUE class, VALUE nets) {
783
844
  result.prefixlen = net->prefixlen;
784
845
  result.mask = net->mask;
785
846
  } else {
786
- if (result.prefixlen > net->prefixlen) {
787
- result.prefixlen = net->prefixlen;
788
- result.mask = net->mask;
789
- result.address &= result.mask;
790
- }
791
-
792
- while (result.address != (net->address & result.mask)) {
793
- result.prefixlen -= 1;
847
+ while (result.prefixlen > net->prefixlen ||
848
+ result.address != (net->address & result.mask)) {
849
+ result.prefixlen = MIN(result.prefixlen-1, net->prefixlen);
794
850
  result.mask = mk_mask4(result.prefixlen);
795
851
  result.address &= result.mask;
796
852
  }
@@ -811,11 +867,11 @@ method_net6_summarize(VALUE class, VALUE nets) {
811
867
  net6_t result;
812
868
 
813
869
  for (ssize_t i = 0; i < RARRAY_LEN(nets); i++) {
870
+ net6_t *net;
814
871
  VALUE rbnet = RARRAY_AREF(nets, i);
815
872
 
816
873
  assert_kind_of(rbnet, Net6);
817
874
 
818
- net6_t *net;
819
875
  Data_Get_Struct(rbnet, net6_t, net);
820
876
 
821
877
  if (i == 0) {
@@ -823,14 +879,9 @@ method_net6_summarize(VALUE class, VALUE nets) {
823
879
  result.prefixlen = net->prefixlen;
824
880
  result.mask = net->mask;
825
881
  } else {
826
- if (result.prefixlen > net->prefixlen) {
827
- result.prefixlen = net->prefixlen;
828
- result.mask = net->mask;
829
- result.address = ip6_band(result.address, result.mask);
830
- }
831
-
832
- while(!ip6_eql_p(result.address, ip6_band(net->address, result.mask))) {
833
- result.prefixlen -= 1;
882
+ while(result.prefixlen > net->prefixlen ||
883
+ !ip6_eql_p(result.address, ip6_band(net->address, result.mask))) {
884
+ result.prefixlen = MIN(result.prefixlen-1, net->prefixlen);
834
885
  result.mask = mk_mask6(result.prefixlen);
835
886
  result.address = ip6_band(result.address, result.mask);
836
887
  }
@@ -848,8 +899,9 @@ method_net6_summarize(VALUE class, VALUE nets) {
848
899
  */
849
900
  VALUE
850
901
  method_subnets_parse(VALUE mod, VALUE str) {
902
+ const char *s;
851
903
  str = StringValue(str);
852
- const char *s = StringValueCStr(str);
904
+ s = StringValueCStr(str);
853
905
  {
854
906
  net4_t net;
855
907
  if (read_net4_strict(s, &net)) return net4_new(Net4, net);
@@ -1019,6 +1071,7 @@ void Init_Subnets() {
1019
1071
  // Subnets::IP6
1020
1072
  IP6 = rb_define_class_under(Subnets, "IP6", IP);
1021
1073
  rb_define_singleton_method(IP6, "random", method_ip6_random, -1);
1074
+ rb_define_singleton_method(IP6, "new", method_ip6_new, 1);
1022
1075
  rb_define_method(IP6, "==", method_ip6_eql_p, 1);
1023
1076
  rb_define_alias(IP6, "eql?", "==");
1024
1077
  rb_define_method(IP6, "hash", method_ip6_hash, 0);
@@ -12,9 +12,11 @@
12
12
 
13
13
  ip4_t
14
14
  mk_mask4(int prefixlen) {
15
+ int shift;
16
+
15
17
  if (prefixlen==0) return 0;
16
18
 
17
- int shift = 32 - prefixlen;
19
+ shift = 32 - prefixlen;
18
20
  return (~((ip4_t) 0) >> shift) << shift;
19
21
  }
20
22
 
@@ -309,6 +311,7 @@ read_ip6(const char *s, ip6_t *a) {
309
311
  int i = 0;
310
312
  size_t pos = 0;
311
313
  int brk = 8;
314
+ ip4_t ip4;
312
315
 
313
316
  /*
314
317
  * read optional leading hextet followed by zero or more
@@ -337,7 +340,6 @@ read_ip6(const char *s, ip6_t *a) {
337
340
  return 0;
338
341
  }
339
342
 
340
- ip4_t ip4;
341
343
  if ((i==6 || (brk<8 && i<4)) && (n = read_ip4(s+pos, &ip4))) {
342
344
  pos += n;
343
345
  hextets[i] = (ip4 >> 16) & 0xffff;
@@ -430,11 +432,11 @@ read_net6_strict(const char *s, net6_t *net) {
430
432
  size_t
431
433
  read_net6(const char *s, net6_t *net) {
432
434
  size_t pos;
435
+ int i, v = 0;
433
436
 
434
437
  pos = read_ip6(s, &net->address);
435
438
  if (!pos) return 0;
436
439
 
437
- int i, v = 0;
438
440
  if (s[pos++] != '/') return 0;
439
441
  for (i = 0; i < 3 && isdigit(s[pos+i]); i++) {
440
442
  v = v*10 + s[pos+i]-'0';
@@ -3,6 +3,10 @@ module EqlAndHash
3
3
  c.new(*constructor_args)
4
4
  end
5
5
 
6
+ def other_obj(c=klass)
7
+ c.new(*other_constructor_args)
8
+ end
9
+
6
10
  def new_obj_subclass
7
11
  new_obj(Class.new(klass))
8
12
  end
@@ -18,14 +22,18 @@ module EqlAndHash
18
22
  end
19
23
 
20
24
  def test_eq_string
25
+ refute_equal new_obj, other_obj
21
26
  refute_equal new_obj, 'str'
22
27
  end
23
28
 
24
29
  def test_hash
25
- a, b = [new_obj, new_obj]
30
+ a, b, = [new_obj, new_obj]
26
31
  refute_equal a.object_id, b.object_id
27
32
  assert_equal a.hash, b.hash
28
33
 
34
+ other = other_obj
35
+ refute_equal a.hash, other.hash
36
+
29
37
  h = {}
30
38
  h[a] = 'found'
31
39
  assert_equal 'found', h[a]
@@ -0,0 +1,19 @@
1
+ require 'test_helper'
2
+
3
+ module Subnets
4
+ class TestIP4 < Minitest::Test
5
+ include EqlAndHash
6
+
7
+ def klass
8
+ IP4
9
+ end
10
+
11
+ def constructor_args
12
+ [1]
13
+ end
14
+
15
+ def other_constructor_args
16
+ [345728]
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ require 'test_helper'
2
+
3
+ module Subnets
4
+ class TestIP6 < Minitest::Test
5
+ include EqlAndHash
6
+
7
+ # for EqlAndHash
8
+ def klass
9
+ IP6
10
+ end
11
+
12
+ # for EqlAndHash
13
+ def constructor_args
14
+ [[1,2,3,4,5,6,7,8]]
15
+ end
16
+
17
+ # for EqlAndHash
18
+ def other_constructor_args
19
+ [[5,5,5,5,5,5,5,5]]
20
+ end
21
+
22
+ end
23
+ end
24
+
@@ -12,7 +12,11 @@ module Subnets
12
12
  def constructor_args
13
13
  [1,24]
14
14
  end
15
-
15
+
16
+ def other_constructor_args
17
+ [345728,16]
18
+ end
19
+
16
20
  def test_new_creates_net4
17
21
  assert_instance_of Net4, Net4.new(1, 1)
18
22
  end
@@ -1,5 +1,4 @@
1
1
  require 'test_helper'
2
- require 'ipaddr'
3
2
 
4
3
  module Subnets
5
4
  class TestNet6 < Minitest::Test
@@ -15,7 +14,12 @@ module Subnets
15
14
  def constructor_args
16
15
  [[1,2,3,4,5,6,7,8], 96]
17
16
  end
18
-
17
+
18
+ # for EqlAndHash
19
+ def other_constructor_args
20
+ [[5,5,5,5,5,5,5,5], 122]
21
+ end
22
+
19
23
  class New < Minitest::Test
20
24
  def test_rejects_invalid_prefixlen
21
25
  assert_raises(ArgumentError) { Net6.new([0,0,0,0,0,0,0,0], 129) }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: subnets
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0pre1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Patrick Mahoney
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-20 00:00:00.000000000 Z
11
+ date: 2018-05-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -172,6 +172,8 @@ files:
172
172
  - test/private_networks_benchmark.rb
173
173
  - test/rack_ip_benchmark.rb
174
174
  - test/rails_remote_ip_benchmark.rb
175
+ - test/subnets/ip4_test.rb
176
+ - test/subnets/ip6_test.rb
175
177
  - test/subnets/net4_test.rb
176
178
  - test/subnets/net6_test.rb
177
179
  - test/subnets_test.rb
@@ -193,9 +195,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
193
195
  version: '0'
194
196
  required_rubygems_version: !ruby/object:Gem::Requirement
195
197
  requirements:
196
- - - ">"
198
+ - - ">="
197
199
  - !ruby/object:Gem::Version
198
- version: 1.3.1
200
+ version: '0'
199
201
  requirements: []
200
202
  rubyforge_project:
201
203
  rubygems_version: 2.7.6