iptocc 3.2.0__tar.gz → 3.2.2__tar.gz

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.
Files changed (31) hide show
  1. {iptocc-3.2.0 → iptocc-3.2.2}/Cargo.lock +3 -3
  2. {iptocc-3.2.0 → iptocc-3.2.2}/PKG-INFO +1 -1
  3. {iptocc-3.2.0 → iptocc-3.2.2}/bindings/python/Cargo.toml +1 -1
  4. {iptocc-3.2.0 → iptocc-3.2.2}/crate/Cargo.toml +1 -1
  5. {iptocc-3.2.0 → iptocc-3.2.2}/crate/src/bin/generate-data.rs +90 -3
  6. {iptocc-3.2.0 → iptocc-3.2.2}/crate/src/data/v4.bin +0 -0
  7. {iptocc-3.2.0 → iptocc-3.2.2}/crate/src/data/v6.bin +82 -78
  8. {iptocc-3.2.0 → iptocc-3.2.2}/Cargo.toml +0 -0
  9. {iptocc-3.2.0 → iptocc-3.2.2}/LICENSE-APACHE +0 -0
  10. {iptocc-3.2.0 → iptocc-3.2.2}/LICENSE-MIT +0 -0
  11. {iptocc-3.2.0 → iptocc-3.2.2}/README.md +0 -0
  12. {iptocc-3.2.0 → iptocc-3.2.2}/bindings/python/LICENSE-APACHE +0 -0
  13. {iptocc-3.2.0 → iptocc-3.2.2}/bindings/python/LICENSE-MIT +0 -0
  14. {iptocc-3.2.0 → iptocc-3.2.2}/bindings/python/README.md +0 -0
  15. {iptocc-3.2.0 → iptocc-3.2.2}/bindings/python/benchmarks/bench_lookup.py +0 -0
  16. {iptocc-3.2.0 → iptocc-3.2.2}/bindings/python/src/lib.rs +0 -0
  17. {iptocc-3.2.0 → iptocc-3.2.2}/bindings/python/tests/test_api.py +0 -0
  18. {iptocc-3.2.0 → iptocc-3.2.2}/bindings/python/uv.lock +0 -0
  19. {iptocc-3.2.0 → iptocc-3.2.2}/crate/LICENSE-APACHE +0 -0
  20. {iptocc-3.2.0 → iptocc-3.2.2}/crate/LICENSE-MIT +0 -0
  21. {iptocc-3.2.0 → iptocc-3.2.2}/crate/README.md +0 -0
  22. {iptocc-3.2.0 → iptocc-3.2.2}/crate/benches/lookup.rs +0 -0
  23. {iptocc-3.2.0 → iptocc-3.2.2}/crate/src/format.rs +0 -0
  24. {iptocc-3.2.0 → iptocc-3.2.2}/crate/src/lib.rs +0 -0
  25. {iptocc-3.2.0 → iptocc-3.2.2}/crate/src/main.rs +0 -0
  26. {iptocc-3.2.0 → iptocc-3.2.2}/crate/tests/api.rs +0 -0
  27. {iptocc-3.2.0 → iptocc-3.2.2}/pyproject.toml +0 -0
  28. {iptocc-3.2.0 → iptocc-3.2.2}/python/iptocc/__init__.py +0 -0
  29. {iptocc-3.2.0 → iptocc-3.2.2}/python/iptocc/cli.py +0 -0
  30. {iptocc-3.2.0 → iptocc-3.2.2}/python/iptocc/iptocc.pyi +0 -0
  31. {iptocc-3.2.0 → iptocc-3.2.2}/python/iptocc/py.typed +0 -0
