run-rs 0.6.7

Run a subset of Rust as an interpreted script
run-rs-0.6.7 is not a library.

RustScript

Crates.io CI Marketplace Licence

Linux macOS Windows

Write your helper scripts in Rust and run them like shell scripts, no compile step. RustScript interprets a practical subset of the language, so a script starts instantly. rust check validates the same file with the real rustc.

docs/interpreter.md explains how it works inside.

Install

cargo install run-rs

This installs a binary named rust.

First script

#!/usr/bin/env rust

use std::fs;

fn main() -> anyhow::Result<()> {
    let text = fs::read_to_string("notes.txt")?;
    println!("{} lines", text.lines().count());
    Ok(())
}

Make it executable and run it:

chmod +x notes.rs
./notes.rs

Usage

rust FILE.rs         interpret the script
rust -e 'CODE'       run a snippet, arguments after CODE go to it
rust check FILE.rs   validate without running
rust build FILE.rs   compile, cache, and run a native binary
rust supported       list every bridged method per receiver
rust clean           clear cached checks and builds
rust update [VER]    install a release, the newest one by default
rust --version       show version and build information

Arguments after the file go to the script.

A script run directly cannot use rust build, so the word cmp as the first argument does the same thing. ./tool.rs cmp one two compiles the script and runs the binary with one two. Because of this a script must not treat its own first argument as cmp, that word is reserved.

What works

Functions, closures, structs, enums, patterns, loops, iterators, Vec, strings, maps, sets, Option, Result, ?, formatting, modules, local path crates, and async with #[tokio::main], spawned tasks, timers, and HTTP. Traits with default methods, user Display, Debug, Drop, operator, and Iterator impls, associated consts, u128 and i128, mem::swap and its siblings, and real sharing through Rc, Arc, RefCell, Cell, and Mutex. Values copy on write, so clones and Copy assignments mutate independently, exactly like compiled Rust.

The standard library bridge covers files, paths, stdin and stdout, processes, TCP sockets, environment, time, and collections. Bridged crates include anyhow, serde, serde_json, reqwest, regex, tokio, chrono, rand, and more. Windows builds also bridge winreg, windows-service, and wmi.

The full generated list of bridged methods is in docs/supported.md. Every feature has a working example under crates/examples/examples.

Limitations

  • Crates without a bridge stop with an unsupported crate error.
  • std::thread is not supported, use tokio tasks.
  • static mut is rejected. Plain statics behave like constants.
  • Lifetimes are accepted but mean nothing at runtime. Generic bounds dispatch by the value's runtime type.
  • Glob imports from script modules are not supported.
  • HashMap iterates in insertion order. Real Rust's order is arbitrary and unpromised, so a correct script cannot observe the difference, but an interpreted run is deterministic where a compiled one is not.

GitHub Actions

The repository is also a GitHub Action:

- uses: VladasZ/rustscript@v0.6
  with:
    script: tools/release.rs

It downloads a prebuilt binary. Linux, macOS, and Windows on x86_64 and arm64 supported. See docs/github-actions.md.

Benchmarks

RustScript is compared with native Rust, Node, and Python on equivalent programs. See all benchmark charts for every case, the benchmark guide for methodology, and the profiling guide for finding interpreter hot spots.

regex benchmark

json parse benchmark

Licence

Dual licensed under either MIT or Apache-2.0, at your option.