ipaddress_2 0.12.1 → 0.13.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: 37bc348612c012d7c7d743d9a9b642df1ee7d22d1362bcb0cfd23bf129eb07c3
4
- data.tar.gz: 41b6893dc33205c71e0340838bc7fe6ec6a2faba3c6b18b0e3599304e3fbe15d
3
+ metadata.gz: cda18a11bce6a923e0471a7d08d6f8df8dae71d1ff768c6e0978772124be6f50
4
+ data.tar.gz: 47c24c1776bb9de0dedbec3179e42c22ed8ff4da96db53bcd95d8cb328bf2ca5
5
5
  SHA512:
6
- metadata.gz: 76ac4f4c0af074075402e6ab1032e0bd46b500963d3763ff39f106c871cf54ae25e2fb8b3dc5a9386d3cfb53f7b3197b5a42d3e505fa014d489715a6429b4d31
7
- data.tar.gz: 6f406303771c6a18470801ba35842fb36ff436e0d097b4971945ea3d02007c0f44349c18b3e3894affd338ba6d83ffa8f8ae7f1e9bd7650e8b3f6331585df3c2
6
+ metadata.gz: f9c69847cbf37301f1ded22d7bd4e97f0ab1040ff14d8f14993c414908872de88d06d6c25eecf1d153aaa22644038dcf3fb0fc2e4febf8be93e339b379b1f480
7
+ data.tar.gz: dbd02e8ed7d482b51873b45f443d92d7d11c78545ac20b9ba970745d3029c3d66c90aeb526dbf87f7bf95bd8a138ceb87e8621fba8d3e71dfadd591988b1fb35
@@ -1,5 +1,10 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## 0.13.0
4
+
5
+ ### Enhancements
6
+ * Provide arithmetic operations on IPv4 and IPv6
7
+
3
8
  ## 0.12.1
4
9
 
5
10
  ### Bugfix
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.12.1
1
+ 0.13.0
@@ -377,6 +377,18 @@ module IPAddress;
377
377
  def network
378
378
  self.class.parse_u32(network_u32, @prefix)
379
379
  end
380
+
381
+ #
382
+ # Returns a new IPv4 object containing only the host part of this IP.
383
+ #
384
+ # ip = IPAddress("172.16.10.64/24")
385
+ #
386
+ # ip.hostpart.to_s
387
+ # #=> "0.0.0.64"
388
+ #
389
+ def hostpart
390
+ self.class.parse_u32(hostpart_u32, 32)
391
+ end
380
392
 
381
393
  #
382
394
  # Returns a new IPv4 object with the
@@ -600,6 +612,18 @@ module IPAddress;
600
612
  def network_u32
601
613
  @u32 & @prefix.to_u32
602
614
  end
615
+
616
+ #
617
+ # Returns this address' host part in unsigned 32bits format
618
+ #
619
+ # ip = IPAddress("10.0.0.42/24")
620
+ #
621
+ # ip.host_u32
622
+ # #=> 42
623
+ #
624
+ def hostpart_u32
625
+ @u32 & ~@prefix.to_u32
626
+ end
603
627
 
604
628
  #
605
629
  # Returns the broadcast address in Unsigned 32bits format
@@ -886,6 +910,97 @@ module IPAddress;
886
910
  def +(oth)
887
911
  aggregate(*[self,oth].sort.map{|i| i.network})
888
912
  end
