{"id":13500483,"url":"https://github.com/rustviz/rustviz","last_synced_at":"2025-05-14T10:11:32.087Z","repository":{"id":41238894,"uuid":"301535510","full_name":"rustviz/rustviz","owner":"rustviz","description":"Interactively Visualizing Ownership and Borrowing for Rust","archived":false,"fork":false,"pushed_at":"2024-02-13T06:01:59.000Z","size":44661,"stargazers_count":2753,"open_issues_count":25,"forks_count":76,"subscribers_count":26,"default_branch":"master","last_synced_at":"2025-04-07T02:01:39.212Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rustviz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-10-05T20:46:19.000Z","updated_at":"2025-04-03T20:21:00.000Z","dependencies_parsed_at":"2024-05-05T03:43:12.645Z","dependency_job_id":null,"html_url":"https://github.com/rustviz/rustviz","commit_stats":{"total_commits":131,"total_committers":13,"mean_commits":"10.076923076923077","dds":0.7862595419847328,"last_synced_commit":"5b2a8b2303e3b1e6e295c764f804565d75eadcfd"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustviz%2Frustviz","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustviz%2Frustviz/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustviz%2Frustviz/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustviz%2Frustviz/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rustviz","download_url":"https://codeload.github.com/rustviz/rustviz/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248824654,"owners_count":21167344,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T22:01:02.946Z","updated_at":"2025-04-14T05:53:28.706Z","avatar_url":"https://github.com/rustviz.png","language":"HTML","funding_links":[],"categories":["HTML","Resources","资源 Resources","Programming","Programming Languages","Rust"],"sub_categories":["Web programming","网络编程 Web programming","Rust 🦀"],"readme":"# RustViz\n[![Build Status](https://travis-ci.org/joemccann/dillinger.svg?branch=master)](https://travis-ci.org/joemccann/dillinger)\n\n*RustViz* is a tool that generates interactive visualizations from simple Rust programs to assist users in better understanding the Rust [Lifetime and Borrowing](https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html) mechanism.\n\nRustViz is a project of the [Future of Programming Lab](http://fplab.mplse.org/) at the University of Michigan.\n\n## What does it look like?\n\n*RustViz* generates [SVG](https://developer.mozilla.org/en-US/docs/Web/SVG) files with graphical indicators that integrate with [mdbook](https://github.com/rust-lang/mdBook) to render interactive visualizations of ownership and borrowing related events in a Rust program. Here's a sample view of what a visualization can look like:\n\n![alt tag](https://github.com/rustviz/rustviz/blob/master/src/svg_generator/example.png)\n\nYou can read more about it in [our VL/HCC 2022 paper](https://web.eecs.umich.edu/~comar/rustviz-vlhcc22.pdf). Note that the section on generating visualizations is out of date, see below.\n\n## Usage\n*RustViz* is capable of generating visualizations for simple Rust programs (albeit with certain limitations) that have been annotated by the user. We are not currently attempting to generate visualizations automatically. In this section, we'll showcase how to generate SVG renderings of examples provided by us.\n\n*RustViz* requires [Rust](https://www.rust-lang.org/), [Cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html) and [mdbook](https://github.com/rust-lang/mdBook) to be installed. Once you have installed all the above prerequisites, direct into [/rustviz_mdbook](rustviz_mdbook) and run the script:\n```shell\n~/rustviz/rustviz_mdbook$ ./view_examples.sh\n```\nYou may have an output similar to this:\n```shell\nGenerating visualizations for the following examples:\nbuilding copy...\nbuilding hatra1...\nbuilding hatra2...\nbuilding func_take_ownership...\nbuilding func_take_return_ownership...\n2021-01-19 12:36:13 [INFO] (mdbook::book): Book building has started\n2021-01-19 12:36:13 [INFO] (mdbook::book): Running the html backend\nServing HTTP on :: port 8000 (http://[::]:8000/) ...\n```\nIf you observed this output, then you have successfully generated the Rust visualization examples! Now open your browser and navigate to [http://localhost:8000/](http://localhost:8000/). You should be able to view the examples individually by selecting them from the left side bar. To view the visualization, click the toggle button on the top right corner of the code block.\n\nGreat, this is how you can generate and view visualizations created using *RustViz*. Now let's create one from scratch!\n\n## Step-By-Step Guide\nIn this section, we'll dive into creating an example, [string_from_move_print](src/examples/string_from_move_print). Note that all visualization examples are placed under [`rustviz/src/examples/`](src/examples) directory and you can create a new directory in [`rustviz/src/examples/`](src/examples) of your own.\nFirst, take note of the file structure we'll need to run the example:\n```shell\nstring_from_move_print\n├── input\n│   └── annotated_source.rs\n└── source.rs\n```\n[source.rs](src/examples/string_from_move_print/source.rs) contains the untouched source code we wish to render into an image:\n```rust\nfn main() {\n    let x = String::from(\"hello\");\n    let y = x;\n    println!(\"{}\", y);\n}\n```\nIn this example, `String::from()` moves a string (`\"hello\"`) to `x`, then `x`'s resource is moved to `y`. Subsequently, `println!()` outputs a message to `io::stdout` without moving the resource.\n\n[annotated_source.rs](src/examples/string_from_move_print/input/annotated_source.rs) contains style annotation to [source.rs](src/examples/string_from_move_print/source.rs) so as to generate SVG for code panel.\n```rust\nfn main() {\n    let \u003ctspan data-hash=\"1\"\u003ex\u003c/tspan\u003e = \u003ctspan class=\"fn\" data-hash=\"0\" hash=\"3\"\u003eString::from\u003c/tspan\u003e(\"hello\");\n    let \u003ctspan data-hash=\"2\"\u003ey\u003c/tspan\u003e = \u003ctspan data-hash=\"1\"\u003ex\u003c/tspan\u003e;\n    \u003ctspan class=\"fn\" data-hash=\"0\" hash=\"4\"\u003eprintln!\u003c/tspan\u003e(\"{}\", \u003ctspan data-hash=\"2\"\u003ey\u003c/tspan\u003e);\n}\n```\n\nNext, let's familiarize ourselves with the syntax used in [main.rs](src/examples/string_from_move_print/main.rs). The RustViz tool **defines all possible owners, references or input of any memory resource** as a [ResourceAccessPoint](#Data_Structures_and_Function_Specifications). In this case, we consider the function `String::from()` and two variables, `x` and `y`, as Resource Access Points (RAPs). Each of `String::from()` and `x`/`y` corresponds to RAPs `ResourceAccessPoint::Function` and `ResourceAccessPoint::Owner`, respectively.\n\nIn [main.rs](src/examples/string_from_move_print/main.rs), we define these RAPs between the `BEGIN` and `END` comments on lines 1 and 2:\n```rust\n/*--- BEGIN Variable Definitions ---\nOwner x; Owner y;\nFunction String::from();\n--- END Variable Definitions ---*/\n```\nThe definition header now can be automatically generated by running the [view_examples.sh](rustviz_mdbook/view_examples.sh) once. If any incorrect information appeared at the generated header, you could manully edit it by refering to the following documentation.\n\nThe format for each `ResourceAccessPoint` enum is shown below, where fields preceded by `':'` denote an optional field:\n```rust\nResourceAccessPoint Usage --\n    Owner \u003c:mut\u003e \u003cname\u003e\n    MutRef \u003c:mut\u003e \u003cname\u003e\n    StaticRef \u003c:mut\u003e \u003cname\u003e\n    Struct \u003c:mut\u003e \u003cname\u003e{\u003c:mut\u003e \u003cmember_1\u003e, \u003c:mut\u003e \u003cmember_2\u003e, ... }\n    Function \u003cname\u003e\n```\nAlternatively, some code `let mut a = 5;` and `let b = \u0026a;` would correspond to `Owner mut a` and `StaticRef b`, respectively.\nAn immutable instance of some struct with member variables `x` and `mut y`, on the other hand, may be annotated as `Struct a{x, mut y}`.\n\n\u003e It is important to note:\n\u003e \u003col\u003e\n\u003e \u003cli\u003eall definitions \u003cstrong\u003e\u003cem\u003emust\u003c/em\u003e\u003c/strong\u003e lie between \u003ccode\u003eBEGIN\u003c/code\u003e and \u003ccode\u003eEND\u003c/code\u003e\u003c/li\u003e\n\u003e \u003cli\u003eall definitions \u003cstrong\u003e\u003cem\u003emust\u003c/em\u003e\u003c/strong\u003e be defined in the same order by which they were declared in the source code\u003c/li\u003e\n\u003e \u003cli\u003eall definitions \u003cstrong\u003e\u003cem\u003emust\u003c/em\u003e\u003c/strong\u003e be separated by a singular semicolon\u003c/li\u003e\n\u003e \u003cli\u003eeach field within a RAP definition \u003cstrong\u003e\u003cem\u003emust\u003c/em\u003e\u003c/strong\u003e be separated by a whitespace\u003c/li\u003e\n\u003e \u003c/ol\u003e\n\u003cbr\u003e\n\nAfter running the [view_examples.sh](rustviz_mdbook/view_examples.sh) once we should have the following file structure:\n```shell\nstring_from_move_print\n├── input\n│   └── annotated_source.rs\n├── main.rs\n└── source.rs\n```\n\nNext, we annotate the code with the use of `ExternalEvent`s that **describe move, borrow, and drop semantics** of Rust. In [string_from_move_print](src/examples/string_from_move_print), we have four such events:\n1. Move of resource from `String::from()` to `x`\n2. Move of resource from `y` to `x`\n3. Drop of resource binded to `x`\n4. Drop of resource binded to `y`\n\nWe can specify Events in structured comments like so:\n```rust\n/* --- BEGIN Variable Definitions ---\nOwner x; Owner y;\nFunction String::from();\n --- END Variable Definitions --- */\nfn main() {\n    let x = String::from(\"hello\"); // !{ Move(String::from()-\u003ex) }\n    let y = x; // !{ Move(x-\u003ey) }\n    println!(\"{}\", y); // print to stdout!\n} /* !{\n    GoOutOfScope(x),\n    GoOutOfScope(y)\n} */\n```\nEach Event is defined on the line where it occurs and within delimiters `!{` and `}`.\n\u003e Events can be annotated within block comments; however, the block **_must_** start on the line in which the events occur. Additionally, all Events within a `!{}` delimitation **_must_** be separated by a singular comma and must each follow the format:\n\n```rust\nExternalEvents Usage:\n    Format: \u003cevent_name\u003e(\u003cfrom\u003e-\u003e\u003cto\u003e)\n        e.g.: // !{ PassByMutableReference(a-\u003eSome_Function()), ... }\n    Note: GoOutOfScope and InitRefParam require only the \u003cfrom\u003e parameter\n        e.g.: // !{ GoOutOfScope(x) }\n```\n\u003e Refer to the [Appendix](#Appendix) for a list of usable `ExternalEvent`'s.\n\nPhew! All that's left is running the program. Simply navigate into [src](src) and run:\n```shell\ncargo run string_from_move_print\n```\nNow your folder should look like this:\n```\nstring_from_move_print\n├── input\n│   └── annotated_source.rs\n├── main.rs\n├── source.rs\n├── vis_code.svg\n└── vis_timeline.svg\n```\nCongratulations! You have successfully generated your first visualization! As a last step, add the name of your example to `targetExamples` under [view_examples.sh](rustviz_mdbook/view_examples.sh) and run the script from [rustviz_mdbook](rustviz_mdbook) to see it in your browser.\n\n## Appendix\n\n**`ExternalEvent` Usage:**\n| Event |   Usage   |\n| :---  |   :----   |\n| `Bind(a)` | Let binding or assignment.\u003cbr\u003ee.g.: `let a = 1;` |\n| `Copy(a-\u003eb)` | Copies the resource of `a` to variable `b`. Here, `a` implements the `Copy` trait. |\n| `Move(a-\u003eb)` | Moves the resource of `a` to variable `b`. Here, `a` implements the `Move` trait.\u003cbr\u003eNote: Moving to `None` (i.e.: `Move(a-\u003eNone)`) is used to express a move to the caller function. |\n| `StaticBorrow(a-\u003eb)` | Assigns an immutable reference of `a` to `b`.\u003cbr\u003ee.g.: `let b = \u0026a;` |\n| `MutableBorrow(a-\u003eb)` | Assigns a mutable reference of `a` to `b`.\u003cbr\u003ee.g.: `let b = \u0026mut a;` |\n| `StaticDie(a-\u003eb)` | Ends the non-lexical lifetime of the reference variable `a` and returns the resource back to its owner `b`. |\n| `MutableDie(a-\u003eb)` | Ends the non-lexical lifetime of the reference variable `a` and returns the resource back to its owner `b`. |\n| `PassByStaticReference(a-\u003eb)` | Passes an immutable reference of variable `a` to function `b`. Not to be confused with StaticBorrow. |\n| `PassByMutableReference(a-\u003eb)` | Passes a mutable reference of variable `a` to function `b`. Not to be confused with MutableBorrow. |\n| `GoOutOfScope(a)` | Ends the lexical lifetime of variable `a`. |\n| `InitRefParam(a)` | Initializes the parameter `a` of some function, which is a reference.\u003cbr\u003ee.g.: `some_fn(a: \u0026String) {..}` |\n| `InitOwnerParam(a)` | Initializes the parameter `a` of some function, which owns the resource.\u003cbr\u003ee.g.: `some_fn(a: String) {..}` |\n\n\u003e Note:\n\u003e 1. `GoOutOfScope`, `InitRefParam` and `InitOwnerParam` require a singular parameter previously defined in the `Variable Definitions` section.\n(e.g.: `// !{ GoOutOfScope(x) }`)\n\u003e 2. All other events require two parameters, `a` and `b`, which can either be defined (e.g.: `Owner a`) or undefined (`None`).\n\u003c!-- The `None` option is generally used for scalar types or undefined variables (e.g.: `let x = 1` can be annotated as `Bind(x)`).  --\u003e\nThe `None` type can be used as the `\u003cto\u003e` parameter (e.g.: `Move(a-\u003eNone)`) to specify a move to the function caller.\n\u003e 3. All uses of `Struct` fields must be preceded by its parent struct's name. (e.g.: `a.b = 1;` can be annotated as `Move(None-\u003ea.b)`, where `a` is the parent and `b` is the field.)\n\n## Visualization Limitations\n\nSome features are still being built. As of now, we are limited to:\n- No branching logic\n- No looping\n- No explicit lifetime annotation\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frustviz%2Frustviz","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frustviz%2Frustviz","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frustviz%2Frustviz/lists"}