maxmind-db 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +13 -2
  3. data/Gemfile +8 -0
  4. data/Gemfile.lock +34 -0
  5. data/README.md +2 -2
  6. data/Rakefile +2 -0
  7. data/bin/mmdb-benchmark.rb +4 -1
  8. data/lib/maxmind/db.rb +49 -27
  9. data/lib/maxmind/db/decoder.rb +26 -26
  10. data/lib/maxmind/db/errors.rb +3 -1
  11. data/lib/maxmind/db/file_reader.rb +5 -3
  12. data/lib/maxmind/db/memory_reader.rb +3 -1
  13. data/lib/maxmind/db/metadata.rb +3 -1
  14. data/maxmind-db.gemspec +5 -2
  15. data/test/mmdb_util.rb +2 -0
  16. data/test/test_decoder.rb +2 -0
  17. data/test/test_reader.rb +117 -6
  18. metadata +7 -64
  19. data/test/data/LICENSE +0 -4
  20. data/test/data/MaxMind-DB-spec.md +0 -558
  21. data/test/data/MaxMind-DB-test-metadata-pointers.mmdb +0 -0
  22. data/test/data/README.md +0 -4
  23. data/test/data/bad-data/README.md +0 -7
  24. data/test/data/bad-data/libmaxminddb/libmaxminddb-offset-integer-overflow.mmdb +0 -0
  25. data/test/data/bad-data/maxminddb-golang/cyclic-data-structure.mmdb +0 -0
  26. data/test/data/bad-data/maxminddb-golang/invalid-bytes-length.mmdb +0 -1
  27. data/test/data/bad-data/maxminddb-golang/invalid-data-record-offset.mmdb +0 -0
  28. data/test/data/bad-data/maxminddb-golang/invalid-map-key-length.mmdb +0 -0
  29. data/test/data/bad-data/maxminddb-golang/invalid-string-length.mmdb +0 -1
  30. data/test/data/bad-data/maxminddb-golang/metadata-is-an-uint128.mmdb +0 -1
  31. data/test/data/bad-data/maxminddb-golang/unexpected-bytes.mmdb +0 -0
  32. data/test/data/perltidyrc +0 -12
  33. data/test/data/source-data/GeoIP2-Anonymous-IP-Test.json +0 -41
  34. data/test/data/source-data/GeoIP2-City-Test.json +0 -12852
  35. data/test/data/source-data/GeoIP2-Connection-Type-Test.json +0 -102
  36. data/test/data/source-data/GeoIP2-Country-Test.json +0 -11347
  37. data/test/data/source-data/GeoIP2-DensityIncome-Test.json +0 -14
  38. data/test/data/source-data/GeoIP2-Domain-Test.json +0 -452
  39. data/test/data/source-data/GeoIP2-Enterprise-Test.json +0 -673
  40. data/test/data/source-data/GeoIP2-ISP-Test.json +0 -12585
  41. data/test/data/source-data/GeoIP2-Precision-Enterprise-Test.json +0 -1598
  42. data/test/data/source-data/GeoIP2-User-Count-Test.json +0 -2824
  43. data/test/data/source-data/GeoLite2-ASN-Test.json +0 -37
  44. data/test/data/source-data/README +0 -15
  45. data/test/data/test-data/GeoIP2-Anonymous-IP-Test.mmdb +0 -0
  46. data/test/data/test-data/GeoIP2-City-Test-Broken-Double-Format.mmdb +0 -0
  47. data/test/data/test-data/GeoIP2-City-Test-Invalid-Node-Count.mmdb +0 -0
  48. data/test/data/test-data/GeoIP2-City-Test.mmdb +0 -0
  49. data/test/data/test-data/GeoIP2-Connection-Type-Test.mmdb +0 -0
  50. data/test/data/test-data/GeoIP2-Country-Test.mmdb +0 -0
  51. data/test/data/test-data/GeoIP2-DensityIncome-Test.mmdb +0 -0
  52. data/test/data/test-data/GeoIP2-Domain-Test.mmdb +0 -0
  53. data/test/data/test-data/GeoIP2-Enterprise-Test.mmdb +0 -0
  54. data/test/data/test-data/GeoIP2-ISP-Test.mmdb +0 -0
  55. data/test/data/test-data/GeoIP2-Precision-Enterprise-Test.mmdb +0 -0
  56. data/test/data/test-data/GeoIP2-User-Count-Test.mmdb +0 -0
  57. data/test/data/test-data/GeoLite2-ASN-Test.mmdb +0 -0
  58. data/test/data/test-data/MaxMind-DB-no-ipv4-search-tree.mmdb +0 -0
  59. data/test/data/test-data/MaxMind-DB-string-value-entries.mmdb +0 -0
  60. data/test/data/test-data/MaxMind-DB-test-broken-pointers-24.mmdb +0 -0
  61. data/test/data/test-data/MaxMind-DB-test-broken-search-tree-24.mmdb +0 -0
  62. data/test/data/test-data/MaxMind-DB-test-decoder.mmdb +0 -0
  63. data/test/data/test-data/MaxMind-DB-test-ipv4-24.mmdb +0 -0
  64. data/test/data/test-data/MaxMind-DB-test-ipv4-28.mmdb +0 -0
  65. data/test/data/test-data/MaxMind-DB-test-ipv4-32.mmdb +0 -0
  66. data/test/data/test-data/MaxMind-DB-test-ipv6-24.mmdb +0 -0
  67. data/test/data/test-data/MaxMind-DB-test-ipv6-28.mmdb +0 -0
  68. data/test/data/test-data/MaxMind-DB-test-ipv6-32.mmdb +0 -0
  69. data/test/data/test-data/MaxMind-DB-test-metadata-pointers.mmdb +0 -0
  70. data/test/data/test-data/MaxMind-DB-test-mixed-24.mmdb +0 -0
  71. data/test/data/test-data/MaxMind-DB-test-mixed-28.mmdb +0 -0
  72. data/test/data/test-data/MaxMind-DB-test-mixed-32.mmdb +0 -0
  73. data/test/data/test-data/MaxMind-DB-test-nested.mmdb +0 -0
  74. data/test/data/test-data/README.md +0 -26
  75. data/test/data/test-data/maps-with-pointers.raw +0 -0
  76. data/test/data/test-data/write-test-data.pl +0 -620
  77. data/test/data/tidyall.ini +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 604697b9d2de00a32fec3ee2b84c53703f532ecf708ca6cfcd4898fa934d830e