913
+
914
+ #
915
+ # Returns a new IPv4 object which is the result
916
+ # of advancing this IP address by a given value.
917
+ # In other words, this arithmetically adds IP addresses.
918
+ #
919
+ # Will raise an error if the resulting address is in a different subnet,
920
+ # except validating is set to false.
921
+ #
922
+ # Example:
923
+ #
924
+ # ip = IPAddress::IPv4.new("172.16.10.1/24")
925
+ # ip.add(5).to_string
926
+ # #=> "172.16.10.6/24"
927
+ def add(oth, validating=true)
928
+ oth = oth.to_i if oth.kind_of? IPAddress::IPv4 # oth shall be integer
929
+
930
+ new_obj = self.class.parse_u32(self.to_i + oth, prefix)
931
+
932
+ if validating and self.network_u32 != new_obj.network_u32
933
+ raise RuntimeError, "Subnet (/#{@prefix}) is not large enough."
934
+ end
935
+
936
+ new_obj
937
+ end
938
+
939
+ #
940
+ # Returns a new IPv4 object which is the result
941
+ # of decreasing this IP address by a given value.
942
+ # In other words, this arithmetically subtracts IP addresses.
943
+ #
944
+ # Will raise an error if the resulting address is in a different subnet,
945
+ # except validating is set to false.
946
+ #
947
+ # Example:
948
+ #
949
+ # ip = IPAddress::IPv4.new("172.16.10.10/24")
950
+ # ip.subtract(5).to_string
951
+ # #=> "172.16.10.5/24"
952
+ def subtract(oth, validating=true)
953
+ oth = oth.to_i if oth.kind_of? IPAddress::IPv4 # oth shall be integer
954
+ add(-oth, validating)
955
+ end
956
+
957
+ #
958
+ # Returns the network address of the n-th network succeeding this one.
959
+ #
960
+ # Example:
961
+ #
962
+ # ip = IPAddress::IPv4.new("172.16.10.0/24")
963
+ # ip.advance_network(24).to_string
964
+ # #=> "172.16.52.0/24"
965
+ def advance_network(amount)
966
+ IPAddress::IPv4.parse_u32(self.network.u32 + amount*self.size, @prefix)
967
+ end
968
+
969
+ #
970
+ # Returns the network address of the network succeeding this one.
971
+ #
972
+ # Example:
973
+ #
974
+ # ip = IPAddress::IPv4.new("172.16.10.0/24")
975
+ # ip.next_network.to_string
976
+ # #=> "172.16.11.0/24"
977
+ def next_network
978
+ advance_network 1
979
+ end
980
+
981
+ #
982
+ # Returns the network address of the n-th network preceeding this one.
983
+ #
984
+ # Example:
985
+ #
986
+ # ip = IPAddress::IPv4.new("172.16.10.0/24")
987
+ # ip.regress_network(5).to_string
988
+ # #=> "172.16.5.0/24"
989
+ def regress_network(amount)
990
+ advance_network(-amount)
991
+ end
992
+
993
+ #
994
+ # Returns the network address of the network preceeding this one.
995
+ #
996
+ # Example:
997
+ #
998
+ # ip = IPAddress::IPv4.new("172.16.10.0/24")
999
+ # ip.previous_network.to_string
1000
+ # #=> "172.16.9.0/24"
1001
+ def previous_network
1002
+ regress_network 1
1003
+ end
889
1004
 
890
1005
  #
891
1006
  # Checks whether the ip address belongs to a
@@ -394,8 +394,110 @@ module IPAddress;
394
394
  to_hex.reverse.gsub(/./){|c| c+"."} + "ip6.arpa"
395
395
  end
396
396
  alias_method :arpa, :reverse
397
+
398
+ #
399
+ # Returns a new IPv6 object which is the result
400
+ # of advancing this IP address by a given value.
401
+ # In other words, this arithmetically adds IP addresses.
402
+ #
403
+ # Will raise an error if the resulting address is in a different subnet,
404
+ # except validating is set to false.
405
+ #
406
+ # Example:
407
+ #
408
+ # ip = IPAddress::IPv6.new("fc42:1337::/64")
409
+ # ip.add(5).to_string
410
+ # #=> "fc42:1337::5/64"
411
+ def add(oth, validating=true)
412
+ oth = oth.to_i if oth.kind_of? IPAddress::IPv6 # oth shall be integer
413
+
414
+ new_obj = self.class.parse_u128(self.to_i + oth, prefix)
415
+
416
+ if validating and self.network_u128 != new_obj.network_u128
417
+ raise RuntimeError, "Subnet (/#{@prefix}) is not large enough."
418
+ end
419
+
420
+ new_obj
421
+ end
422
+
423
+ #
424
+ # Returns a new IPv6 object which is the result
425
+ # of decreasing this IP address by a given value.
426
+ # In other words, this arithmetically subtracts IP addresses.
427
+ #
428
+ # Will raise an error if the resulting address is in a different subnet,
429
+ # except validating is set to false.
430
+ #
431
+ # Example:
432
+ #
433
+ # ip = IPAddress::IPv6.new("fc42:1337::a/64")
434
+ # ip.subtract(5).to_string
435
+ # #=> "fc42:1337::5/64"
436
+ def subtract(oth, validating=true)
437
+ oth = oth.to_i if oth.kind_of? IPAddress::IPv6 # oth shall be integer
438
+ add(-oth, validating)
439
+ end
397
440
 
398
441
  #
