Rust SPDX许可证解析库spdx-rs的使用,支持SPDX许可证表达式解析与验证

Rust SPDX许可证解析库spdx-rs的使用,支持SPDX许可证表达式解析与验证

SPDX Documents in Rust

spdx-rs 是一个用于解析SPDX文档到Rust结构体的库,支持多种数据格式。

数据格式

该库主要设计用于处理JSON格式的SPDX文档。这是通过Serde实现的,因此任何Serde支持的数据格式都可以工作,只要命名与JSON SPDX文档中使用的命名一致。

除了使用Serde进行序列化和反序列化外,还支持使用自定义解析器反序列化tag-value格式的文档。

使用

以下是使用spdx-rs库解析和验证SPDX许可证表达式的完整示例:

use spdx_rs::models::LicenseExpression;
use spdx_rs::validation::validate_license_expression;

fn main() {
    // 示例SPDX许可证表达式
    let expr_str = "MIT OR (Apache-2.0 AND BSD-3-Clause)";
    
    // 解析许可证表达式
    let expr = LicenseExpression::parse(expr_str).unwrap();
    println!("Parsed expression: {:?}", expr);
    
    // 验证许可证表达式
    match validate_license_expression(&expr) {
        Ok(_) => println!("License expression is valid"),
        Err(e) => println!("Validation error: {}", e),
    }
    
    // 另一个更复杂的例子
    let complex_expr = "GPL-2.0-only WITH Classpath-exception-2.0 AND MIT";
    match LicenseExpression::parse(complex_expr) {
        Ok(expr) => {
            println!("Successfully parsed complex expression");
            if let Err(e) = validate_license_expression(&expr) {
                println!("Warning: {}", e);
            }
        }
        Err(e) => println!("Parse error: {}", e),
    }
}

项目信息

  • 版本: 0.5.5
  • 许可证: MIT
  • 大小: 29.1 KiB
  • 依赖: 2018 edition
  • 最后更新: 约2年前
  • 分类: 数据结构

完整示例代码

use spdx_rs::models::LicenseExpression;
use spdx_rs::validation::validate_license_expression;

fn main() {
    // 示例1: 简单许可证表达式解析与验证
    let simple_expr = "MIT OR Apache-2.0";
    match LicenseExpression::parse(simple_expr) {
        Ok(expr) => {
            println!("成功解析简单表达式: {:?}", expr);
            if let Err(e) = validate_license_expression(&expr) {
                println!("验证错误: {}", e);
            } else {
                println!("表达式验证通过");
            }
        }
        Err(e) => println!("解析错误: {}", e),
    }

    // 示例2: 带括号的复杂表达式
    let nested_expr = "(MIT AND BSD-2-Clause) OR GPL-3.0-only";
    if let Ok(expr) = LicenseExpression::parse(nested_expr) {
        println!("解析带括号的复杂表达式成功");
        match validate_license_expression(&expr) {
            Ok(_) => println!("复杂表达式验证通过"),
            Err(e) => println!("复杂表达式验证失败: {}", e),
        }
    }

    // 示例3: 带异常条款的表达式
    let with_exception = "LGPL-2.1-only WITH Classpath-exception-2.0";
    if let Ok(expr) = LicenseExpression::parse(with_exception) {
        println!("成功解析带异常条款的表达式");
        if validate_license_expression(&expr).is_ok() {
            println!("带异常条款的表达式验证通过");
        }
    }
}

安装

在项目目录中运行以下Cargo命令:

cargo add spdx-rs

或者在Cargo.toml中添加:

spdx-rs = "0.5.5"

所有者

  • Mikko Murto (mmurto)

1 回复

Rust SPDX许可证解析库spdx-rs使用指南

概述

spdx-rs是一个用于解析和验证SPDX许可证标识符和表达式的Rust库。它支持SPDX许可证列表中的所有标准许可证标识符,并能解析复杂的SPDX许可证表达式。

主要功能

  • 解析和验证SPDX许可证标识符
  • 解析和验证SPDX许可证表达式
  • 支持SPDX 3.0规范
  • 提供详细的错误信息

安装

在Cargo.toml中添加依赖:

[dependencies]
spdx = "0.8.0"

基本使用方法

验证单个许可证标识符

use spdx::LicenseId;

fn main() {
    match LicenseId::parse("MIT") {
        Ok(license) => println!("有效的SPDX许可证: {:?}", license),
        Err(e) => println!("无效的许可证标识符: {}", e),
    }
}

解析许可证表达式

use spdx::Expression;

fn main() {
    let expr = "MIT OR Apache-2.0";
    match Expression::parse(expr) {
        Ok(parsed) => println!("解析成功: {}", parsed),
        Err(e) => println!("解析失败: {}", e),
    }
}

检查表达式有效性

use spdx::Expression;

fn main() {
    let expr = "(MIT AND Apache-2.0) OR GPL-3.0-only WITH Classpath-exception-2.0";
    match Expression::parse(expr) {
        Ok(parsed) => {
            println!("表达式有效: {}", parsed);
            println!("包含的许可证:");
            for req in parsed.requirements() {
                println!("- {}", req.license.id());
            }
        }
        Err(e) => println!("无效表达式: {}", e),
    }
}