4
- data.tar.gz: cdaeb5d99ca07f8c9f6af0354dc23fb3f8678a40e0ea67fe74b7b7dcaabc7ec5
2
+ SHA1:
3
+ metadata.gz: e8404a64573590d7a01fd9199ae1be5bb1892407
4
+ data.tar.gz: cfdec2ef12cae84fa914784b90c386d1006fdf47
5
5
  SHA512:
6
- metadata.gz: 3939f3025d4a715537d6284ac49cfa691bf733711afd6143ec73e586aec96cbcf717115c340214903fd4a8bcc1c4b8c4973d0fa9517491b2c48c5d710cdc9e87
7
- data.tar.gz: 54dbe0bebe152e151234b0b0026492d38a80858174c3342d12ff665026d858295b29434d3ea7c8ea56b3b7c669b0d2f921c018b7dba9c16aad996143f9c66ede
6
+ metadata.gz: 263eff4235eadc529e14266772c3db95bc17950ebc7d73fbb3f5d20ee76f3b2f50035c97ad2e39454e5dbd65dd6093fc56f3a6dd3b8d91a69037b8e396986366
7
+ data.tar.gz: 8fe05ac4631539293ee2d1485fe7c1908858ef952d76e60e75d9f601f356263bb47928bc8dd670c2989df4437cb0d2a876869c662b1f4aab36d0e8a81ce19552
@@ -1,9 +1,20 @@
1
1
  # Changelog
2
2
 