442
+ # Returns the network address of the n-th network succeeding this one.
443
+ #
444
+ # Example:
445
+ #
446
+ # ip = IPAddress::IPv6.new("fc42:1337:0:0::/64")
447
+ # ip.advance_network(5).to_string
448
+ # #=> "fc42:1337:0:5::/64"
449
+ def advance_network(amount)
450
+ IPAddress::IPv6.parse_u128(self.network.to_i + amount*self.size, @prefix)
451
+ end
452
+
453
+ #
454
+ # Returns the network address of the network succeeding this one.
455
+ #
456
+ # Example:
457
+ #
458
+ # ip = IPAddress::IPv6.new("fc42:1337:0:0::/64")
459
+ # ip.next_network.to_string
460
+ # #=> "fc42:1337:0:1::/64"
461
+ def next_network
462
+ advance_network 1
463
+ end
464
+
465
+ #
466
+ # Returns the network address of the n-th network preceeding this one.
467
+ #
468
+ # Example:
469
+ #
470
+ # ip = IPAddress::IPv6.new("fc42:1337:0:5::/64")
471
+ # ip.regress_network(4).to_string
472
+ # #=> "fc42:1337:0:1::/64"
473
+ def regress_network(amount)
474
+ advance_network(-amount)
475
+ end
476
+
477
+ #
478
+ # Returns the network address of the network preceeding this one.
479
+ #
480
+ # Example:
481
+ #
482
+ # ip = IPAddress::IPv6.new("fc42:1337:0:5::/64")
483
+ # ip.previous_network.to_string
484
+ # #=> "fc42:1337:0:4::/64"
485
+ def previous_network
486
+ regress_network 1
487
+ end
488
+
489
+ #
490
+ # Returns a new IPv6 object containing only the host part of this IP.
491
+ #
492
+ # ip = IPAddress::IPv6.new("fc42:1337:0:5::7/64")
493
+ #
494
+ # ip.hostpart.to_s
495
+ # #=> "::7"
496
+ #
497
+ def hostpart
498
+ self.class.parse_u128(hostpart_u128, 128)
499
+ end
500
+
399
501
  # Splits a network into different subnets
400
502
  #
401
503
  # NOTE: Will allow you to split past /64 against RFC 5375
@@ -453,6 +555,18 @@ module IPAddress;
453
555
  def network_u128
454
556
  to_u128 & @prefix.to_u128
455
557
  end
558
+
559
+ #
560
+ # Returns this address' host part in unsigned 128bits format
561
+ #
562
+ # ip = IPAddress::IPv6.new("fc42:1337:0:5::7/64")
563
+ #
564
+ # ip.host_u128
565
+ # #=> 7
566
+ #
567
+ def hostpart_u128
568
+ to_u128 & ~@prefix.to_u128
569
+ end
456
570
 
457
571
  #
458
572
  # Returns the broadcast address in Unsigned 128bits format
@@ -1,3 +1,3 @@
1
1
  module IPAddress
2
- VERSION = "0.12.1"
2
+ VERSION = "0.13.0"
3
3
  end
@@ -455,7 +455,7 @@ class IPv4Test < Minitest::Test
455
455
 
456
456
  ip2 = @klass.new("172.16.12.2/24")
457
457
  assert_equal [ip1.network.to_string, ip2.network.to_string],
458
- (ip1 + ip2).map{|i| i.to_string}
458
+ (ip1 + ip2).map{|i| i.to_string}
459
459
 
460
460
  ip1 = @klass.new("10.0.0.0/23")
461
461
  ip2 = @klass.new("10.0.2.0/24")
@@ -533,6 +533,57 @@ class IPv4Test < Minitest::Test
533
533
  assert_equal "172.16.8.0/22", @ip.supernet(22).to_string
534
534
  end
535
535
 
536
+ def test_method_add
537
+ ip = IPAddress::IPv4.new("172.16.10.1/24")
538
+ assert_equal ip.add(5), IPAddress::IPv4.new("172.16.10.6/24")
539
+ assert_equal ip.add(IPAddress::IPv4.new("0.0.0.5/6")), IPAddress::IPv4.new("172.16.10.6/24")
540
+ assert_equal ip.add(50), IPAddress::IPv4.new("172.16.10.51/24")
541
+ assert_equal ip.add(254), IPAddress::IPv4.new("172.16.10.255/24")
542
+ assert_raises(RuntimeError) {ip.add(255)}
543
+ assert_equal ip.add(255, false), IPAddress::IPv4.new("172.16.11.0/24")
544
+ assert_raises(RuntimeError) {ip.add(1000)}
545
+ ip = IPAddress::IPv4.new("172.16.10.1/30")
546
+ assert_equal ip.add(2), IPAddress::IPv4.new("172.16.10.3/30")
547
+ assert_raises(RuntimeError) {ip.add(3)}
548
+ end
549
+
550
+ def test_method_subtract
551
+ ip = IPAddress::IPv4.new("172.16.10.10/24")
552
+ assert_equal ip.subtract(5), IPAddress::IPv4.new("172.16.10.5/24")
553
+ assert_equal ip.subtract(IPAddress::IPv4.new("0.0.0.5/32")), IPAddress::IPv4.new("172.16.10.5/24")
554
+ assert_equal ip.subtract(10), IPAddress::IPv4.new("172.16.10.0/24")
555
+ assert_raises(RuntimeError) {ip.subtract(11)}
556
+ assert_equal ip.subtract(11, false), IPAddress::IPv4.new("172.16.9.255/24")
557
+ assert_raises(RuntimeError) {ip.subtract(IPAddress::IPv4.new("0.0.0.11/16"))}
558
+ end
559
+
560
+ def test_method_hostpart
561
+ ip = IPAddress::IPv4.new("172.16.10.64/24")
562
+ assert_equal ip.hostpart.to_s, "0.0.0.64"
563
+ ip = IPAddress::IPv4.new("172.16.10.130/25")
564
+ assert_equal ip.hostpart.to_s, "0.0.0.2"
565
+ end
566
+
567
+ def test_method_advance_network
568
+ ip = IPAddress::IPv4.new("172.16.10.64/24")
569
+ assert_equal ip.advance_network(42), IPAddress::IPv4.new("172.16.52.0/24")
570
+ end
571
+
572
+ def test_method_next_network
573
+ ip = IPAddress::IPv4.new("172.16.10.64/24")
574
+ assert_equal ip.next_network, IPAddress::IPv4.new("172.16.11.0/24")
575
+ end
576
+
577
+ def test_method_regress_network
578
+ ip = IPAddress::IPv4.new("172.16.10.64/24")
579
+ assert_equal ip.regress_network(5), IPAddress::IPv4.new("172.16.5.0/24")
580
+ end
581
+
582
+ def test_method_previous_network
583
+ ip = IPAddress::IPv4.new("172.16.10.64/24")
584
+ assert_equal ip.previous_network, IPAddress::IPv4.new("172.16.9.0/24")
585
+ end
586
+
536
587
  def test_classmethod_parse_u32
