@@ -24,35 +24,55 @@ See https://aboutcode.org for more information about nexB OSS projects.
2424//! ```
2525//! use purl_validator::validate;
2626//!
27- //! let result: bool = validate("pkg:nuget/FluentValidation");
27+ //! let result: bool = validate("pkg:nuget/FluentValidation")
28+ //! .expect("only fails if PURL is invalid or contains version, qualifier, or subpath");
2829//! ```
2930//!
3031
3132use fst:: Set ;
32-
3333use once_cell:: sync:: Lazy ;
34+ use packageurl:: PackageUrl ;
3435use std:: env;
36+ use std:: str:: FromStr ;
3537
3638static FST_DATA : & [ u8 ] = include_bytes ! ( concat!( env!( "OUT_DIR" ) , "/purls.fst" ) ) ;
3739
3840static VALIDATOR : Lazy < Set < & ' static [ u8 ] > > =
3941 Lazy :: new ( || Set :: new ( FST_DATA ) . expect ( "Failed to load FST from embedded bytes" ) ) ;
4042
41- fn strip_and_check_purl ( packageurl : & str , fst_map : & Set < & [ u8 ] > ) -> bool {
43+ fn strip_and_check_purl ( packageurl : & str , fst_map : & Set < & [ u8 ] > ) -> Result < bool , ValidateError > {
44+ let purl = PackageUrl :: from_str ( packageurl) . map_err ( ValidateError :: InvalidPurl ) ?;
45+ if purl. version ( ) . is_some ( ) || !purl. qualifiers ( ) . is_empty ( ) || purl. subpath ( ) . is_some ( ) {
46+ return Err ( ValidateError :: UnsupportedPurl (
47+ "only base PURL is supported (no version, qualifiers, or subpath)" ,
48+ ) ) ;
49+ }
50+
4251 let trimmed_packageurl = packageurl. trim_end_matches ( "/" ) ;
43- fst_map. contains ( trimmed_packageurl)
52+ Ok ( fst_map. contains ( trimmed_packageurl) )
4453}
4554
4655/// Validate a Package URL (PURL)
4756///
48- /// Returns `true` if the given base PURL represents an existing package,
49- /// otherwise returns `false`.
57+ /// Return `Ok(true)` if given **base PURL** represents an existing package,
58+ /// `Ok(false)` if it does not, or `Err` if the PURL is invalid or contains
59+ /// unsupported fields (version, qualifiers, or subpath).
60+ ///
61+ /// A **base PURL** is a PURL without a version, qualifiers, or subpath.
62+ /// PURLs containing a version, qualifiers, or subpath are **not supported**
63+ /// and will cause the validator to return an error.
5064///
5165/// Use pre-built FST (Finite State Transducer) to perform lookups and confirm whether
5266/// the **base PURL** exists.
53- pub fn validate ( packageurl : & str ) -> bool {
67+ pub fn validate ( packageurl : & str ) -> Result < bool , ValidateError > {
5468 strip_and_check_purl ( packageurl, & VALIDATOR )
5569}
5670
71+ #[ derive( Debug ) ]
72+ pub enum ValidateError {
73+ InvalidPurl ( packageurl:: Error ) ,
74+ UnsupportedPurl ( & ' static str ) ,
75+ }
76+
5777#[ cfg( test) ]
5878mod validate_tests;
0 commit comments