3
- ## 1.0.0 - 2019-01-04
3
+ ## 1.1.0 (2020-01-08)
4
+
5
+ * The method `get_with_prefix_length` was added. This method returns both
6
+ the record and the network prefix length associated with the record in
7
+ the database.
8
+ * Simplified a check for whether to return early in the decoder. Pull
9
+ request by Ivan Palamarchuk. GitHub #12.
10
+ * Support for Ruby 2.3 was dropped since it is now end of life.
11
+
12
+ ## 1.0.0 (2019-01-04)
13
+
4
14
  * We no longer include the database's buffer in inspect output. This avoids
5
15
  showing excessive output when creating a memory reader in irb. Reported
6
16
  by Wojciech Wnętrzak. GitHub #6.
7
17
 
8
- ## 1.0.0.beta - 2018-12-24
18
+ ## 1.0.0.beta (2018-12-24)
19
+
9
20
  * Initial implementation.
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gem 'minitest', group: :development
6
+ gem 'rake', group: :development
7
+ gem 'rubocop', group: :development
8
+ gem 'rubocop-performance', group: :development
@@ -0,0 +1,34 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ ast (2.4.0)
5
+ jaro_winkler (1.5.4)
6
+ minitest (5.13.0)
7
+ parallel (1.19.1)
8
+ parser (2.7.0.1)
9
+ ast (~> 2.4.0)
10
+ rainbow (3.0.0)
11
+ rake (13.0.1)
12
+ rubocop (0.79.0)
13
+ jaro_winkler (~> 1.5.1)
14
+ parallel (~> 1.10)
15
+ parser (>= 2.7.0.1)
16
+ rainbow (>= 2.2.2, < 4.0)
17
+ ruby-progressbar (~> 1.7)
18
+ unicode-display_width (>= 1.4.0, < 1.7)
19
+ rubocop-performance (1.5.2)
20
+ rubocop (>= 0.71.0)
21
+ ruby-progressbar (1.10.1)
22
+ unicode-display_width (1.6.0)
23
+
24
+ PLATFORMS
25
+ ruby
26
+
27
+ DEPENDENCIES
28
+ minitest
29
+ rake
30
+ rubocop
31
+ rubocop-performance
32
+
33
+ BUNDLED WITH
34
+ 2.0.1
data/README.md CHANGED
@@ -43,7 +43,7 @@ For more information see the
43
43
 
44
44
  ## Requirements
45
45
 
46
- This code requires Ruby version 2.3 or higher. Older versions may work, but
46
+ This code requires Ruby version 2.4 or higher. Older versions may work, but
47
47
  are not supported.
48
48
 
49
49
  ## Contributing