537
588
  @decimal_values.each do |addr,int|
538
589
  ip = @klass.parse_u32(int)
@@ -627,6 +627,51 @@ class IPv6Test < Minitest::Test
627
627
  assert_equal "2001:db8:8:2000::/51", @klass.new("2001:db8:8::/51").find_adjacent_subnet
628
628
  end
629
629
 
630
+ def test_method_add
631
+ ip = IPAddress::IPv6.new("fc42:1337::/64")
632
+ assert_equal ip.add(5), IPAddress::IPv6.new("fc42:1337::5/64")
633
+ assert_equal ip.add(IPAddress::IPv6.new("::5/42")), IPAddress::IPv6.new("fc42:1337::5/64")
634
+ assert_equal ip.add(50), IPAddress::IPv6.new("fc42:1337::32/64")
635
+ ip = IPAddress::IPv6.new("fc42:1337::/120")
636
+ assert_equal ip.add(2), IPAddress::IPv6.new("fc42:1337::2/120")
637
+ assert_raises(RuntimeError) {ip.add(256)}
638
+ assert_equal ip.add(256, false), IPAddress::IPv6.new("fc42:1337::100/120")
639
+ end
640
+
641
+ def test_method_subtract
642
+ ip = IPAddress::IPv6.new("fc42:1337::5/64")
643
+ assert_equal ip.subtract(5), IPAddress::IPv6.new("fc42:1337::/64")
644
+ assert_equal ip.subtract(IPAddress::IPv6.new("::5/12")), IPAddress::IPv6.new("fc42:1337::0/64")
645
+ assert_raises(RuntimeError) {ip.subtract(11)}
646
+ assert_raises(RuntimeError) {ip.subtract(IPAddress::IPv6.new("::11/66"))}
647
+ end
648
+
649
+ def test_method_hostpart
650
+ ip = IPAddress::IPv6.new("fc42:1337:0:5::7/64")
651
+ assert_equal ip.hostpart.to_s, "::7"
652
+ end
653
+
654
+ def test_method_advance_network
655
+ ip = IPAddress::IPv6.new("fc42:1337:0:0::/64")
656
+ assert_equal ip.advance_network(5), IPAddress::IPv6.new("fc42:1337:0:5::/64")
657
+ end
658
+
659
+ def test_method_next_network
660
+ ip = IPAddress::IPv6.new("fc42:1337:0:0::/64")
661
+ assert_equal ip.next_network, IPAddress::IPv6.new("fc42:1337:0:1::/64")
662
+ end
663
+
664
+ def test_method_regress_network
665
+ ip = IPAddress::IPv6.new("fc42:1337:0:5::/64")
666
+ assert_equal ip.regress_network(4), IPAddress::IPv6.new("fc42:1337:0:1::/64")
667
+ end
668
+
669
+ def test_method_previous_network
670
+ ip = IPAddress::IPv6.new("fc42:1337:0:5::/64")
671
+ assert_equal ip.previous_network, IPAddress::IPv6.new("fc42:1337:0:4::/64")
672
+ end
673
+
674
+
630
675
  end # class IPv6Test
631
676
 
632
677
  class IPv6UnspecifiedTest < Minitest::Test
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ipaddress_2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.1
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - bluemonk
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-02-19 00:00:00.000000000 Z
12
+ date: 2019-05-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler