run-rs 0.6.25

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

RustScript

Crates.io CI Marketplace Licence

Linux macOS Windows

Write helper scripts in rust and run them like shell scripts, with 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.

How it works inside: docs/interpreter.md

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.

rust check and rust build need cargo. Interpreting does not. Set RUSTSCRIPT_SKIP_CHECK=1 to skip the cargo check gate, for example on a machine without a Rust toolchain.

./tool.rs cmp one two does what rust build does and runs the binary with one two. So cmp is reserved as a script's first argument.

What works

Functions, closures, structs, enums, patterns, loops with labels, iterators, Vec, VecDeque, strings, maps, sets, Option, Result, ?, formatting, modules and local path crates. 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. Real sharing through Rc, Arc, RefCell, Cell and Mutex, and a conflicting RefCell borrow panics like it does in compiled Rust. Values move and copy exactly like compiled Rust.

The std bridge covers files, paths, stdio, processes, TCP, env, 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: docs/supported.md

Every feature has a working example under crates/examples/examples.

Limitations

  • Crates without a bridge fail rust check. A function of a bridged crate or of std that the interpreter lacks stops the script before it runs.
  • std::thread is not supported, use tokio tasks.
  • static mut is rejected. Plain statics behave like constants.
  • Lifetimes and generic bounds mean nothing at runtime.
  • Glob imports from script modules are not supported.
  • HashMap and HeaderMap iterate in insertion order. Real Rust promises no order, so a correct script cannot see the difference.
  • file!() gives the script path as it was passed to rust, where a compiled build stamps the path rustc was given.

GitHub Actions

The repository is also a GitHub Action:

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

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

Benchmarks

RustScript is compared with native rust, node and python on the same programs. Charts: bench/RESULTS.md, method: bench/README.md, profiling: docs/profiling.md

regex benchmark

json parse benchmark

Licence

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