@@ -350,7 +350,7 @@ dependencies = [
350
350
 
351
351
  [[package]]
352
352
  name = "iptocc"
353
- version = "1.3.0"
353
+ version = "1.3.2"
354
354
  dependencies = [
355
355
  "clap",
356
356
  "criterion",
@@ -359,7 +359,7 @@ dependencies = [
359
359
 
360
360
  [[package]]
361
361
  name = "iptocc-py"
362
- version = "3.2.0"
362
+ version = "3.2.2"
363
363
  dependencies = [
364
364
  "iptocc",
365
365
  "pyo3",
@@ -367,7 +367,7 @@ dependencies = [
367
367
 
368
368
  [[package]]
369
369
  name = "iptocc-wasm"
370
- version = "1.2.0"
370
+ version = "1.2.2"
371
371
  dependencies = [
372
372
  "iptocc",
373
373
  "js-sys",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iptocc
3
- Version: 3.2.0
3
+ Version: 3.2.2
4
4
  Classifier: Programming Language :: Python :: 3.10
5
5
  Classifier: Programming Language :: Python :: 3.11
6
6
  Classifier: Programming Language :: Python :: 3.12
@@ -1,7 +1,7 @@
1
1
  [package]
2
2
  name = "iptocc-py"
3
3
  description = "Python bindings for iptocc, a fast IP-to-country lookup library written in Rust"
4
- version = "3.2.0"
4
+ version = "3.2.2"
5
5
  edition.workspace = true
6
6
  license.workspace = true
7
7
  repository.workspace = true
@@ -1,7 +1,7 @@
1
1
  [package]
2
2
  name = "iptocc"
3
3
  description = "Fast, offline IPv4/IPv6 address to ISO-3166 country code lookup using RIR delegated statistics"
4
- version = "1.3.0"
4
+ version = "1.3.2"
5
5
  default-run = "iptocc"
6
6
  edition.workspace = true
7
7
  license.workspace = true
@@ -2,6 +2,7 @@ use std::collections::{BTreeMap, BTreeSet};
2
2
  use std::env;
3
3
  use std::fs;
4
4
  use std::net::{Ipv4Addr, Ipv6Addr};
5
+ use std::ops::{Add, Sub};
5
6
  use std::path::Path;
6
7
  use std::str::FromStr;
7
8
 
@@ -9,18 +10,70 @@ use iptocc::format::{FIRST_LEVEL_COUNT, V4_GAP_SENTINEL, V6_BUCKET_COUNT, V6_BUC
9
10
 
10
11
  const RIRS: &[&str] = &["afrinic", "apnic", "arin", "lacnic", "ripencc"];
11
12
 
13
+ trait Interval: Copy {
14
+ type Addr: Copy + Ord + Add<Output = Self::Addr> + Sub<Output = Self::Addr>;
15
+ const ONE: Self::Addr;
16
+ fn start(&self) -> Self::Addr;
17
+ fn end(&self) -> Self::Addr;
18
+ fn cc(&self) -> [u8; 2];
19
+ fn new(start: Self::Addr, end: Self::Addr, cc: [u8; 2]) -> Self;
20
+ fn set_end(&mut self, end: Self::Addr);
21
+ }
22
+
23
+ #[derive(Clone, Copy)]
12
24
  struct V4Interval {
13
25
  start: u32,
14
26
  end: u32,
15
27
  cc: [u8; 2],
16
28
  }
17
29
 
30
+ #[derive(Clone, Copy)]
18
31
  struct V6Interval {
19
32
  start: u128,
20
33
  end: u128,
21
34
  cc: [u8; 2],
22
35
  }
23
36
 
37
+ impl Interval for V4Interval {
38
+ type Addr = u32;
39
+ const ONE: u32 = 1;
40
+ fn start(&self) -> u32 {
41
+ self.start
42
+ }
43
+ fn end(&self) -> u32 {
44
+ self.end
45
+ }
46
+ fn cc(&self) -> [u8; 2] {
47
+ self.cc
48
+ }
49
+ fn new(start: u32, end: u32, cc: [u8; 2]) -> Self {
50
+ V4Interval { start, end, cc }
51
+ }
52
+ fn set_end(&mut self, end: u32) {
53
+ self.end = end;
54
+ }
55
+ }
56
+
57
+ impl Interval for V6Interval {
58
+ type Addr = u128;
59
+ const ONE: u128 = 1;
60
+ fn start(&self) -> u128 {
61
+ self.start
62
+ }
63
+ fn end(&self) -> u128 {
64
+ self.end
65
+ }
66
+ fn cc(&self) -> [u8; 2] {
67
+ self.cc
68
+ }
69
+ fn new(start: u128, end: u128, cc: [u8; 2]) -> Self {
70
+ V6Interval { start, end, cc }
71
+ }
72
+ fn set_end(&mut self, end: u128) {
73
+ self.end = end;
74
+ }
75
+ }
76
+
24
77
  fn main() {
25
78
  let manifest_dir = env!("CARGO_MANIFEST_DIR");
26
79
  let workspace_root = Path::new(manifest_dir).parent().expect("workspace root");
@@ -28,13 +81,21 @@ fn main() {
28
81
  let out_dir = Path::new(manifest_dir).join("src/data");
29
82
  fs::create_dir_all(&out_dir).expect("creating src/data");
30
83
 
31
- let (mut v4, mut v6) = parse_rir(&data_dir);
84
+ let (v4, v6) = parse_rir(&data_dir);
85
+ let mut v4 = resolve_overlaps(v4);
86
+ let mut v6 = resolve_overlaps(v6);
32
87
 
33
88
  v4.sort_unstable_by_key(|t| t.start);
34
89
  v6.sort_unstable_by_key(|t| t.start);
35
90
 
36
- assert!(v4.windows(2).all(|w| w[0].end < w[1].start), "v4 intervals overlap");
37
- assert!(v6.windows(2).all(|w| w[0].end < w[1].start), "v6 intervals overlap");
91
+ assert!(
92
+ v4.windows(2).all(|w| w[0].end < w[1].start),
93
+ "v4 intervals still overlap after resolution"
94
+ );
95
+ assert!(
96
+ v6.windows(2).all(|w| w[0].end < w[1].start),
97
+ "v6 intervals still overlap after resolution"
98
+ );
38
99
 
39
100
  for entry in v4.iter().map(|e| e.cc).chain(v6.iter().map(|e| e.cc)) {
40
101
  assert!(
@@ -138,6 +199,32 @@ fn parse_rir(data_dir: &Path) -> (Vec<V4Interval>, Vec<V6Interval>) {
138
199
  (v4, v6)
139
200
  }
140
201
 
202
+ fn resolve_overlaps<I: Interval>(mut intervals: Vec<I>) -> Vec<I> {
203
+ intervals.sort_by_key(|t| t.start());
204
+ let mut out: Vec<I> = Vec::with_capacity(intervals.len());
205
+ for entry in intervals {
206
+ let mut tail: Option<I> = None;
207
+ while let Some(&last) = out.last() {
208
+ if last.end() < entry.start() {
209
+ break;
210
+ }
211
+ if last.end() > entry.end() && tail.is_none() {
212
+ tail = Some(I::new(entry.end() + I::ONE, last.end(), last.cc()));
213
+ }
214
+ if last.start() < entry.start() {
215
+ out.last_mut().unwrap().set_end(entry.start() - I::ONE);
216
+ break;
217
+ }
218
+ out.pop();
219
+ }
220
+ out.push(entry);
221
+ if let Some(t) = tail {
222
+ out.push(t);
223
+ }
224
+ }
225
+ out
226
+ }
227
+
141
228
  fn transform_v4(intervals: &[V4Interval]) -> Vec<u8> {
142
229
  let mut merged: Vec<V4Interval> = Vec::with_capacity(intervals.len());
143
230
  for entry in intervals {