subnets 1.0.0pre1 → 1.0.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
  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