5 个版本

0.2.0 2024年2月12日
0.1.3 2024年2月9日
0.1.2 2024年2月7日
0.1.1 2024年2月7日
0.1.0 2024年2月7日

2344Rust 模式

每月 31 次下载

Apache-2.0 许可

10KB
51

runtime-contracts: 为 Rust 提供结构化、易于理解的运行时合约。

有关背景、上下文和使用示例,请参阅 crate 文档

错误

如果您发现任何问题,请提交问题。欢迎提出建议!

路线图

  • 可通过简单实用函数表达的结构化合约。
  • 将合约作为函数/闭包。
    • 这会像 type RuntimeContractFunction<T> = dyn Fn(T) -> Result<T> 那样简单,还是我们需要更多?
  • 合约组合(假设我们至少想要单调组合)。
    • 如果合约是函数,我们能否只使用函数组合?
    • 我们需要或想要一个 RuntimeContract 结构来封装合约的特定信息,并提供 ResultOption 这样的组合子吗?

lib.rs:

结构化、易于理解的运行时合约。

虽然许多语言都有合约库,但许多都选择仅在调试和测试构建中编译它们。这种选择的背后似乎是因为他们不希望在生产环境中承担性能损失。一个值得注意的例外是 Racket 的合约模块,它本身就是一个 杰作。在这个库中,我们为了运行时安全和程序正确性而放弃了这种担忧。

这个 crate 希望让构建软件的从业者更容易使用和理解基于合约的编程。其哲学直接受到著名计算机科学家、Dr. Betrand Meyer 在 1986 年设计 Eiffel 编程语言 时所表达的 设计-by-Contract (DbC) 概念的启发。

此外,还要感谢实现合约作为过程宏的 contracts crate。绝对推荐您去看看!

示例

尽管这个示例使用了crate自己的错误类型,但只要它能工作,您可以用任何您想要的类型替换。

use runtime_contracts::{check, ensures, requires, error::RuntimeContractError, Result};


fn refund_loyalty_points(account_id: &str, point_amount: usize) -> Result<usize> {
  requires(|| account_id.len() == 32, "malformed account ID")?;
  requires(|| point_amount % 2 == 0, "attempting to refund an odd number of points")?;

  let account = load_account(account_id);
  let starting_balance = account.balance;
  let closing_balance = account.add_to_balance(point_amount)?;

  ensures(closing_balance, |balance| balance - point_amount == starting_balance, "points were not added to account")
}

依赖项

~295–750KB
~18K SLoC