Skip to content

Commit 1d3df4f

Browse files
authored
Merge pull request #2 from aboutcode-org/mmap
Load FST using memory-mapped file
2 parents a3b6aba + 1fa9f41 commit 1d3df4f

File tree

8 files changed

+116
-6
lines changed

8 files changed

+116
-6
lines changed

.github/workflows/ci.yml

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
name: Rust CI
2+
3+
on:
4+
workflow_dispatch:
5+
pull_request:
6+
push:
7+
branches:
8+
- main
9+
10+
jobs:
11+
build-test:
12+
name: Run test and build
13+
strategy:
14+
fail-fast: false
15+
matrix:
16+
include:
17+
- os: ubuntu-latest
18+
target: x86_64-unknown-linux-gnu
19+
20+
- os: ubuntu-24.04-arm
21+
target: aarch64-unknown-linux-gnu
22+
23+
- os: macos-14
24+
target: aarch64-apple-darwin
25+
26+
- os: macos-15
27+
target: aarch64-apple-darwin
28+
29+
- os: macos-15-intel
30+
target: x86_64-apple-darwin
31+
32+
- os: windows-latest
33+
target: x86_64-pc-windows-msvc
34+
35+
runs-on: ${{ matrix.os }}
36+
37+
steps:
38+
- name: Checkout source
39+
uses: actions/checkout@v4
40+
41+
- name: Install Rust
42+
uses: dtolnay/rust-toolchain@stable
43+
with:
44+
components: rustfmt, clippy
45+
46+
- name: Check fmt and linting
47+
run: make check
48+
49+
- name: Run tests
50+
run: cargo test --target ${{ matrix.target }} --verbose
51+
52+
- name: Build
53+
run: cargo build --target ${{ matrix.target }} --verbose

Cargo.lock

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ crate-type = ["rlib"]
2323

2424
[dependencies]
2525
fst = "0.4.7"
26+
memmap2 = "0.9.9"
2627
once_cell = "1.21"
2728

2829
[[bin]]

Makefile

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
11
build-fst:
22
cargo run --bin fst_builder
33

4-
54
clean:
65
cargo clean
76
rm -f purls.fst
87
rm -rf target
98

10-
.PHONY: build-fst clean
9+
test:
10+
cargo test
11+
12+
valid:
13+
cargo fmt --all
14+
cargo clippy --all-targets --all-features
15+
16+
check:
17+
cargo fmt --all -- --check
18+
cargo clippy --all-targets --all-features -- -D warnings
19+
20+
.PHONY: build-fst clean test valid check

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
[![License](https://img.shields.io/badge/License-Apache--2.0-blue.svg?style=for-the-badge)](https://opensource.org/licenses/Apache-2.0)
44
[![Version](https://img.shields.io/github/v/release/aboutcode-org/purl-validator-rust?style=for-the-badge)](https://github.com/aboutcode-org/purl-validator-rust/releases)
5-
[![Test](https://img.shields.io/github/actions/workflow/status/aboutcode-org/purl-validator-rust/run-test.yml?style=for-the-badge&logo=github)](https://github.com/aboutcode-org/purl-validator-rust/actions)
5+
[![Test](https://img.shields.io/github/actions/workflow/status/aboutcode-org/purl-validator-rust/ci.yml?style=for-the-badge&logo=github)](https://github.com/aboutcode-org/purl-validator-rust/actions)
66

77
**purl-validator** is a Rust library for validating [Package URLs (PURLs)](https://github.com/package-url/purl-spec). It works fully offline, including in **air-gapped** or **restricted environments**, and answers one key question: **Does the package this PURL represents actually exist?**
88

@@ -53,6 +53,12 @@ Run tests:
5353
make test
5454
```
5555

56+
Fix formatting and linting:
57+
58+
```bash
59+
make valid
60+
```
61+
5662
## License
5763

5864
SPDX-License-Identifier: Apache-2.0

src/lib.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,25 @@
11
use fst::Set;
2+
use memmap2::Mmap;
23
use once_cell::sync::Lazy;
4+
use std::env;
5+
use std::fs::File;
6+
use std::path::Path;
37

4-
static FST_BYTES: &[u8] = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/purls.fst"));
8+
static VALIDATOR: Lazy<Set<Mmap>> = Lazy::new(|| {
9+
let path = Path::new(env!("CARGO_MANIFEST_DIR")).join("purls.fst");
10+
load_fst(&path)
11+
});
512

6-
static VALIDATOR: Lazy<Set<&[u8]>> =
7-
Lazy::new(|| Set::new(FST_BYTES).expect("Failed to load FST from embedded bytes"));
13+
fn load_fst(path: &Path) -> Set<Mmap> {
14+
let file = File::open(path).expect("Failed to open FST file");
15+
let mmap = unsafe { Mmap::map(&file).expect("Failed to mmap FST file") };
16+
Set::new(mmap).expect("Failed to load FST from mmap")
17+
}
818

919
pub fn validate(packageurl: &str) -> bool {
1020
let trimmed_packageurl = packageurl.trim_end_matches("/");
1121
VALIDATOR.contains(trimmed_packageurl)
1222
}
23+
24+
#[cfg(test)]
25+
mod validate_tests;

src/validate_tests.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
use super::*;
2+
use std::path::Path;
3+
4+
#[test]
5+
fn test_validate_with_custom_file() {
6+
let test_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/data/test_purls.fst");
7+
let validator = load_fst(&test_path);
8+
9+
assert!(validator.contains("pkg:nuget/FluentUtils.EnumExtensions"));
10+
assert!(!validator.contains("pkg:example/nonexistent"));
11+
}

tests/data/test_purls.fst

103 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)