@@ -65,7 +65,7 @@ This library uses [Semantic Versioning](https://semver.org/).
65
65
 
66
66
  ## Copyright and License
67
67
 
68
- This software is Copyright (c) 2018 - 2019 by MaxMind, Inc.
68
+ This software is Copyright (c) 2018 - 2020 by MaxMind, Inc.
69
69
 
70
70
  This is free software, licensed under the [Apache License, Version
71
71
  2.0](LICENSE-APACHE) or the [MIT License](LICENSE-MIT), at your option.
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rake/testtask'
2
4
  require 'rubocop/rake_task'
3
5
 
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'maxmind/db'
4
5
 
@@ -27,9 +28,11 @@ def parse_args
27
28
  end
28
29
 
29
30
  def print_usage
30
- STDERR.puts "Usage: #{$PROGRAM_NAME} <MMDB file> [IP file]"
31
+ # rubocop:disable Style/StderrPuts
32
+ STDERR.puts "Usage: #{$PROGRAM_NAME} <MMDB file> <IP file>"
31
33
  STDERR.puts
32
34
  STDERR.puts 'Benchmark by reading IPs from the IP file and looking up each one in the MMDB file.'
35
+ # rubocop:enable Style/StderrPuts
33
36
  end
34
37
 
35
38
  def benchmark(reader, file)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'ipaddr'
2
4
  require 'maxmind/db/decoder'
3
5
  require 'maxmind/db/errors'
@@ -7,9 +9,9 @@ require 'maxmind/db/metadata.rb'
7
9
 
8
10
  module MaxMind # :nodoc:
9
11
  # DB provides a way to read {MaxMind DB
10
- # files}[http://maxmind.github.io/MaxMind-DB/].
12
+ # files}[https://maxmind.github.io/MaxMind-DB/].
11
13
  #
12
- # {MaxMind DB}[http://maxmind.github.io/MaxMind-DB/] is a binary file format
14
+ # {MaxMind DB}[https://maxmind.github.io/MaxMind-DB/] is a binary file format
13
15
  # that stores data indexed by IP address subnets (IPv4 or IPv6).
14
16
  #
15
17
  # This class is a pure Ruby implementation of a reader for the format.
@@ -49,7 +51,7 @@ module MaxMind # :nodoc:
49
51
 
50
52
  DATA_SECTION_SEPARATOR_SIZE = 16
51
53
  private_constant :DATA_SECTION_SEPARATOR_SIZE
52
- METADATA_START_MARKER = "\xAB\xCD\xEFMaxMind.com".freeze.b.freeze
54
+ METADATA_START_MARKER = "\xAB\xCD\xEFMaxMind.com".b.freeze
53
55
  private_constant :METADATA_START_MARKER
54
56
  METADATA_START_MARKER_LENGTH = 14
55
57
  private_constant :METADATA_START_MARKER_LENGTH
@@ -57,11 +59,11 @@ module MaxMind # :nodoc:
57
59
  private_constant :METADATA_MAX_SIZE
58
60
 
59
61
  # Return the metadata associated with the {MaxMind
60
- # DB}[http://maxmind.github.io/MaxMind-DB/] as a Metadata object.
62
+ # DB}[https://maxmind.github.io/MaxMind-DB/] as a Metadata object.
61
63
  attr_reader :metadata
62
64
 
63
65
  # Create a DB. A DB provides a way to read {MaxMind DB
64
- # files}[http://maxmind.github.io/MaxMind-DB/]. If you're performing
66
+ # files}[https://maxmind.github.io/MaxMind-DB/]. If you're performing
65
67
  # multiple lookups, it's most efficient to create one DB and reuse it.
66
68
  #
67
69
  # Once created, the DB is safe to use for lookups from multiple threads. It
@@ -71,7 +73,7 @@ module MaxMind # :nodoc:
71
73
  # Creating the DB may raise an exception if initialization fails.
72
74
  #
73
75
  # +database+ is a path to a {MaxMind
74
- # DB}[http://maxmind.github.io/MaxMind-DB/].
76
+ # DB}[https://maxmind.github.io/MaxMind-DB/].
75
77
  #
76
78
  # +options+ is an option hash where each key is a symbol. The options
77
79
  # control the behaviour of the DB.
@@ -93,7 +95,7 @@ module MaxMind # :nodoc:
93
95
  when MODE_PARAM_IS_BUFFER
94
96
  @io = MemoryReader.new(database, is_buffer: true)
95
97
  else
96
- raise ArgumentError, 'Invalid mode'.freeze
98
+ raise ArgumentError, 'Invalid mode'
97
99
  end
98
100
 
99
101
  begin
@@ -124,7 +126,7 @@ module MaxMind # :nodoc:
124
126
  end
125
127
 
126
128
  # Return the record for the +ip_address+ in the {MaxMind
127
- # DB}[http://maxmind.github.io/MaxMind-DB/]. The record can be one of
129
+ # DB}[https://maxmind.github.io/MaxMind-DB/]. The record can be one of
128
130
  # several types and depends on the contents of the database.
129
131
  #
130
132
  # If no record is found for +ip_address+, +get+ returns +nil+.
@@ -134,6 +136,25 @@ module MaxMind # :nodoc:
134
136
  # +ip_address+ is a string in the standard notation. It may be IPv4 or
135
137
  # IPv6.
136
138
  def get(ip_address)
139
+ record, = get_with_prefix_length(ip_address)
140
+
141
+ record
142
+ end
143
+
144
+ # Return an array containing the record for the +ip_address+ in the
145
+ # {MaxMind DB}[https://maxmind.github.io/MaxMind-DB/] and its associated
146
+ # network prefix length. The record can be one of several types and
147
+ # depends on the contents of the database.
148
+ #
149
+ # If no record is found for +ip_address+, the record will be +nil+ and
150
+ # the prefix length will be the value for the missing network.
151
+ #
152
+ # +get_with_prefix_length+ raises an exception if there is an error
153
+ # performing the lookup.
154
+ #
155
+ # +ip_address+ is a string in the standard notation. It may be IPv4 or
156
+ # IPv6.
157
+ def get_with_prefix_length(ip_address)
137
158
  ip = IPAddr.new(ip_address)
138
159
  # We could check the IP has the correct prefix (32 or 128) but I do not
139
160
  # for performance reasons.
@@ -144,10 +165,10 @@ module MaxMind # :nodoc:
144
165
  "Error looking up #{ip}. You attempted to look up an IPv6 address in an IPv4-only database."
145
166
  end
146
167
 
147
- pointer = find_address_in_tree(ip, ip_version)
148
- return nil if pointer == 0
168
+ pointer, depth = find_address_in_tree(ip, ip_version)
169
+ return nil, depth if pointer == 0
149
170
 
150
- resolve_data_pointer(pointer)
171
+ [resolve_data_pointer(pointer), depth]
151
172
  end
152
173
 
153
174
  private
@@ -165,19 +186,22 @@ module MaxMind # :nodoc:
165
186
  node = start_node(bit_count)
166
187
 
167
188
  node_count = @node_count
168
- bit_count.times do |i|
169
- break if node >= node_count
170
189
 
171
- c = packed[i >> 3].ord
172
- bit = 1 & (c >> 7 - (i % 8))
190
+ depth = 0
191
+ loop do
192
+ break if depth >= bit_count || node >= node_count
193
+
194
+ c = packed[depth >> 3].ord
195
+ bit = 1 & (c >> 7 - (depth % 8))
173
196
  node = read_node(node, bit)
197
+ depth += 1
174
198
  end
175
199
 
176
- return 0 if node == node_count
200
+ return 0, depth if node == node_count
177
201
 
178
- return node if node > node_count
202
+ return node, depth if node > node_count
179
203
 
180
- raise InvalidDatabaseError, 'Invalid node in search tree'.freeze
204
+ raise InvalidDatabaseError, 'Invalid node in search tree'
181
205
  end
182
206
 
183
207
  def start_node(length)
@@ -205,28 +229,26 @@ module MaxMind # :nodoc:
205
229
  if @record_size == 24
206
230
  offset = index == 0 ? base_offset : base_offset + 3
207
231
  buf = @io.read(offset, 3)
208
- node_bytes = "\x00".freeze.b << buf
209
- # When we support only Ruby 2.4+, we can change String#unpack calls
210
- # that take the first element to String#unpack1.
211
- return node_bytes.unpack('N'.freeze)[0]
232
+ node_bytes = "\x00".b << buf
233
+ return node_bytes.unpack1('N')
212
234
  end
213
235
 
214
236
  if @record_size == 28
215
237
  if index == 0
216
238
  buf = @io.read(base_offset, 4)
217
- n = buf.unpack('N'.freeze)[0]
239
+ n = buf.unpack1('N')
218
240
  last24 = n >> 8
219
241
  first4 = (n & 0xf0) << 20
220
242
  return first4 | last24
221
243
  end
222
244
  buf = @io.read(base_offset + 3, 4)
223
- return buf.unpack('N'.freeze)[0] & 0x0fffffff
245
+ return buf.unpack1('N') & 0x0fffffff
224
246
  end
225
247
 
226
248
  if @record_size == 32
227
249
  offset = index == 0 ? base_offset : base_offset + 4
228
250
  node_bytes = @io.read(offset, 4)
229
- return node_bytes.unpack('N'.freeze)[0]
251
+ return node_bytes.unpack1('N')
230
252
  end
231
253
 
232
254
  raise InvalidDatabaseError, "Unsupported record size: #{@record_size}"
@@ -238,7 +260,7 @@ module MaxMind # :nodoc:
238
260
 
239
261
  if offset_in_file >= @size
240
262
  raise InvalidDatabaseError,
241
- 'The MaxMind DB file\'s search tree is corrupt'.freeze
263
+ 'The MaxMind DB file\'s search tree is corrupt'
242
264
  end
243
265
 
244
266
  data, = @decoder.decode(offset_in_file)
@@ -257,7 +279,7 @@ module MaxMind # :nodoc:
257
279
  end
258
280
 
259
281
  raise InvalidDatabaseError,
260
- 'Metadata section not found. Is this a valid MaxMind DB file?'.freeze
282
+ 'Metadata section not found. Is this a valid MaxMind DB file?'
261
283
  end
262
284
 
263
285
  def at_metadata?(index)
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'maxmind/db/errors'
2
4
 
3
5
  module MaxMind # :nodoc:
4
6
  class DB
5
- # +Decoder+ decodes a {MaxMind DB}[http://maxmind.github.io/MaxMind-DB/]
7
+ # +Decoder+ decodes a {MaxMind DB}[https://maxmind.github.io/MaxMind-DB/]
6
8
  # data section.
7
9
  #
8
10
  # Typically you will interact with this class through a Reader rather than
@@ -47,44 +49,44 @@ module MaxMind # :nodoc:
47
49
  def decode_double(size, offset)
48
50
  verify_size(8, size)
49
51
  buf = @io.read(offset, 8)
50
- [buf.unpack('G'.freeze)[0], offset + 8]
52
+ [buf.unpack1('G'), offset + 8]
51
53
  end
52
54
 
53
55
  def decode_float(size, offset)
54
56
  verify_size(4, size)
55
57
  buf = @io.read(offset, 4)
56
- [buf.unpack('g'.freeze)[0], offset + 4]
58
+ [buf.unpack1('g'), offset + 4]
57
59
  end
58
60
 
59
61
  def verify_size(expected, actual)
60
62
  return if expected == actual
61
63
 
62
64
  raise InvalidDatabaseError,
63
- 'The MaxMind DB file\'s data section contains bad data (unknown data type or corrupt data)'.freeze
65
+ 'The MaxMind DB file\'s data section contains bad data (unknown data type or corrupt data)'
64
66
  end
65
67
 
66
68
  def decode_int32(size, offset)
67
- decode_int('l>'.freeze, 4, size, offset)
69
+ decode_int('l>', 4, size, offset)
68
70
  end
69
71
 
70
72
  def decode_uint16(size, offset)
71
- decode_int('n'.freeze, 2, size, offset)
73
+ decode_int('n', 2, size, offset)
72
74
  end
73
75
 
74
76
  def decode_uint32(size, offset)
75
- decode_int('N'.freeze, 4, size, offset)
77
+ decode_int('N', 4, size, offset)
76
78
  end
77
79
 
78
80
  def decode_uint64(size, offset)
79
- decode_int('Q>'.freeze, 8, size, offset)
81
+ decode_int('Q>', 8, size, offset)
80
82
  end
81
83
 
82
84
  def decode_int(type_code, type_size, size, offset)
83
85
  return 0, offset if size == 0
84
86
 
85
87
  buf = @io.read(offset, size)
86
- buf = buf.rjust(type_size, "\x00".freeze) if size != type_size
87
- [buf.unpack(type_code)[0], offset + size]
88
+ buf = buf.rjust(type_size, "\x00") if size != type_size
89
+ [buf.unpack1(type_code), offset + size]
88
90
  end
89
91
 
90
92
  def decode_uint128(size, offset)
@@ -93,14 +95,14 @@ module MaxMind # :nodoc:
93
95
  buf = @io.read(offset, size)
94
96
 
95
97
  if size <= 8
96
- buf = buf.rjust(8, "\x00".freeze)
97
- return buf.unpack('Q>'.freeze)[0], offset + size
98
+ buf = buf.rjust(8, "\x00")
99
+ return buf.unpack1('Q>'), offset + size
98
100
  end
99
101
 
100
- a_bytes = buf[0...-8].rjust(8, "\x00".freeze)
102
+ a_bytes = buf[0...-8].rjust(8, "\x00")
101
103
  b_bytes = buf[-8...buf.length]
102
- a = a_bytes.unpack('Q>'.freeze)[0]
103
- b = b_bytes.unpack('Q>'.freeze)[0]
104
+ a = a_bytes.unpack1('Q>')
105
+ b = b_bytes.unpack1('Q>')
104
106
  a <<= 64
105
107
  [a | b, offset + size]
106
108
  end
@@ -122,19 +124,19 @@ module MaxMind # :nodoc:
122
124
  when 0
123
125
  new_offset = offset + 1
124
126
  buf = (size & 0x7).chr << @io.read(offset, 1)
125
- pointer = buf.unpack('n'.freeze)[0] + @pointer_base
127
+ pointer = buf.unpack1('n') + @pointer_base
126
128
  when 1
127
129
  new_offset = offset + 2
128
- buf = "\x00".freeze.b << (size & 0x7).chr << @io.read(offset, 2)
129
- pointer = buf.unpack('N'.freeze)[0] + 2048 + @pointer_base
130
+ buf = "\x00".b << (size & 0x7).chr << @io.read(offset, 2)
131
+ pointer = buf.unpack1('N') + 2048 + @pointer_base
130
132
  when 2
131
133
  new_offset = offset + 3
132
134
  buf = (size & 0x7).chr << @io.read(offset, 3)
133
- pointer = buf.unpack('N'.freeze)[0] + 526_336 + @pointer_base
135
+ pointer = buf.unpack1('N') + 526_336 + @pointer_base
134
136
  else
135
137
  new_offset = offset + 4
136
138
  buf = @io.read(offset, 4)
137
- pointer = buf.unpack('N'.freeze)[0] + @pointer_base
139
+ pointer = buf.unpack1('N') + @pointer_base
138
140
  end
139
141
 
140
142
  return pointer, new_offset if @pointer_test
@@ -208,9 +210,7 @@ module MaxMind # :nodoc:
208
210
  def size_from_ctrl_byte(ctrl_byte, offset, type_num)
209
211
  size = ctrl_byte & 0x1f
210
212
 
211
- return size, offset if type_num == 1
212
-
213
- return size, offset if size < 29
213
+ return size, offset if type_num == 1 || size < 29
214
214
 
215
215
  if size == 29
216
216
  size_bytes = @io.read(offset, 1)
@@ -220,12 +220,12 @@ module MaxMind # :nodoc:
220
220
 
221
221
  if size == 30
222
222
  size_bytes = @io.read(offset, 2)
223
- size = 285 + size_bytes.unpack('n'.freeze)[0]
223
+ size = 285 + size_bytes.unpack1('n')
224
224
  return size, offset + 2
225
225
  end
226
226
 
227
- size_bytes = "\x00".freeze.b << @io.read(offset, 3)
228
- size = 65_821 + size_bytes.unpack('N'.freeze)[0]
227
+ size_bytes = "\x00".b << @io.read(offset, 3)
228
+ size = 65_821 + size_bytes.unpack1('N')
229
229
  [size, offset + 3]
230
230
  end
231
231
  end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module MaxMind # :nodoc:
2
4
  class DB
3
5
  # An InvalidDatabaseError means the {MaxMind
4
- # DB}[http://maxmind.github.io/MaxMind-DB/] file is corrupt or invalid.
6
+ # DB}[https://maxmind.github.io/MaxMind-DB/] file is corrupt or invalid.
5
7
  class InvalidDatabaseError < RuntimeError
6
8
  end
7
9
  end