rrs 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c0d9733af6339a12ce11ff22d41f27142c86f16b46755c9b12c671f9a851fa6e
4
+ data.tar.gz: a3df3377fa1a8f10e93281536fb4ccdcfc1cdd2bf19ab3bf5ce8e2840f575a60
5
+ SHA512:
6
+ metadata.gz: f8ab7a7e7b4d8046101570b92a1ac8e7e07fd55100a3d43f4287b6c48ad317e5f13c07ccd80c743a6cd46a624d21dd82f5f27c993ea90430f79ace1e0b790f21
7
+ data.tar.gz: 6e2479f8d855d39afb625f61699501ec4d2d00c7d177d2f950d63dc845c260e0a6a02b6daf37e8f1e5fdb9b73b51357d9e58f735ddc3b35599025674b4688317
data/.standard.yml ADDED
@@ -0,0 +1,3 @@
1
+ # For available configuration options, see:
2
+ # https://github.com/standardrb/standard
3
+ ruby_version: 3.0
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # RRs
2
+
3
+ TODO: Delete this and the text below, and describe your gem
4
+
5
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/rrs`. To experiment with that code, run `bin/console` for an interactive prompt.
6
+
7
+ ## Installation
8
+
9
+ TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
10
+
11
+ Install the gem and add to the application's Gemfile by executing:
12
+
13
+ $ bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
14
+
15
+ If bundler is not being used to manage dependencies, install the gem by executing:
16
+
17
+ $ gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Development
24
+
25
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
26
+
27
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
28
+
29
+ ## Contributing
30
+
31
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/rrs.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "standard/rake"
5
+
6
+ task default: :standard
data/lib/rrs/a.rb ADDED
@@ -0,0 +1,26 @@
1
+ module RRs
2
+ class A
3
+ TypeValue = 1
4
+ ClassValue = 1
5
+
6
+ ##
7
+ # Creates a new A for +address+.
8
+
9
+ def initialize(address)
10
+ @address = IPv4.create(address)
11
+ end
12
+
13
+ ##
14
+ # The IPv4 address for this A.
15
+
16
+ attr_reader :address
17
+
18
+ def encode_rdata(msg) # :nodoc:
19
+ msg.put_bytes(@address.address)
20
+ end
21
+
22
+ def self.decode_rdata(msg) # :nodoc:
23
+ return self.new(IPv4.new(msg.get_bytes(4)))
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,13 @@
1
+ module RRs
2
+ class Inflector < Zeitwerk::Inflector
3
+ def camelize(basename, abspath)
4
+ if basename =~ /\Arrs(.*)/
5
+ "RRs" + super($1, abspath)
6
+ elsif basename =~ /\Aipv(.*)/
7
+ "IPv" + super($1, abspath)
8
+ else
9
+ super
10
+ end
11
+ end
12
+ end
13
+ end
data/lib/rrs/ipv4.rb ADDED
@@ -0,0 +1,69 @@
1
+ module RRs
2
+ class IPv4
3
+
4
+ ##
5
+ # Regular expression IPv4 addresses must match.
6
+
7
+ Regex256 = /0
8
+ |1(?:[0-9][0-9]?)?
9
+ |2(?:[0-4][0-9]?|5[0-5]?|[6-9])?
10
+ |[3-9][0-9]?/x
11
+ Regex = /\A(#{Regex256})\.(#{Regex256})\.(#{Regex256})\.(#{Regex256})\z/
12
+
13
+ def self.create(arg)
14
+ case arg
15
+ when IPv4
16
+ return arg
17
+ when Regex
18
+ if (0..255) === (a = $1.to_i) &&
19
+ (0..255) === (b = $2.to_i) &&
20
+ (0..255) === (c = $3.to_i) &&
21
+ (0..255) === (d = $4.to_i)
22
+ return self.new([a, b, c, d].pack("CCCC"))
23
+ else
24
+ raise ArgumentError.new("IPv4 address with invalid value: " + arg)
25
+ end
26
+ else
27
+ raise ArgumentError.new("cannot interpret as IPv4 address: #{arg.inspect}")
28
+ end
29
+ end
30
+
31
+ def initialize(address) # :nodoc:
32
+ unless address.kind_of?(String)
33
+ raise ArgumentError, 'IPv4 address must be a string'
34
+ end
35
+ unless address.length == 4
36
+ raise ArgumentError, "IPv4 address expects 4 bytes but #{address.length} bytes"
37
+ end
38
+ @address = address
39
+ end
40
+
41
+ ##
42
+ # A String representation of this IPv4 address.
43
+
44
+ ##
45
+ # The raw IPv4 address as a String.
46
+
47
+ attr_reader :address
48
+
49
+ def to_s # :nodoc:
50
+ return sprintf("%d.%d.%d.%d", *@address.unpack("CCCC"))
51
+ end
52
+
53
+ def inspect # :nodoc:
54
+ return "#<#{self.class} #{self}>"
55
+ end
56
+
57
+ def ==(other) # :nodoc:
58
+ return @address == other.address
59
+ end
60
+
61
+ def eql?(other) # :nodoc:
62
+ return self == other
63
+ end
64
+
65
+ def hash # :nodoc:
66
+ return @address.hash
67
+ end
68
+ end
69
+ end
data/lib/rrs/ipv6.rb ADDED
@@ -0,0 +1,154 @@
1
+ module RRs
2
+ class IPv6
3
+
4
+ ##
5
+ # IPv6 address format a:b:c:d:e:f:g:h
6
+ Regex_8Hex = /\A
7
+ (?:[0-9A-Fa-f]{1,4}:){7}
8
+ [0-9A-Fa-f]{1,4}
9
+ \z/x
10
+
11
+ ##
12
+ # Compressed IPv6 address format a::b
13
+
14
+ Regex_CompressedHex = /\A
15
+ ((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?) ::
16
+ ((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)
17
+ \z/x
18
+
19
+ ##
20
+ # IPv4 mapped IPv6 address format a:b:c:d:e:f:w.x.y.z
21
+
22
+ Regex_6Hex4Dec = /\A
23
+ ((?:[0-9A-Fa-f]{1,4}:){6,6})
24
+ (\d+)\.(\d+)\.(\d+)\.(\d+)
25
+ \z/x
26
+
27
+ ##
28
+ # Compressed IPv4 mapped IPv6 address format a::b:w.x.y.z
29
+
30
+ Regex_CompressedHex4Dec = /\A
31
+ ((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?) ::
32
+ ((?:[0-9A-Fa-f]{1,4}:)*)
33
+ (\d+)\.(\d+)\.(\d+)\.(\d+)
34
+ \z/x
35
+
36
+ ##
37
+ # IPv6 link local address format fe80:b:c:d:e:f:g:h%em1
38
+ Regex_8HexLinkLocal = /\A
39
+ [Ff][Ee]80
40
+ (?::[0-9A-Fa-f]{1,4}){7}
41
+ %[-0-9A-Za-z._~]+
42
+ \z/x
43
+
44
+ ##
45
+ # Compressed IPv6 link local address format fe80::b%em1
46
+
47
+ Regex_CompressedHexLinkLocal = /\A
48
+ [Ff][Ee]80:
49
+ (?:
50
+ ((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?) ::
51
+ ((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)
52
+ |
53
+ :((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)
54
+ )?
55
+ :[0-9A-Fa-f]{1,4}%[-0-9A-Za-z._~]+
56
+ \z/x
57
+
58
+ ##
59
+ # A composite IPv6 address Regexp.
60
+
61
+ Regex = /
62
+ (?:#{Regex_8Hex}) |
63
+ (?:#{Regex_CompressedHex}) |
64
+ (?:#{Regex_6Hex4Dec}) |
65
+ (?:#{Regex_CompressedHex4Dec}) |
66
+ (?:#{Regex_8HexLinkLocal}) |
67
+ (?:#{Regex_CompressedHexLinkLocal})
68
+ /x
69
+
70
+ ##
71
+ # Creates a new IPv6 address from +arg+ which may be:
72
+ #
73
+ # IPv6:: returns +arg+.
74
+ # String:: +arg+ must match one of the IPv6::Regex* constants
75
+
76
+ def self.create(arg)
77
+ case arg
78
+ when IPv6
79
+ return arg
80
+ when String
81
+ address = ''.b
82
+ if Regex_8Hex =~ arg
83
+ arg.scan(/[0-9A-Fa-f]+/) {|hex| address << [hex.hex].pack('n')}
84
+ elsif Regex_CompressedHex =~ arg
85
+ prefix = $1
86
+ suffix = $2
87
+ a1 = ''.b
88
+ a2 = ''.b
89
+ prefix.scan(/[0-9A-Fa-f]+/) {|hex| a1 << [hex.hex].pack('n')}
90
+ suffix.scan(/[0-9A-Fa-f]+/) {|hex| a2 << [hex.hex].pack('n')}
91
+ omitlen = 16 - a1.length - a2.length
92
+ address << a1 << "\0" * omitlen << a2
93
+ elsif Regex_6Hex4Dec =~ arg
94
+ prefix, a, b, c, d = $1, $2.to_i, $3.to_i, $4.to_i, $5.to_i
95
+ if (0..255) === a && (0..255) === b && (0..255) === c && (0..255) === d
96
+ prefix.scan(/[0-9A-Fa-f]+/) {|hex| address << [hex.hex].pack('n')}
97
+ address << [a, b, c, d].pack('CCCC')
98
+ else
99
+ raise ArgumentError.new("not numeric IPv6 address: " + arg)
100
+ end
101
+ elsif Regex_CompressedHex4Dec =~ arg
102
+ prefix, suffix, a, b, c, d = $1, $2, $3.to_i, $4.to_i, $5.to_i, $6.to_i
103
+ if (0..255) === a && (0..255) === b && (0..255) === c && (0..255) === d
104
+ a1 = ''.b
105
+ a2 = ''.b
106
+ prefix.scan(/[0-9A-Fa-f]+/) {|hex| a1 << [hex.hex].pack('n')}
107
+ suffix.scan(/[0-9A-Fa-f]+/) {|hex| a2 << [hex.hex].pack('n')}
108
+ omitlen = 12 - a1.length - a2.length
109
+ address << a1 << "\0" * omitlen << a2 << [a, b, c, d].pack('CCCC')
110
+ else
111
+ raise ArgumentError.new("not numeric IPv6 address: " + arg)
112
+ end
113
+ else
114
+ raise ArgumentError.new("not numeric IPv6 address: " + arg)
115
+ end
116
+ return IPv6.new(address)
117
+ else
118
+ raise ArgumentError.new("cannot interpret as IPv6 address: #{arg.inspect}")
119
+ end
120
+ end
121
+
122
+ def initialize(address) # :nodoc:
123
+ unless address.kind_of?(String) && address.length == 16
124
+ raise ArgumentError.new('IPv6 address must be 16 bytes')
125
+ end
126
+ @address = address
127
+ end
128
+
129
+ ##
130
+ # The raw IPv6 address as a String.
131
+
132
+ attr_reader :address
133
+
134
+ def to_s # :nodoc:
135
+ sprintf("%x:%x:%x:%x:%x:%x:%x:%x", *@address.unpack("nnnnnnnn")).sub(/(^|:)0(:0)+(:|$)/, '::')
136
+ end
137
+
138
+ def inspect # :nodoc:
139
+ return "#<#{self.class} #{self}>"
140
+ end
141
+
142
+ def ==(other) # :nodoc:
143
+ return @address == other.address
144
+ end
145
+
146
+ def eql?(other) # :nodoc:
147
+ return self == other
148
+ end
149
+
150
+ def hash # :nodoc:
151
+ return @address.hash
152
+ end
153
+ end
154
+ end
data/lib/rrs.rb ADDED
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ require "zeitwerk"
3
+ require_relative "rrs/inflector"
4
+
5
+ loader = Zeitwerk::Loader.for_gem
6
+ loader.inflector = RRs::Inflector.new
7
+ loader.setup
8
+
9
+ module RRs
10
+ VERSION = "0.1.0"
11
+
12
+ class Error < StandardError; end
13
+ end
14
+
15
+ loader.eager_load
data/sig/rrs.rbs ADDED
@@ -0,0 +1,4 @@
1
+ module RRs
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rrs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - reesericci
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-08-17 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: "RRs is a set of self-contained DNS primitives that do not share state,
14
+ which makes them suitable for use in Ractors. \n\nThis is a contrast to the Resolv::DNS
15
+ and Dnsruby primitives which use a ClassHash."
16
+ email:
17
+ - me@reeseric.ci
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - ".standard.yml"
23
+ - README.md
24
+ - Rakefile
25
+ - lib/rrs.rb
26
+ - lib/rrs/a.rb
27
+ - lib/rrs/inflector.rb
28
+ - lib/rrs/ipv4.rb
29
+ - lib/rrs/ipv6.rb
30
+ - sig/rrs.rbs
31
+ homepage: https://codeberg.org/reesericci/rrs
32
+ licenses: []
33
+ metadata:
34
+ homepage_uri: https://codeberg.org/reesericci/rrs
35
+ source_code_uri: https://codeberg.org/reesericci/rrs
36
+ post_install_message:
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: 3.0.0
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ requirements: []
51
+ rubygems_version: 3.5.17
52
+ signing_key:
53
+ specification_version: 4
54
+ summary: RRs is a set of self-contained DNS primitives
55
+ test_files: []