Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 0 additions & 157 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 11 additions & 16 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,9 @@ edition = "2024"
authors = ["Keshav Priyadarshi <git@keshav.space>", "AboutCode <info@aboutcode.org>"]
description = "PackageURL validator using prebuilt FST"
license = "Apache-2.0"
repository = "https://github.com/aboutcode-org/purl-validator"
repository = "https://github.com/aboutcode-org/purl-validator-rust"

[lib]
name = "purl_validator"
crate-type = ["cdylib", "rlib"]

[dependencies]
fst = "0.4.7"
once_cell = "1.21"
pyo3 = { version = "0.27.1", features = ["extension-module"] }

[[bin]]
name = "fst_builder"
path = "fst_builder/main.rs"
exclude = ["fst_builder/*"]

include = [
"src/**",
Expand All @@ -28,8 +17,14 @@ include = [
"LICENSE"
]

[package.metadata.maturin]
[lib]
name = "purl_validator"
crate-type = ["rlib"]

[tool.maturin]
include = ["purls.fst"]
[dependencies]
fst = "0.4.7"
once_cell = "1.21"

[[bin]]
name = "fst_builder"
path = "fst_builder/main.rs"
4 changes: 1 addition & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
build-fst:
cargo run --bin fst_builder

build-python:
maturin build --release

clean:
cargo clean
rm -f purls.fst
rm -rf target

.PHONY: build-fst build-python clean
.PHONY: build-fst clean
77 changes: 76 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,76 @@
# purl-validator
# purl-validator

[![License](https://img.shields.io/badge/License-Apache--2.0-blue.svg?style=for-the-badge)](https://opensource.org/licenses/Apache-2.0)
[![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)
[![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)

**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?**

## How It Works?

**purl-validator** is shipped with a pre-built FST (Finite State Transducer), a set of compact automata containing latest Package URLs mined by the MineCode[^1]. Library uses this FST to perform lookups and confirm whether the **base PURL**[^2] exists.

## Currently Supported Ecosystems

- **nuget**: [https://www.nuget.org/](https://www.nuget.org/)

## Usage

Add `purl-validator` to your Rust dependency

```bash
cargo add purl-validator
```

Use it in your code like this

```rust
use purl_validator::validate;

let result: bool = validate("pkg:nuget/FluentValidation");
```

## Contribution

We welcome contributions from the community! If you find a bug or have an idea for a new feature, please open an issue on the GitHub repository. If you want to contribute code, you can fork the repository, make your changes, and submit a pull request.

* Please try to write a good commit message, see [good commit message wiki](https://aboutcode.readthedocs.io/en/latest/contributing/writing_good_commit_messages.html).
* Add DCO `Sign Off` to your commits.

## Development Setup

Run these commands, starting from a git clone of [https://github.com/aboutcode-org/purl-validator-rust.git](https://github.com/aboutcode-org/purl-validator-rust.git)

Generate FST:

```bash
make build-fst
```

Run tests:

```bash
make test
```

## License

SPDX-License-Identifier: Apache-2.0

purl-validator is licensed under Apache License version 2.0.

```text
You may not use this software except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```

[^1]: MineCode continuously collects package metadata from various package ecosystems to maintain an up-to-date catalog of known packages.
[^2]: A Base Package URL is a Package URL without a version or subpath.
18 changes: 0 additions & 18 deletions pyproject.toml

This file was deleted.

24 changes: 5 additions & 19 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,12 @@
use fst::Set;
use once_cell::sync::Lazy;


static FST_BYTES: &[u8] = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/purls.fst"));

static VALIDATOR: Lazy<Set<&[u8]>> = Lazy::new(|| {
Set::new(FST_BYTES).expect("Failed to load FST from embedded bytes")
});


pub fn validate(word: &str) -> bool {
VALIDATOR.contains(word)
}


#[pyo3::pymodule]
mod purl_validator {
use pyo3::prelude::*;
use crate::validate;
static VALIDATOR: Lazy<Set<&[u8]>> =
Lazy::new(|| Set::new(FST_BYTES).expect("Failed to load FST from embedded bytes"));

#[pyfunction(name = "validate")]
fn py_validate(word: &str) -> PyResult<bool> {
Ok(validate(word))
}
pub fn validate(packageurl: &str) -> bool {
let trimmed_packageurl = packageurl.trim_end_matches("/");
VALIDATOR.contains(trimmed_packageurl)
}