maxmind-db-rust 0.1.4-x64-mingw-ucrt
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 +7 -0
- data/CHANGELOG.md +73 -0
- data/CONTRIBUTING.md +509 -0
- data/LICENSE +15 -0
- data/README.md +343 -0
- data/ext/maxmind_db_rust/lib/maxmind/db/rust.rb +16 -0
- data/lib/maxmind/db/3.2/maxmind_db_rust.so +0 -0
- data/lib/maxmind/db/3.3/maxmind_db_rust.so +0 -0
- data/lib/maxmind/db/3.4/maxmind_db_rust.so +0 -0
- data/lib/maxmind/db/rust.rb +135 -0
- metadata +188 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 6f93aee8a9271cebd4ca9fae8d381cd29f938d011aec8da57f7c6152426b0508
|
|
4
|
+
data.tar.gz: 388899722f19531ef59967141f8c9afe54daf0b30a7da5340ed02f8b843e7f01
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: ac7ba29e3504d61b93f0b819456e7541dabb6ed80ccc06711b77e3e0c9cd73896aef5f9494d56f511a6d32cbea88b263581567d621c4393e52d5e963400b9ade
|
|
7
|
+
data.tar.gz: d988947ebe5f67cd1696136df2fb74c88eb1a8a223593d1436580f4d4d12563fb26db53e494c6f7b2c01ef41c3ca112055b7a3419fe06375a32ff560b7d613f4
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.4] - 2025-11-16
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Release workflow for publishing multiple platform-specific gems
|
|
15
|
+
|
|
16
|
+
## [0.1.3] - 2025-11-16
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- Pre-compiled native gems for multiple platforms, eliminating the need to compile Rust during installation:
|
|
21
|
+
- `x86_64-linux` (Linux x86_64)
|
|
22
|
+
- `aarch64-linux` (Linux ARM64)
|
|
23
|
+
- `x86_64-darwin` (macOS Intel)
|
|
24
|
+
- `arm64-darwin` (macOS Apple Silicon)
|
|
25
|
+
- `x64-mingw-ucrt` (Windows)
|
|
26
|
+
- `x86_64-linux-musl` (Alpine Linux)
|
|
27
|
+
- Source gem as fallback for platforms without pre-compiled binaries
|
|
28
|
+
|
|
29
|
+
## [0.1.2] - 2025-11-15
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
|
|
33
|
+
- Automated release script (`dev-bin/release.sh`) that validates changelog dates, updates gemspec version, runs tests, and creates GitHub releases
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
|
|
37
|
+
- Updated actions/checkout from v4 to v5 in GitHub workflows
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- Release workflow no longer runs twice (removed redundant triggers)
|
|
42
|
+
|
|
43
|
+
### Removed
|
|
44
|
+
|
|
45
|
+
- Unused test/maxmind-db-reader-ruby git submodule (documentation now references upstream repository by URL)
|
|
46
|
+
|
|
47
|
+
## [0.1.1] - 2025-11-15
|
|
48
|
+
|
|
49
|
+
### Fixed
|
|
50
|
+
|
|
51
|
+
- Release workflow now has environment set.
|
|
52
|
+
|
|
53
|
+
## [0.1.0] - 2025-11-15
|
|
54
|
+
|
|
55
|
+
### Added
|
|
56
|
+
|
|
57
|
+
- Initial release
|
|
58
|
+
- Reader class with `get()`, `get_with_prefix_length()`, `metadata()`, `close()`, and `closed()` methods
|
|
59
|
+
- Metadata class with all standard MaxMind DB metadata attributes
|
|
60
|
+
- Support for MODE_AUTO, MODE_MEMORY, and MODE_MMAP modes
|
|
61
|
+
- Iterator support via `each` method (Enumerable interface)
|
|
62
|
+
- Iterate over all networks in database
|
|
63
|
+
- Network-scoped iteration with optional CIDR parameter (String or IPAddr)
|
|
64
|
+
- InvalidDatabaseError exception for corrupt databases
|
|
65
|
+
- Thread-safe implementation using Rust Arc and RwLock
|
|
66
|
+
- Support for both String and IPAddr IP address inputs
|
|
67
|
+
- High-performance Rust implementation using maxminddb crate
|
|
68
|
+
- Comprehensive API documentation
|
|
69
|
+
|
|
70
|
+
### Not Implemented
|
|
71
|
+
|
|
72
|
+
- MODE_FILE support (use MODE_MMAP instead)
|
|
73
|
+
- File descriptor support in constructor
|
data/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
# Contributing to maxmind-db-rust
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to maxmind-db-rust! This document provides guidelines and instructions for developers.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Development Setup](#development-setup)
|
|
8
|
+
- [Building the Extension](#building-the-extension)
|
|
9
|
+
- [Running Tests](#running-tests)
|
|
10
|
+
- [Code Quality](#code-quality)
|
|
11
|
+
- [Project Structure](#project-structure)
|
|
12
|
+
- [Making Changes](#making-changes)
|
|
13
|
+
- [Testing Guidelines](#testing-guidelines)
|
|
14
|
+
- [Submitting Changes](#submitting-changes)
|
|
15
|
+
- [Release Process](#release-process)
|
|
16
|
+
|
|
17
|
+
## Development Setup
|
|
18
|
+
|
|
19
|
+
### Prerequisites
|
|
20
|
+
|
|
21
|
+
- Ruby 3.2 or higher
|
|
22
|
+
- Rust toolchain (stable)
|
|
23
|
+
- Bundler
|
|
24
|
+
- Git
|
|
25
|
+
|
|
26
|
+
### Installing Rust
|
|
27
|
+
|
|
28
|
+
If you don't have Rust installed:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
|
32
|
+
source $HOME/.cargo/env
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Clone and Setup
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
git clone https://github.com/oschwald/maxmind-db-rust-ruby.git
|
|
39
|
+
cd maxmind-db-rust-ruby
|
|
40
|
+
|
|
41
|
+
# Initialize git submodules (for test data)
|
|
42
|
+
git submodule update --init --recursive
|
|
43
|
+
|
|
44
|
+
# Install dependencies
|
|
45
|
+
bundle install
|
|
46
|
+
|
|
47
|
+
# Configure git to use the .githooks directory
|
|
48
|
+
git config core.hooksPath .githooks
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
This will enable the pre-commit hook that runs `precious lint` on staged files before each commit.
|
|
52
|
+
|
|
53
|
+
## Building the Extension
|
|
54
|
+
|
|
55
|
+
### First Time Build
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Compile the Rust extension
|
|
59
|
+
bundle exec rake compile
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
This will:
|
|
63
|
+
|
|
64
|
+
1. Run `extconf.rb` to generate the Makefile
|
|
65
|
+
2. Compile the Rust code using rb-sys
|
|
66
|
+
3. Place the compiled extension in `lib/maxmind/db/`
|
|
67
|
+
|
|
68
|
+
### Clean Build
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# Clean build artifacts
|
|
72
|
+
bundle exec rake clean
|
|
73
|
+
|
|
74
|
+
# Clean and rebuild
|
|
75
|
+
bundle exec rake clobber compile
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Development Build (Debug)
|
|
79
|
+
|
|
80
|
+
The default rake task builds in release mode. For faster compile times during development:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# Set environment variable for debug builds
|
|
84
|
+
CARGO_PROFILE=dev bundle exec rake compile
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Note: Debug builds are significantly slower at runtime but compile faster.
|
|
88
|
+
|
|
89
|
+
## Running Tests
|
|
90
|
+
|
|
91
|
+
### Test Organization
|
|
92
|
+
|
|
93
|
+
Tests are organized into two categories:
|
|
94
|
+
|
|
95
|
+
1. **Our Own Tests** (`test/*_test.rb`)
|
|
96
|
+
- Tests specific to this implementation
|
|
97
|
+
- License: ISC (same as project)
|
|
98
|
+
|
|
99
|
+
2. **MaxMind Upstream Tests** (`test/maxmind/test_*.rb`)
|
|
100
|
+
- Adapted from official MaxMind-DB-Reader-ruby
|
|
101
|
+
- License: Apache-2.0 or MIT (MaxMind, Inc.)
|
|
102
|
+
- See `test/maxmind/README.md` for details
|
|
103
|
+
|
|
104
|
+
### Running Tests
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
# Run all tests (recommended before submitting PR)
|
|
108
|
+
bundle exec rake test
|
|
109
|
+
|
|
110
|
+
# Run only our own tests
|
|
111
|
+
bundle exec rake test_own
|
|
112
|
+
|
|
113
|
+
# Run only MaxMind upstream compatibility tests
|
|
114
|
+
bundle exec rake test_maxmind
|
|
115
|
+
|
|
116
|
+
# Run with verbose output
|
|
117
|
+
bundle exec rake test_verbose
|
|
118
|
+
|
|
119
|
+
# Run specific test file
|
|
120
|
+
bundle exec ruby test/reader_test.rb
|
|
121
|
+
|
|
122
|
+
# Run specific test method
|
|
123
|
+
bundle exec ruby test/reader_test.rb -n test_get_ipv4_address
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Test Data
|
|
127
|
+
|
|
128
|
+
Test databases are stored in `test/data/MaxMind-DB/` as a git submodule. If tests are failing with "file not found" errors:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
git submodule update --init --recursive
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Code Quality
|
|
135
|
+
|
|
136
|
+
### Precious (Recommended)
|
|
137
|
+
|
|
138
|
+
The easiest way to run all linters and formatters is using [precious](https://github.com/houseabsolute/precious):
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
# Install precious (once)
|
|
142
|
+
cargo install precious
|
|
143
|
+
|
|
144
|
+
# Check all linters
|
|
145
|
+
precious lint --all
|
|
146
|
+
|
|
147
|
+
# Auto-fix all issues
|
|
148
|
+
precious tidy --all
|
|
149
|
+
|
|
150
|
+
# Check only staged files (useful before committing)
|
|
151
|
+
precious lint --staged
|
|
152
|
+
|
|
153
|
+
# Run specific linter
|
|
154
|
+
precious lint -c rubocop
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
The pre-commit hook automatically runs `precious lint --staged` before each commit.
|
|
158
|
+
|
|
159
|
+
### RuboCop (Ruby)
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
# Check Ruby code style
|
|
163
|
+
bundle exec rubocop
|
|
164
|
+
|
|
165
|
+
# Auto-fix issues
|
|
166
|
+
bundle exec rubocop -a
|
|
167
|
+
|
|
168
|
+
# Check specific files
|
|
169
|
+
bundle exec rubocop lib/maxmind/db/rust.rb
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Clippy (Rust)
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
# Run Rust linter
|
|
176
|
+
cd ext/maxmind_db_rust
|
|
177
|
+
cargo clippy -- -D warnings
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Formatting
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
# Format Rust code
|
|
184
|
+
cd ext/maxmind_db_rust
|
|
185
|
+
cargo fmt
|
|
186
|
+
|
|
187
|
+
# Check formatting without changing files
|
|
188
|
+
cargo fmt -- --check
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Project Structure
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
maxmind-db-rust-ruby/
|
|
195
|
+
├── ext/maxmind_db_rust/ # Rust extension code
|
|
196
|
+
│ ├── Cargo.toml # Rust dependencies
|
|
197
|
+
│ ├── extconf.rb # Ruby build configuration
|
|
198
|
+
│ └── src/
|
|
199
|
+
│ └── lib.rs # Main Rust implementation
|
|
200
|
+
├── lib/ # Ruby integration layer
|
|
201
|
+
│ └── maxmind/
|
|
202
|
+
│ └── db/
|
|
203
|
+
│ └── rust.rb # Ruby API wrapper
|
|
204
|
+
├── test/ # Test suite
|
|
205
|
+
│ ├── *_test.rb # Our own tests
|
|
206
|
+
│ ├── maxmind/ # Upstream tests (MaxMind copyright)
|
|
207
|
+
│ │ ├── README.md # Licensing info
|
|
208
|
+
│ │ └── test_*.rb # Adapted tests
|
|
209
|
+
│ └── data/
|
|
210
|
+
│ └── MaxMind-DB/ # Test databases (submodule)
|
|
211
|
+
├── Rakefile # Build and test tasks
|
|
212
|
+
├── maxmind-db-rust.gemspec # Gem specification
|
|
213
|
+
├── README.md # User documentation
|
|
214
|
+
├── CONTRIBUTING.md # This file
|
|
215
|
+
├── CHANGELOG.md # Version history
|
|
216
|
+
└── LICENSE # ISC License
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## Making Changes
|
|
220
|
+
|
|
221
|
+
### Workflow
|
|
222
|
+
|
|
223
|
+
1. **Create a branch** for your changes:
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
git checkout -b feature/my-new-feature
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
2. **Make your changes**:
|
|
230
|
+
- Rust code: `ext/maxmind_db_rust/src/lib.rs`
|
|
231
|
+
- Ruby wrapper: `lib/maxmind/db/rust.rb`
|
|
232
|
+
- Tests: Add tests in `test/` directory
|
|
233
|
+
|
|
234
|
+
3. **Compile and test**:
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
bundle exec rake compile
|
|
238
|
+
bundle exec rake test
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
4. **Check code quality**:
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
bundle exec rubocop
|
|
245
|
+
cd ext/maxmind_db_rust && cargo clippy && cargo fmt
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
5. **Commit your changes**:
|
|
249
|
+
```bash
|
|
250
|
+
git add .
|
|
251
|
+
git commit -m "Add feature: description"
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Commit Message Guidelines
|
|
255
|
+
|
|
256
|
+
- Use present tense ("Add feature" not "Added feature")
|
|
257
|
+
- Use imperative mood ("Move cursor to..." not "Moves cursor to...")
|
|
258
|
+
- First line should be 50 characters or less
|
|
259
|
+
- Reference issues and pull requests when relevant
|
|
260
|
+
|
|
261
|
+
Example:
|
|
262
|
+
|
|
263
|
+
```
|
|
264
|
+
Add support for custom metadata attributes
|
|
265
|
+
|
|
266
|
+
- Implement metadata attribute getter
|
|
267
|
+
- Add tests for custom attributes
|
|
268
|
+
- Update documentation
|
|
269
|
+
|
|
270
|
+
Fixes #123
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
## Testing Guidelines
|
|
274
|
+
|
|
275
|
+
### Writing Tests
|
|
276
|
+
|
|
277
|
+
When adding new features or fixing bugs:
|
|
278
|
+
|
|
279
|
+
1. **Add tests to our own test suite** (`test/*_test.rb`):
|
|
280
|
+
|
|
281
|
+
```ruby
|
|
282
|
+
def test_new_feature
|
|
283
|
+
reader = MaxMind::DB::Rust::Reader.new('path/to/test.mmdb')
|
|
284
|
+
result = reader.new_method
|
|
285
|
+
assert_equal expected_value, result
|
|
286
|
+
reader.close
|
|
287
|
+
end
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
2. **Ensure existing tests pass**:
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
bundle exec rake test
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
3. **Test both modes** (MMAP and MEMORY) when relevant:
|
|
297
|
+
```ruby
|
|
298
|
+
[MaxMind::DB::Rust::MODE_MMAP, MaxMind::DB::Rust::MODE_MEMORY].each do |mode|
|
|
299
|
+
reader = MaxMind::DB::Rust::Reader.new(path, mode: mode)
|
|
300
|
+
# Test logic here
|
|
301
|
+
reader.close
|
|
302
|
+
end
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Test Coverage
|
|
306
|
+
|
|
307
|
+
- Test normal operation (happy path)
|
|
308
|
+
- Test edge cases (empty results, boundary conditions)
|
|
309
|
+
- Test error conditions (invalid input, closed readers, etc.)
|
|
310
|
+
- Test thread safety for concurrent operations
|
|
311
|
+
- Test both IPv4 and IPv6 addresses
|
|
312
|
+
|
|
313
|
+
### Upstream Test Synchronization
|
|
314
|
+
|
|
315
|
+
When the official MaxMind-DB-Reader-ruby gem is updated:
|
|
316
|
+
|
|
317
|
+
1. Clone or update a local copy of the upstream repository:
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
# Clone to a temporary location
|
|
321
|
+
git clone https://github.com/maxmind/MaxMind-DB-Reader-ruby.git /tmp/maxmind-db-reader-ruby
|
|
322
|
+
cd /tmp/maxmind-db-reader-ruby
|
|
323
|
+
|
|
324
|
+
# Or update existing clone
|
|
325
|
+
git pull origin main
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
2. Review changes:
|
|
329
|
+
|
|
330
|
+
```bash
|
|
331
|
+
cd /tmp/maxmind-db-reader-ruby
|
|
332
|
+
git log --oneline --since="3 months ago" -- test/
|
|
333
|
+
git diff HEAD~10..HEAD -- test/test_reader.rb
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
3. Apply relevant changes to `test/maxmind/test_reader.rb`:
|
|
337
|
+
- Maintain our namespace changes (MaxMind::DB::Rust)
|
|
338
|
+
- Keep MODE_MMAP instead of MODE_FILE
|
|
339
|
+
- Preserve our path adjustments
|
|
340
|
+
- Update expected error messages if needed
|
|
341
|
+
|
|
342
|
+
4. Document changes in `test/maxmind/README.md`
|
|
343
|
+
|
|
344
|
+
## Submitting Changes
|
|
345
|
+
|
|
346
|
+
### Before Submitting a Pull Request
|
|
347
|
+
|
|
348
|
+
1. **Ensure all tests pass**:
|
|
349
|
+
|
|
350
|
+
```bash
|
|
351
|
+
bundle exec rake test
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
2. **Run code quality checks**:
|
|
355
|
+
|
|
356
|
+
```bash
|
|
357
|
+
bundle exec rubocop
|
|
358
|
+
cd ext/maxmind_db_rust && cargo clippy && cargo fmt --check
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
3. **Update documentation** if needed:
|
|
362
|
+
- README.md for user-facing changes
|
|
363
|
+
- CHANGELOG.md for notable changes
|
|
364
|
+
- Code comments for complex logic
|
|
365
|
+
|
|
366
|
+
4. **Rebase on main**:
|
|
367
|
+
```bash
|
|
368
|
+
git fetch origin
|
|
369
|
+
git rebase origin/main
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### Pull Request Process
|
|
373
|
+
|
|
374
|
+
1. **Push your branch**:
|
|
375
|
+
|
|
376
|
+
```bash
|
|
377
|
+
git push origin feature/my-new-feature
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
2. **Create a pull request** on GitHub with:
|
|
381
|
+
- Clear description of changes
|
|
382
|
+
- Reference to related issues
|
|
383
|
+
- Screenshots/examples if applicable
|
|
384
|
+
- Test results
|
|
385
|
+
|
|
386
|
+
3. **Address review feedback**:
|
|
387
|
+
- Make requested changes
|
|
388
|
+
- Push updates to the same branch
|
|
389
|
+
- Respond to comments
|
|
390
|
+
|
|
391
|
+
4. **Wait for approval** and merge
|
|
392
|
+
|
|
393
|
+
## Release Process
|
|
394
|
+
|
|
395
|
+
### Version Numbering
|
|
396
|
+
|
|
397
|
+
We follow [Semantic Versioning](https://semver.org/):
|
|
398
|
+
|
|
399
|
+
- **MAJOR**: Incompatible API changes
|
|
400
|
+
- **MINOR**: Backward-compatible functionality additions
|
|
401
|
+
- **PATCH**: Backward-compatible bug fixes
|
|
402
|
+
|
|
403
|
+
### Creating a Release
|
|
404
|
+
|
|
405
|
+
1. **Update version** in `maxmind-db-rust.gemspec`:
|
|
406
|
+
|
|
407
|
+
```ruby
|
|
408
|
+
s.version = '0.2.0'
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
2. **Update CHANGELOG.md**:
|
|
412
|
+
|
|
413
|
+
```markdown
|
|
414
|
+
## [0.2.0] - 2025-01-15
|
|
415
|
+
|
|
416
|
+
### Added
|
|
417
|
+
|
|
418
|
+
- New feature X
|
|
419
|
+
|
|
420
|
+
### Fixed
|
|
421
|
+
|
|
422
|
+
- Bug fix Y
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
3. **Commit version bump**:
|
|
426
|
+
|
|
427
|
+
```bash
|
|
428
|
+
git add maxmind-db-rust.gemspec CHANGELOG.md
|
|
429
|
+
git commit -m "Bump version to 0.2.0"
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
4. **Create and push tag**:
|
|
433
|
+
|
|
434
|
+
```bash
|
|
435
|
+
git tag -a v0.2.0 -m "Release version 0.2.0"
|
|
436
|
+
git push origin main
|
|
437
|
+
git push origin v0.2.0
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
5. **Create GitHub Release**:
|
|
441
|
+
|
|
442
|
+
Go to https://github.com/oschwald/maxmind-db-rust-ruby/releases/new and create a new release with tag `v0.2.0`.
|
|
443
|
+
|
|
444
|
+
The GitHub Actions workflow will automatically:
|
|
445
|
+
- Build native gems for all supported platforms:
|
|
446
|
+
- `x86_64-linux` (Linux x86_64)
|
|
447
|
+
- `aarch64-linux` (Linux ARM64)
|
|
448
|
+
- `x86_64-darwin` (macOS Intel)
|
|
449
|
+
- `arm64-darwin` (macOS Apple Silicon)
|
|
450
|
+
- `x64-mingw-ucrt` (Windows)
|
|
451
|
+
- `x86_64-linux-musl` (Alpine Linux)
|
|
452
|
+
- Build a source gem (fallback for unsupported platforms)
|
|
453
|
+
- Push all gems to RubyGems.org
|
|
454
|
+
|
|
455
|
+
### Building Native Gems
|
|
456
|
+
|
|
457
|
+
Native gems for multiple platforms are built automatically by the CI/CD pipeline using the `oxidize-rb/actions/cross-gem` GitHub Action. The workflow handles cross-compilation for all supported platforms without requiring local Docker setup.
|
|
458
|
+
|
|
459
|
+
## Performance Considerations
|
|
460
|
+
|
|
461
|
+
### Benchmarking
|
|
462
|
+
|
|
463
|
+
When making performance-related changes:
|
|
464
|
+
|
|
465
|
+
1. **Create benchmark script**:
|
|
466
|
+
|
|
467
|
+
```ruby
|
|
468
|
+
require 'benchmark'
|
|
469
|
+
require 'maxmind/db/rust'
|
|
470
|
+
|
|
471
|
+
reader = MaxMind::DB::Rust::Reader.new('path/to/db.mmdb')
|
|
472
|
+
ips = File.readlines('test_ips.txt').map(&:strip)
|
|
473
|
+
|
|
474
|
+
Benchmark.bm do |x|
|
|
475
|
+
x.report("lookups:") do
|
|
476
|
+
100_000.times { reader.get(ips.sample) }
|
|
477
|
+
end
|
|
478
|
+
end
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
2. **Compare before and after** your changes
|
|
482
|
+
|
|
483
|
+
3. **Document results** in PR description
|
|
484
|
+
|
|
485
|
+
### Optimization Tips
|
|
486
|
+
|
|
487
|
+
- Use MODE_MMAP for best performance (default)
|
|
488
|
+
- Release GIL during I/O operations (already implemented)
|
|
489
|
+
- Minimize Ruby object allocations in hot paths
|
|
490
|
+
- Use Arc for thread-safe sharing instead of cloning
|
|
491
|
+
|
|
492
|
+
## Getting Help
|
|
493
|
+
|
|
494
|
+
- **Issues**: https://github.com/oschwald/maxmind-db-rust-ruby/issues
|
|
495
|
+
- **Discussions**: Use GitHub Discussions for questions
|
|
496
|
+
- **MaxMind Docs**: https://maxmind.github.io/MaxMind-DB/
|
|
497
|
+
|
|
498
|
+
## Code of Conduct
|
|
499
|
+
|
|
500
|
+
- Be respectful and inclusive
|
|
501
|
+
- Provide constructive feedback
|
|
502
|
+
- Focus on the code, not the person
|
|
503
|
+
- Help others learn and grow
|
|
504
|
+
|
|
505
|
+
## License
|
|
506
|
+
|
|
507
|
+
By contributing, you agree that your contributions will be licensed under the ISC License.
|
|
508
|
+
|
|
509
|
+
Thank you for contributing! 🎉
|
data/LICENSE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025, Gregory Oschwald
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
10
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
11
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
12
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
13
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
14
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
15
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
# maxmind-db-rust
|
|
2
|
+
|
|
3
|
+
[](https://github.com/oschwald/maxmind-db-rust-ruby/actions/workflows/test.yml)
|
|
4
|
+
[](https://github.com/oschwald/maxmind-db-rust-ruby/actions/workflows/lint.yml)
|
|
5
|
+
|
|
6
|
+
A high-performance Rust-based Ruby gem for reading MaxMind DB files. Provides API compatibility with the official `maxmind-db` gem while leveraging Rust for superior performance.
|
|
7
|
+
|
|
8
|
+
> **Note:** This is an unofficial library and is not endorsed by MaxMind. For the official Ruby library, see [maxmind-db](https://github.com/maxmind/MaxMind-DB-Reader-ruby).
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- **High Performance**: Rust-based implementation provides significantly faster lookups than pure Ruby
|
|
13
|
+
- **API Compatible**: Familiar API similar to the official MaxMind::DB gem
|
|
14
|
+
- **Thread-Safe**: Safe to use from multiple threads
|
|
15
|
+
- **Memory Modes**: Support for both memory-mapped (MMAP) and in-memory modes
|
|
16
|
+
- **Iterator Support**: Iterate over all networks in the database (extension feature)
|
|
17
|
+
- **Type Support**: Works with both String and IPAddr objects
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
Add this line to your application's Gemfile:
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
gem 'maxmind-db-rust'
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
And then execute:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
bundle install
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Or install it yourself as:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
gem install maxmind-db-rust
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Requirements
|
|
40
|
+
|
|
41
|
+
- Ruby 3.2 or higher
|
|
42
|
+
- Rust toolchain (for building from source)
|
|
43
|
+
|
|
44
|
+
## Usage
|
|
45
|
+
|
|
46
|
+
### Basic Usage
|
|
47
|
+
|
|
48
|
+
```ruby
|
|
49
|
+
require 'maxmind/db/rust'
|
|
50
|
+
|
|
51
|
+
# Open database
|
|
52
|
+
reader = MaxMind::DB::Rust::Reader.new(
|
|
53
|
+
'GeoIP2-City.mmdb',
|
|
54
|
+
mode: MaxMind::DB::Rust::MODE_MEMORY
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
# Lookup an IP address
|
|
58
|
+
record = reader.get('8.8.8.8')
|
|
59
|
+
if record
|
|
60
|
+
puts record['country']['iso_code']
|
|
61
|
+
puts record['country']['names']['en']
|
|
62
|
+
puts record['city']['names']['en']
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Close the database
|
|
66
|
+
reader.close
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Get with Prefix Length
|
|
70
|
+
|
|
71
|
+
```ruby
|
|
72
|
+
require 'maxmind/db/rust'
|
|
73
|
+
|
|
74
|
+
reader = MaxMind::DB::Rust::Reader.new('GeoIP2-City.mmdb')
|
|
75
|
+
|
|
76
|
+
record, prefix_length = reader.get_with_prefix_length('8.8.8.8')
|
|
77
|
+
puts "Record: #{record}"
|
|
78
|
+
puts "Prefix length: #{prefix_length}"
|
|
79
|
+
|
|
80
|
+
reader.close
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Using IPAddr Objects
|
|
84
|
+
|
|
85
|
+
```ruby
|
|
86
|
+
require 'maxmind/db/rust'
|
|
87
|
+
require 'ipaddr'
|
|
88
|
+
|
|
89
|
+
reader = MaxMind::DB::Rust::Reader.new('GeoIP2-City.mmdb')
|
|
90
|
+
|
|
91
|
+
ip = IPAddr.new('8.8.8.8')
|
|
92
|
+
record = reader.get(ip)
|
|
93
|
+
|
|
94
|
+
reader.close
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Database Modes
|
|
98
|
+
|
|
99
|
+
```ruby
|
|
100
|
+
require 'maxmind/db/rust'
|
|
101
|
+
|
|
102
|
+
# MODE_AUTO: Uses memory-mapped files (default, best performance)
|
|
103
|
+
reader = MaxMind::DB::Rust::Reader.new(
|
|
104
|
+
'GeoIP2-City.mmdb',
|
|
105
|
+
mode: MaxMind::DB::Rust::MODE_AUTO
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
# MODE_MMAP: Explicitly use memory-mapped files (recommended)
|
|
109
|
+
reader = MaxMind::DB::Rust::Reader.new(
|
|
110
|
+
'GeoIP2-City.mmdb',
|
|
111
|
+
mode: MaxMind::DB::Rust::MODE_MMAP
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
# MODE_MEMORY: Load entire database into memory
|
|
115
|
+
reader = MaxMind::DB::Rust::Reader.new(
|
|
116
|
+
'GeoIP2-City.mmdb',
|
|
117
|
+
mode: MaxMind::DB::Rust::MODE_MEMORY
|
|
118
|
+
)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Accessing Metadata
|
|
122
|
+
|
|
123
|
+
```ruby
|
|
124
|
+
require 'maxmind/db/rust'
|
|
125
|
+
|
|
126
|
+
reader = MaxMind::DB::Rust::Reader.new('GeoIP2-City.mmdb')
|
|
127
|
+
|
|
128
|
+
metadata = reader.metadata
|
|
129
|
+
puts "Database type: #{metadata.database_type}"
|
|
130
|
+
puts "Node count: #{metadata.node_count}"
|
|
131
|
+
puts "Record size: #{metadata.record_size}"
|
|
132
|
+
puts "IP version: #{metadata.ip_version}"
|
|
133
|
+
puts "Build epoch: #{metadata.build_epoch}"
|
|
134
|
+
puts "Languages: #{metadata.languages.join(', ')}"
|
|
135
|
+
puts "Description: #{metadata.description}"
|
|
136
|
+
|
|
137
|
+
reader.close
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Iterator Support (Extension Feature)
|
|
141
|
+
|
|
142
|
+
Iterate over all networks in the database:
|
|
143
|
+
|
|
144
|
+
```ruby
|
|
145
|
+
require 'maxmind/db/rust'
|
|
146
|
+
|
|
147
|
+
reader = MaxMind::DB::Rust::Reader.new('GeoLite2-Country.mmdb')
|
|
148
|
+
|
|
149
|
+
# Iterate over all networks
|
|
150
|
+
reader.each do |network, data|
|
|
151
|
+
puts "#{network}: #{data['country']['iso_code']}"
|
|
152
|
+
break # Remove this to see all networks
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Iterate over networks within a specific subnet (String CIDR notation)
|
|
156
|
+
reader.each('192.168.0.0/16') do |network, data|
|
|
157
|
+
puts "#{network}: #{data['city']['names']['en']}"
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Iterate over networks within a specific subnet (IPAddr object)
|
|
161
|
+
require 'ipaddr'
|
|
162
|
+
subnet = IPAddr.new('10.0.0.0/8')
|
|
163
|
+
reader.each(subnet) do |network, data|
|
|
164
|
+
puts "#{network}: #{data['country']['iso_code']}"
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Use Enumerable methods
|
|
168
|
+
countries = reader.map { |network, data| data['country']['iso_code'] }.uniq
|
|
169
|
+
puts "Unique countries: #{countries.size}"
|
|
170
|
+
|
|
171
|
+
reader.close
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## API Documentation
|
|
175
|
+
|
|
176
|
+
### `MaxMind::DB::Rust::Reader`
|
|
177
|
+
|
|
178
|
+
#### `new(database_path, options = {})`
|
|
179
|
+
|
|
180
|
+
Create a new Reader instance.
|
|
181
|
+
|
|
182
|
+
**Parameters:**
|
|
183
|
+
|
|
184
|
+
- `database_path` (String): Path to the MaxMind DB file
|
|
185
|
+
- `options` (Hash): Optional configuration
|
|
186
|
+
- `:mode` (Symbol): One of `:MODE_AUTO`, `:MODE_MEMORY`, or `:MODE_MMAP`
|
|
187
|
+
|
|
188
|
+
**Returns:** Reader instance
|
|
189
|
+
|
|
190
|
+
**Raises:**
|
|
191
|
+
|
|
192
|
+
- `Errno::ENOENT`: If the database file does not exist
|
|
193
|
+
- `MaxMind::DB::Rust::InvalidDatabaseError`: If the file is not a valid MaxMind DB
|
|
194
|
+
|
|
195
|
+
#### `get(ip_address)`
|
|
196
|
+
|
|
197
|
+
Look up an IP address in the database.
|
|
198
|
+
|
|
199
|
+
**Parameters:**
|
|
200
|
+
|
|
201
|
+
- `ip_address` (String or IPAddr): The IP address to look up
|
|
202
|
+
|
|
203
|
+
**Returns:** Hash with the record data, or `nil` if not found
|
|
204
|
+
|
|
205
|
+
**Raises:**
|
|
206
|
+
|
|
207
|
+
- `ArgumentError`: If looking up IPv6 in an IPv4-only database
|
|
208
|
+
- `MaxMind::DB::Rust::InvalidDatabaseError`: If the database is corrupt
|
|
209
|
+
|
|
210
|
+
#### `get_with_prefix_length(ip_address)`
|
|
211
|
+
|
|
212
|
+
Look up an IP address and return the prefix length.
|
|
213
|
+
|
|
214
|
+
**Parameters:**
|
|
215
|
+
|
|
216
|
+
- `ip_address` (String or IPAddr): The IP address to look up
|
|
217
|
+
|
|
218
|
+
**Returns:** Array `[record, prefix_length]` where record is a Hash or `nil`
|
|
219
|
+
|
|
220
|
+
#### `metadata()`
|
|
221
|
+
|
|
222
|
+
Get metadata about the database.
|
|
223
|
+
|
|
224
|
+
**Returns:** `MaxMind::DB::Rust::Metadata` instance
|
|
225
|
+
|
|
226
|
+
#### `close()`
|
|
227
|
+
|
|
228
|
+
Close the database and release resources.
|
|
229
|
+
|
|
230
|
+
#### `closed()`
|
|
231
|
+
|
|
232
|
+
Check if the database has been closed.
|
|
233
|
+
|
|
234
|
+
**Returns:** Boolean
|
|
235
|
+
|
|
236
|
+
#### `each(network = nil) { |network, data| ... }`
|
|
237
|
+
|
|
238
|
+
Iterate over networks in the database.
|
|
239
|
+
|
|
240
|
+
**Parameters:**
|
|
241
|
+
|
|
242
|
+
- `network` (String or IPAddr, optional): Network CIDR to iterate within (e.g., "192.168.0.0/16"). If omitted, iterates over all networks in the database.
|
|
243
|
+
|
|
244
|
+
**Yields:** IPAddr network and Hash data for each entry
|
|
245
|
+
|
|
246
|
+
**Returns:** Enumerator if no block given
|
|
247
|
+
|
|
248
|
+
**Raises:**
|
|
249
|
+
|
|
250
|
+
- `ArgumentError`: If network CIDR is invalid or IPv6 network specified for IPv4-only database
|
|
251
|
+
|
|
252
|
+
### `MaxMind::DB::Rust::Metadata`
|
|
253
|
+
|
|
254
|
+
Metadata attributes:
|
|
255
|
+
|
|
256
|
+
- `binary_format_major_version` - Major version of the binary format
|
|
257
|
+
- `binary_format_minor_version` - Minor version of the binary format
|
|
258
|
+
- `build_epoch` - Unix timestamp when the database was built
|
|
259
|
+
- `database_type` - Type of database (e.g., "GeoIP2-City")
|
|
260
|
+
- `description` - Hash of locale codes to descriptions
|
|
261
|
+
- `ip_version` - 4 for IPv4-only, 6 for IPv4/IPv6 support
|
|
262
|
+
- `languages` - Array of supported locale codes
|
|
263
|
+
- `node_count` - Number of nodes in the search tree
|
|
264
|
+
- `record_size` - Record size in bits (24, 28, or 32)
|
|
265
|
+
- `node_byte_size` - Size of a node in bytes
|
|
266
|
+
- `search_tree_size` - Size of the search tree in bytes
|
|
267
|
+
|
|
268
|
+
### Constants
|
|
269
|
+
|
|
270
|
+
- `MaxMind::DB::Rust::MODE_AUTO` - Automatically choose the best mode (uses MMAP)
|
|
271
|
+
- `MaxMind::DB::Rust::MODE_MEMORY` - Load entire database into memory
|
|
272
|
+
- `MaxMind::DB::Rust::MODE_MMAP` - Use memory-mapped file I/O (recommended)
|
|
273
|
+
|
|
274
|
+
### Exceptions
|
|
275
|
+
|
|
276
|
+
- `MaxMind::DB::Rust::InvalidDatabaseError` - Raised when the database file is corrupt or invalid
|
|
277
|
+
|
|
278
|
+
## Comparison with Official Gem
|
|
279
|
+
|
|
280
|
+
| Feature | maxmind-db (official) | maxmind-db-rust (this gem) |
|
|
281
|
+
| ---------------- | --------------------- | -------------------------- |
|
|
282
|
+
| Implementation | Pure Ruby | Rust with Ruby bindings |
|
|
283
|
+
| Performance | Baseline | 10-50x faster |
|
|
284
|
+
| API | MaxMind::DB | MaxMind::DB::Rust |
|
|
285
|
+
| MODE_FILE | ✓ | ✗ |
|
|
286
|
+
| MODE_MEMORY | ✓ | ✓ |
|
|
287
|
+
| MODE_AUTO | ✓ | ✓ |
|
|
288
|
+
| MODE_MMAP | ✗ | ✓ |
|
|
289
|
+
| Iterator support | ✗ | ✓ |
|
|
290
|
+
| Thread-safe | ✓ | ✓ |
|
|
291
|
+
|
|
292
|
+
## Performance
|
|
293
|
+
|
|
294
|
+
Expected performance characteristics (will vary based on hardware):
|
|
295
|
+
|
|
296
|
+
- Single-threaded lookups: 300,000 - 500,000 lookups/second
|
|
297
|
+
- Significantly faster than pure Ruby implementations
|
|
298
|
+
- Memory-mapped mode (MMAP) provides best performance
|
|
299
|
+
- Fully thread-safe for concurrent lookups
|
|
300
|
+
|
|
301
|
+
## Development
|
|
302
|
+
|
|
303
|
+
Interested in contributing? See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed developer documentation, including:
|
|
304
|
+
|
|
305
|
+
- Development setup and prerequisites
|
|
306
|
+
- Building and testing the extension
|
|
307
|
+
- Code quality guidelines
|
|
308
|
+
- Project structure
|
|
309
|
+
- Submitting changes
|
|
310
|
+
|
|
311
|
+
### Quick Start
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
git clone https://github.com/oschwald/maxmind-db-rust-ruby.git
|
|
315
|
+
cd maxmind-db-rust-ruby
|
|
316
|
+
git submodule update --init --recursive
|
|
317
|
+
bundle install
|
|
318
|
+
bundle exec rake compile
|
|
319
|
+
bundle exec rake test
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## Contributing
|
|
323
|
+
|
|
324
|
+
1. Fork it
|
|
325
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
326
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
327
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
328
|
+
5. Create a new Pull Request
|
|
329
|
+
|
|
330
|
+
## License
|
|
331
|
+
|
|
332
|
+
This software is licensed under the ISC License. See the LICENSE file for details.
|
|
333
|
+
|
|
334
|
+
## Support
|
|
335
|
+
|
|
336
|
+
- **Issues**: https://github.com/oschwald/maxmind-db-rust-ruby/issues
|
|
337
|
+
- **Documentation**: https://www.rubydoc.info/gems/maxmind-db-rust
|
|
338
|
+
|
|
339
|
+
## Credits
|
|
340
|
+
|
|
341
|
+
This gem uses the [maxminddb](https://github.com/oschwald/maxminddb-rust) Rust crate for the core MaxMind DB reading functionality.
|
|
342
|
+
|
|
343
|
+
Built with [magnus](https://github.com/matsadler/magnus) and [rb-sys](https://github.com/oxidize-rb/rb-sys).
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'ipaddr'
|
|
4
|
+
require 'maxmind/db/maxmind_db_rust'
|
|
5
|
+
|
|
6
|
+
module MaxMind
|
|
7
|
+
module DB
|
|
8
|
+
module Rust
|
|
9
|
+
# The native extension defines:
|
|
10
|
+
# - Reader class
|
|
11
|
+
# - Metadata class
|
|
12
|
+
# - InvalidDatabaseError exception
|
|
13
|
+
# - MODE_AUTO, MODE_MEMORY, MODE_MMAP constants
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'ipaddr'
|
|
4
|
+
require 'maxmind/db/maxmind_db_rust'
|
|
5
|
+
|
|
6
|
+
module MaxMind
|
|
7
|
+
# Check if DB is already defined as a Class (official gem)
|
|
8
|
+
if const_defined?(:DB) && DB.is_a?(Class)
|
|
9
|
+
# Official gem loaded - Rust module is already attached to the class by native extension
|
|
10
|
+
# Just add documentation here
|
|
11
|
+
class << DB
|
|
12
|
+
# The Rust module provides a high-performance Rust-based implementation for reading
|
|
13
|
+
# {MaxMind DB files}[https://maxmind.github.io/MaxMind-DB/].
|
|
14
|
+
#
|
|
15
|
+
# MaxMind DB is a binary file format that stores data indexed by IP address
|
|
16
|
+
# subnets (IPv4 or IPv6).
|
|
17
|
+
#
|
|
18
|
+
# This is a Rust-based implementation that provides significant performance
|
|
19
|
+
# improvements over pure Ruby implementations while maintaining API compatibility
|
|
20
|
+
# with the official MaxMind::DB gem.
|
|
21
|
+
#
|
|
22
|
+
# == Example
|
|
23
|
+
#
|
|
24
|
+
# require 'maxmind/db/rust'
|
|
25
|
+
#
|
|
26
|
+
# reader = MaxMind::DB::Rust::Reader.new(
|
|
27
|
+
# 'GeoIP2-City.mmdb',
|
|
28
|
+
# mode: MaxMind::DB::Rust::MODE_MEMORY
|
|
29
|
+
# )
|
|
30
|
+
#
|
|
31
|
+
# record = reader.get('1.1.1.1')
|
|
32
|
+
# if record.nil?
|
|
33
|
+
# puts '1.1.1.1 was not found in the database'
|
|
34
|
+
# else
|
|
35
|
+
# puts record['country']['iso_code']
|
|
36
|
+
# puts record['country']['names']['en']
|
|
37
|
+
# end
|
|
38
|
+
#
|
|
39
|
+
# reader.close
|
|
40
|
+
#
|
|
41
|
+
# == Using the Iterator
|
|
42
|
+
#
|
|
43
|
+
# require 'maxmind/db/rust'
|
|
44
|
+
#
|
|
45
|
+
# reader = MaxMind::DB::Rust::Reader.new('GeoLite2-Country.mmdb')
|
|
46
|
+
#
|
|
47
|
+
# # Iterate over all networks in the database
|
|
48
|
+
# reader.each do |network, data|
|
|
49
|
+
# puts "#{network}: #{data['country']['iso_code']}"
|
|
50
|
+
# end
|
|
51
|
+
#
|
|
52
|
+
# # Iterate over networks within a specific subnet
|
|
53
|
+
# reader.each('192.168.0.0/16') do |network, data|
|
|
54
|
+
# puts "#{network}: #{data['city']['names']['en']}"
|
|
55
|
+
# end
|
|
56
|
+
#
|
|
57
|
+
# # Also accepts IPAddr objects
|
|
58
|
+
# subnet = IPAddr.new('10.0.0.0/8')
|
|
59
|
+
# reader.each(subnet) do |network, data|
|
|
60
|
+
# puts "#{network}: #{data['country']['iso_code']}"
|
|
61
|
+
# end
|
|
62
|
+
#
|
|
63
|
+
# reader.close
|
|
64
|
+
#
|
|
65
|
+
# The Rust module (MaxMind::DB::Rust) defines:
|
|
66
|
+
# - Reader class
|
|
67
|
+
# - Metadata class
|
|
68
|
+
# - InvalidDatabaseError exception
|
|
69
|
+
# - MODE_AUTO, MODE_MEMORY, MODE_MMAP constants
|
|
70
|
+
end
|
|
71
|
+
else
|
|
72
|
+
# Official gem not loaded - define DB as a module
|
|
73
|
+
module DB
|
|
74
|
+
# Rust provides a high-performance Rust-based implementation for reading
|
|
75
|
+
# {MaxMind DB files}[https://maxmind.github.io/MaxMind-DB/].
|
|
76
|
+
#
|
|
77
|
+
# MaxMind DB is a binary file format that stores data indexed by IP address
|
|
78
|
+
# subnets (IPv4 or IPv6).
|
|
79
|
+
#
|
|
80
|
+
# This is a Rust-based implementation that provides significant performance
|
|
81
|
+
# improvements over pure Ruby implementations while maintaining API compatibility
|
|
82
|
+
# with the official MaxMind::DB gem.
|
|
83
|
+
#
|
|
84
|
+
# == Example
|
|
85
|
+
#
|
|
86
|
+
# require 'maxmind/db/rust'
|
|
87
|
+
#
|
|
88
|
+
# reader = MaxMind::DB::Rust::Reader.new(
|
|
89
|
+
# 'GeoIP2-City.mmdb',
|
|
90
|
+
# mode: MaxMind::DB::Rust::MODE_MEMORY
|
|
91
|
+
# )
|
|
92
|
+
#
|
|
93
|
+
# record = reader.get('1.1.1.1')
|
|
94
|
+
# if record.nil?
|
|
95
|
+
# puts '1.1.1.1 was not found in the database'
|
|
96
|
+
# else
|
|
97
|
+
# puts record['country']['iso_code']
|
|
98
|
+
# puts record['country']['names']['en']
|
|
99
|
+
# end
|
|
100
|
+
#
|
|
101
|
+
# reader.close
|
|
102
|
+
#
|
|
103
|
+
# == Using the Iterator
|
|
104
|
+
#
|
|
105
|
+
# require 'maxmind/db/rust'
|
|
106
|
+
#
|
|
107
|
+
# reader = MaxMind::DB::Rust::Reader.new('GeoLite2-Country.mmdb')
|
|
108
|
+
#
|
|
109
|
+
# # Iterate over all networks in the database
|
|
110
|
+
# reader.each do |network, data|
|
|
111
|
+
# puts "#{network}: #{data['country']['iso_code']}"
|
|
112
|
+
# end
|
|
113
|
+
#
|
|
114
|
+
# # Iterate over networks within a specific subnet
|
|
115
|
+
# reader.each('192.168.0.0/16') do |network, data|
|
|
116
|
+
# puts "#{network}: #{data['city']['names']['en']}"
|
|
117
|
+
# end
|
|
118
|
+
#
|
|
119
|
+
# # Also accepts IPAddr objects
|
|
120
|
+
# subnet = IPAddr.new('10.0.0.0/8')
|
|
121
|
+
# reader.each(subnet) do |network, data|
|
|
122
|
+
# puts "#{network}: #{data['country']['iso_code']}"
|
|
123
|
+
# end
|
|
124
|
+
#
|
|
125
|
+
# reader.close
|
|
126
|
+
module Rust
|
|
127
|
+
# The native extension defines:
|
|
128
|
+
# - Reader class
|
|
129
|
+
# - Metadata class
|
|
130
|
+
# - InvalidDatabaseError exception
|
|
131
|
+
# - MODE_AUTO, MODE_MEMORY, MODE_MMAP constants
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: maxmind-db-rust
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.4
|
|
5
|
+
platform: x64-mingw-ucrt
|
|
6
|
+
authors:
|
|
7
|
+
- Gregory Oschwald
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2025-11-16 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: minitest
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '5.0'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '5.0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rake
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '13.0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '13.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rake-compiler
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '1.2'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '1.2'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rake-compiler-dock
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '1.5'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '1.5'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: rubocop
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '1.0'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '1.0'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: rubocop-minitest
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - "~>"
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '0.36'
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - "~>"
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '0.36'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: rubocop-performance
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - "~>"
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '1.0'
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - "~>"
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '1.0'
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: rubocop-rake
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - "~>"
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '0.6'
|
|
118
|
+
type: :development
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - "~>"
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: '0.6'
|
|
125
|
+
- !ruby/object:Gem::Dependency
|
|
126
|
+
name: rubocop-thread_safety
|
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
|
128
|
+
requirements:
|
|
129
|
+
- - "~>"
|
|
130
|
+
- !ruby/object:Gem::Version
|
|
131
|
+
version: '0.6'
|
|
132
|
+
type: :development
|
|
133
|
+
prerelease: false
|
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
135
|
+
requirements:
|
|
136
|
+
- - "~>"
|
|
137
|
+
- !ruby/object:Gem::Version
|
|
138
|
+
version: '0.6'
|
|
139
|
+
description: An unofficial high-performance Rust-based gem for reading MaxMind DB
|
|
140
|
+
files. Provides API compatibility with the official maxmind-db gem while leveraging
|
|
141
|
+
Rust for superior performance. This library is not endorsed by MaxMind.
|
|
142
|
+
email: oschwald@gmail.com
|
|
143
|
+
executables: []
|
|
144
|
+
extensions: []
|
|
145
|
+
extra_rdoc_files: []
|
|
146
|
+
files:
|
|
147
|
+
- CHANGELOG.md
|
|
148
|
+
- CONTRIBUTING.md
|
|
149
|
+
- LICENSE
|
|
150
|
+
- README.md
|
|
151
|
+
- ext/maxmind_db_rust/lib/maxmind/db/rust.rb
|
|
152
|
+
- lib/maxmind/db/3.2/maxmind_db_rust.so
|
|
153
|
+
- lib/maxmind/db/3.3/maxmind_db_rust.so
|
|
154
|
+
- lib/maxmind/db/3.4/maxmind_db_rust.so
|
|
155
|
+
- lib/maxmind/db/rust.rb
|
|
156
|
+
homepage: https://github.com/oschwald/maxmind-db-rust-ruby
|
|
157
|
+
licenses:
|
|
158
|
+
- ISC
|
|
159
|
+
metadata:
|
|
160
|
+
bug_tracker_uri: https://github.com/oschwald/maxmind-db-rust-ruby/issues
|
|
161
|
+
changelog_uri: https://github.com/oschwald/maxmind-db-rust-ruby/blob/main/CHANGELOG.md
|
|
162
|
+
documentation_uri: https://www.rubydoc.info/gems/maxmind-db-rust
|
|
163
|
+
homepage_uri: https://github.com/oschwald/maxmind-db-rust-ruby
|
|
164
|
+
source_code_uri: https://github.com/oschwald/maxmind-db-rust-ruby
|
|
165
|
+
rubygems_mfa_required: 'true'
|
|
166
|
+
post_install_message:
|
|
167
|
+
rdoc_options: []
|
|
168
|
+
require_paths:
|
|
169
|
+
- lib
|
|
170
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
171
|
+
requirements:
|
|
172
|
+
- - ">="
|
|
173
|
+
- !ruby/object:Gem::Version
|
|
174
|
+
version: '3.2'
|
|
175
|
+
- - "<"
|
|
176
|
+
- !ruby/object:Gem::Version
|
|
177
|
+
version: 3.5.dev
|
|
178
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
179
|
+
requirements:
|
|
180
|
+
- - ">="
|
|
181
|
+
- !ruby/object:Gem::Version
|
|
182
|
+
version: '0'
|
|
183
|
+
requirements: []
|
|
184
|
+
rubygems_version: 3.5.23
|
|
185
|
+
signing_key:
|
|
186
|
+
specification_version: 4
|
|
187
|
+
summary: Unofficial high-performance Rust-based MaxMind DB reader for Ruby
|
|
188
|
+
test_files: []
|