ipaddress_2 0.12.1 → 0.13.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: 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