高级用法

自定义许可证解析

use spdx::{Expression, ParseOptions};

fn main() {
    let options = ParseOptions {
        allow_lower_case: true,  // 允许小写许可证标识符
        ..Default::default()
    };
    
    let expr = "mit or apache-2.0";
    match Expression::parse_with_options(expr, &options) {
        Ok(parsed) => println!("解析成功: {}", parsed),
        Err(e) => println!("解析失败: {}", e),
    }
}

检查许可证是否满足特定条件

use spdx::{LicenseId, LicenseExceptionId};

fn main() {
    let license = LicenseId::parse("GPL-3.0-only").unwrap();
    let exception = LicenseExceptionId::parse("Classpath-exception-2.0").unwrap();
    
    println!("GPL-3.0-only是自由软件许可证: {}", license.is_fsf_libre());
    println!("Classpath-exception-2.0是FSF批准的例外: {}", exception.is_fsf_exception());
}

实际应用示例

在项目中使用许可证检查

use spdx::Expression;

struct Project {
    name: String,
    license: String,
}

fn check_project_license(project: &Project) {
    match Expression::parse(&project.license) {
        Ok(expr) => {
            println!("项目 {} 使用有效的SPDX许可证表达式", project.name);
            if expr.evaluate(|req| {
                req.license.id().is_fsf_libre()
            }) {
                println!("  -> 符合自由软件定义");
            }
        }
        Err(e) => println!("项目 {} 的许可证无效: {}", project.name, e),
    }
}

fn main() {
    let projects = vec![
        Project {
            name: "MyApp".to_string(),
            license: "MIT OR Apache-2.0".to_string(),
        },
        Project {
            name: "OtherLib".to_string(),
            license: "Invalid-License".to_string(),
        },
    ];
    
    for project in projects {
        check_project_license(&project);
    }
}

错误处理

spdx-rs提供了详细的错误信息,帮助调试许可证表达式问题:

use spdx::Expression;

fn main() {
    let expr = "MIT AND (Apache-2.0 OR )";
    if let Err(e) = Expression::parse(expr) {
        println!("错误位置: {}", e.span);
        println!("错误原因: {}", e.reason);
        if let Some(help) = e.help {
            println!("建议: {}", help);
        }
    }
}

完整示例

下面是一个完整的示例,展示了如何使用spdx-rs库进行许可证验证和表达式解析:

use spdx::{LicenseId, LicenseExceptionId, Expression, ParseOptions};

fn main() {
    // 示例1: 验证单个许可证标识符
    println!("--- 验证单个许可证标识符 ---");
    let licenses_to_check = ["MIT", "Apache-2.0", "Invalid-License"];
    for license_str in licenses_to_check {
        match LicenseId::parse(license_str) {
            Ok(license) => println!("'{}' 是有效的SPDX许可证", license_str),
            Err(e) => println!("'{}' 无效: {}", license_str, e),
        }
    }

    // 示例2: 解析复杂许可证表达式
    println!("\n--- 解析复杂许可证表达式 ---");
    let complex_expr = "(MIT AND Apache-2.0) OR (GPL-3.0-only WITH Classpath-exception-2.0)";
    match Expression::parse(complex_expr) {
        Ok(expr) => {
            println!("表达式解析成功:");
            println!("规范化形式: {}", expr);
            println!("包含的许可证:");
            for req in expr.requirements() {
                println!("- {}", req.license.id());
                if let Some(exception) = req.exception {
                    println!("  带有例外: {}", exception);
                }
            }
        }
        Err(e) => println!("解析失败: {}", e),
    }

    // 示例3: 自定义解析选项
    println!("\n--- 自定义解析选项 ---");
    let options = ParseOptions {
        allow_lower_case: true,
        ..Default::default()
    };
    let lower_case_expr = "mit or apache-2.0";
    match Expression::parse_with_options(lower_case_expr, &options) {
        Ok(expr) => println!("成功解析小写表达式: {}", expr),
        Err(e) => println!("解析失败: {}", e),
    }

    // 示例4: 检查许可证属性
    println!("\n--- 检查许可证属性 ---");
    let gpl_license = LicenseId::parse("GPL-3.0-only").unwrap();
    let exception = LicenseExceptionId::parse("Classpath-exception-2.0").unwrap();
    println!("{} 是OSI批准的: {}", gpl_license, gpl_license.is_osi_approved());
    println!("{} 是自由软件许可证: {}", gpl_license, gpl_license.is_fsf_libre());
    println!("{} 是FSF批准的例外: {}", exception, exception.is_fsf_exception());

    // 示例5: 错误处理
    println!("\n--- 错误处理示例 ---");
    let invalid_expr = "MIT AND (Apache-2.0 OR )";
    if let Err(e) = Expression::parse(invalid_expr) {
        println!("发现错误:");
        println!("位置: {}", e.span);
        println!("原因: {}", e.reason);
        if let Some(help) = e.help {
            println!("建议: {}", help);
        }
    }
}

总结

spdx-rs库为Rust项目提供了强大的SPDX许可证解析和验证能力,非常适合需要处理软件许可证的工具和应用程序。通过简单的API,开发者可以轻松集成SPDX标准到自己的项目中。

回到顶部