diff --git a/.envrc b/.envrc
new file mode 100644
index 0000000..c4b17d7
--- /dev/null
+++ b/.envrc
@@ -0,0 +1 @@
+use_flake
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 0000000..d7571aa
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1,2 @@
+# Default
+* @fission-codes
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..e667a23
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,61 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: "\U0001F41B bug"
+assignees: ''
+
+---
+
+# Summary
+
+## Problem
+
+Describe the immediate problem.
+
+### Impact
+
+What's the impact of this bug?
+
+## Solution
+
+Describe the sort of fix that would solve the issue.
+
+# Detail
+
+**Describe the bug**
+
+A clear and concise description of what the bug is.
+
+**To Reproduce**
+
+Steps to reproduce the behavior:
+1. Go to '...'
+2. Click on '....'
+3. Scroll down to '....'
+4. See error
+
+**Expected behavior**
+
+A clear and concise description of what you expected to happen.
+
+**Screenshots**
+
+If applicable, add screenshots to help explain your problem.
+
+**Desktop (please complete the following information):**
+
+ - OS: [e.g. iOS]
+ - Browser [e.g. chrome, safari]
+ - Version [e.g. 22]
+
+**Smartphone (please complete the following information):**
+
+ - Device: [e.g. iPhone6]
+ - OS: [e.g. iOS8.1]
+ - Browser [e.g. stock browser, safari]
+ - Version [e.g. 22]
+
+**Additional context**
+
+Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000..fa69cb3
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,42 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: ''
+labels: "\U0001F497 enhancement"
+assignees: ''
+
+---
+
+NB: Feature requests will only be considered if they solve a pain or present a useful refactoring of the code.
+
+# Summary
+
+## Problem
+
+Describe the pain that this feature will solve.
+
+### Impact
+
+Describe the impact of not having this feature.
+
+## Solution
+
+Describe the solution.
+
+# Detail
+
+**Is your feature request related to a problem? Please describe.**
+
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+
+Add any other context or screenshots about the feature request here.
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..59d2411
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,27 @@
+# Description
+
+Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.
+
+## Link to issue
+
+Please add a link to any relevant issues/tickets.
+
+## Type of change
+
+- [ ] Bug fix (non-breaking change that fixes an issue)
+- [ ] New feature (non-breaking change that adds functionality)
+- [ ] Refactor (non-breaking change that updates existing functionality)
+- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
+- [ ] This change requires a documentation update
+- [ ] Comments have been added/updated
+
+Please delete options that are not relevant.
+
+## Test plan (required)
+
+Demonstrate the code is solid. Which commands did you test with and what are the expected results?
+Which tests have you added or updated? Do the tests cover all of the changes included in this PR?
+
+## Screenshots/Screencaps
+
+Please add previews of any UI Changes.
diff --git a/.github/audit.yml b/.github/audit.yml
new file mode 100644
index 0000000..aaaf74f
--- /dev/null
+++ b/.github/audit.yml
@@ -0,0 +1,18 @@
+name: 🛡 Audit-Check
+
+on:
+ schedule:
+ - cron: '0 0 * * *'
+
+jobs:
+ security-audit:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@v3
+
+ - name: Run Audit-Check
+ uses: rustsec/audit-check@v0.1.0
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..023e8a4
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,34 @@
+# To get started with Dependabot version updates, you'll need to specify which
+# package ecosystems to update and where the package manifests are located.
+# Please see the documentation for all configuration options:
+# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
+
+version: 2
+
+updates:
+ - package-ecosystem: "cargo"
+ directory: "/rhizome"
+ commit-message:
+ prefix: "chore(rust)"
+ include: "scope"
+ target-branch: "main"
+ schedule:
+ interval: "weekly"
+
+ - package-ecosystem: "npm"
+ directory: "/rhizome-wasm"
+ commit-message:
+ prefix: "chore(npm)"
+ include: "scope"
+ target-branch: "main"
+ schedule:
+ interval: "weekly"
+
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ commit-message:
+ prefix: "chore(ci)"
+ include: "scope"
+ target-branch: "main"
+ schedule:
+ interval: "weekly"
diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml
new file mode 100644
index 0000000..c3eba11
--- /dev/null
+++ b/.github/workflows/audit.yml
@@ -0,0 +1,18 @@
+name: 🛡 Audit-Check
+
+on:
+ schedule:
+ - cron: '0 0 * * *'
+
+jobs:
+ security-audit:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@v3
+
+ - name: Run Audit-Check
+ uses: rustsec/audit-check@0.1.0
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml
new file mode 100644
index 0000000..a7dd5d6
--- /dev/null
+++ b/.github/workflows/bench.yml
@@ -0,0 +1,58 @@
+name: 📈 Benchmark
+
+on:
+ push:
+ branches: [ main ]
+
+ pull_request:
+ branches: [ '*' ]
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ benchmark:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@v3
+
+ - name: Install Rust Toolchain
+ uses: actions-rs/toolchain@v1
+ with:
+ override: true
+ toolchain: stable
+
+ - name: Cache Project
+ uses: Swatinem/rust-cache@v2
+
+ - name: Run Benchmark
+ run: cargo bench -p rhizome-benches -- --output-format bencher | tee output.txt
+
+ - name: Upload Benchmark Result Artifact
+ uses: actions/upload-artifact@v3
+ with:
+ name: bench_result
+ path: output.txt
+
+ - name: Create gh-pages Branch
+ uses: peterjgrainger/action-create-branch@v2.3.0
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ branch: gh-pages
+
+ - name: Store Benchmark Result
+ uses: benchmark-action/github-action-benchmark@v1
+ with:
+ name: Rust Benchmark
+ tool: 'cargo'
+ output-file-path: output.txt
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ auto-push: ${{ github.event_name == 'push' && github.repository == 'QuinnWilton/rhizome' && github.ref == 'refs/heads/main' }}
+ alert-threshold: '200%'
+ comment-on-alert: true
+ fail-on-alert: true
+ alert-comment-cc-users: '@fission-codes'
diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml
new file mode 100644
index 0000000..4c475b2
--- /dev/null
+++ b/.github/workflows/coverage.yml
@@ -0,0 +1,62 @@
+name: ☂ Code Coverage
+
+on:
+ push:
+ branches: [ main ]
+
+ pull_request:
+ branches: [ '*' ]
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ coverage:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@v3
+
+ - name: Install Rust Toolchain
+ uses: actions-rs/toolchain@v1
+ with:
+ override: true
+ toolchain: nightly
+ components: llvm-tools-preview
+ profile: minimal
+
+ - name: Cache Project
+ uses: Swatinem/rust-cache@v2
+
+ - name: Generate Code coverage
+ env:
+ CARGO_INCREMENTAL: '0'
+ LLVM_PROFILE_FILE: "rhizome-%p-%m.profraw"
+ RUSTFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests'
+ RUSTDOCFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests'
+ ## currently just runs coverage on rust project
+ run: cargo test -p rhizome --all-features
+
+ - name: Install grcov
+ run: "curl -L https://github.com/mozilla/grcov/releases/download/v0.8.12/grcov-x86_64-unknown-linux-gnu.tar.bz2 | tar jxf -"
+
+ - name: Run grcov
+ run: "./grcov . --llvm --binary-path target/debug/ -s . -t lcov --branch --ignore-not-existing --ignore '/*' -o lcov.info"
+
+ - name: Install covfix
+ uses: actions-rs/install@v0.1
+ with:
+ crate: rust-covfix
+ use-tool-cache: true
+
+ - name: Run covfix
+ run: rust-covfix lcov.info -o lcov.info --verbose
+
+ - name: Upload to codecov.io
+ uses: codecov/codecov-action@v3
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
+ fail_ci_if_error: true
+ files: lcov.info
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..87eb466
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,121 @@
+name: 𝌚 Release
+
+on:
+ workflow_dispatch:
+ inputs:
+ force-publish:
+ required: true
+ type: boolean
+ description: Publish Releases at Anytime
+
+ workflow_run:
+ workflows: [ 🧪 Tests and Checks ]
+ branches: [main]
+ types: [ completed ]
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ release-please:
+ runs-on: ubuntu-latest
+ if: github.ref == 'refs/heads/main' && github.repository_owner == 'QuinnWilton'
+
+ steps:
+ - name: Run release-please
+ id: release
+ uses: google-github-actions/release-please-action@v3
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
+ default-branch: main
+ command: manifest
+ extra-files: |
+ Cargo.toml
+
+ publish-release-crates:
+ if: ${{ needs.release.outputs.releases_created || github.event.inputs.force-publish }}
+
+ runs-on: ubuntu-latest
+ needs: [ release-please ]
+
+ permissions:
+ contents: write
+ pull-requests: write
+
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@v3
+
+ - name: Cache Project
+ uses: Swatinem/rust-cache@v2
+
+ - name: Install Rust Toolchain
+ uses: actions-rs/toolchain@v1
+ with:
+ override: true
+ profile: minimal
+ toolchain: stable
+
+ - name: Install Cargo Workspaces
+ env:
+ RUSTFLAGS: '-Copt-level=1'
+ uses: actions-rs/cargo@v1
+ with:
+ args: --force cargo-workspaces
+ command: install
+
+ - name: Cargo Publish to crates.io
+ env:
+ CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
+ run: cargo workspaces publish --from-git
+
+ publish-release-npm:
+ if: ${{ needs.release-please.outputs.releases_created || github.event.inputs.force-publish }}
+
+ runs-on: ubuntu-latest
+ needs: [ release-please ]
+
+ permissions:
+ contents: write
+ pull-requests: write
+
+ defaults:
+ run:
+ working-directory: ./rhizome-wasm
+
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@v3
+
+ - name: Cache Project
+ uses: Swatinem/rust-cache@v2
+
+ - name: Install Rust Toolchain
+ uses: actions-rs/toolchain@v1
+ with:
+ override: true
+ profile: minimal
+ toolchain: stable
+
+ - name: Setup Node
+ uses: actions/setup-node@v3
+ with:
+ node-version: '16.x'
+ registry-url: 'https://registry.npmjs.org'
+
+ - name: Install wasm-pack
+ run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
+
+ # Builds output via wasm-pack and renames package.json name to remove
+ # `-wasm`.
+ - name: Build
+ run: |
+ wasm-pack build --target bundler --out-name rhizome
+ sed -i -e 's/"name": "rhizome-wasm"/"name": "rhizome",\n "type": "module"/g' pkg/package.json
+
+ - name: Publish to npm
+ run: wasm-pack publish
+ working-directory: pkg
+ env:
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
diff --git a/.github/workflows/tests_and_checks.yml b/.github/workflows/tests_and_checks.yml
new file mode 100644
index 0000000..49a206e
--- /dev/null
+++ b/.github/workflows/tests_and_checks.yml
@@ -0,0 +1,134 @@
+name: 🧪 Tests and Checks
+
+on:
+ push:
+ branches: [ main ]
+
+ pull_request:
+ branches: [ '*' ]
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ run-checks:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ rust-toolchain:
+ - stable
+ - nightly
+ # minimum version
+ - 1.64
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@v3
+
+ # Smarter caching action, speeds up build times compared to regular cache:
+ # https://github.com/Swatinem/rust-cache
+ - name: Cache Project
+ uses: Swatinem/rust-cache@v2
+
+ # Widely adopted suite of Rust-specific boilerplate actions, especially
+ # toolchain/cargo use: https://actions-rs.github.io/
+ - name: Install Rust Toolchain
+ uses: actions-rs/toolchain@v1
+ with:
+ override: true
+ components: rustfmt, clippy
+ toolchain: ${{ matrix.rust-toolchain }}
+
+ - name: Check Format
+ uses: actions-rs/cargo@v1
+ with:
+ args: --all -- --check
+ command: fmt
+ toolchain: ${{ matrix.rust-toolchain }}
+
+ - name: Run Linter
+ uses: actions-rs/cargo@v1
+ with:
+ args: --all -- -D warnings
+ command: clippy
+ toolchain: ${{ matrix.rust-toolchain }}
+
+ # Check for security advisories.
+ - name: Check Advisories
+ if: ${{ matrix.rust-toolchain == 'stable' }}
+ uses: EmbarkStudios/cargo-deny-action@v1
+ with:
+ command: check advisories
+ continue-on-error: true
+
+ # Audit licenses, unreleased crates, and unexpected duplicate versions.
+ - name: Check Bans, Licenses, and Sources
+ if: ${{ matrix.rust-toolchain == 'stable' }}
+ uses: EmbarkStudios/cargo-deny-action@v1
+ with:
+ command: check bans licenses sources
+
+ - name: Install wasm-pack
+ if: ${{ matrix.rust-toolchain == 'stable' }} && github.event_name == 'push' }}
+ run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
+
+ # Only "test" release build on push event.
+ - name: Test Release
+ if: ${{ matrix.rust-toolchain == 'stable' }} && github.event_name == 'push' }}
+ run: |
+ cargo build --manifest-path rhizome/Cargo.toml --release
+ cd rhizome-wasm && wasm-pack build --target bundler --release
+
+ run-cargo-tests:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ rust-toolchain:
+ - stable
+ - nightly
+
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@v3
+
+ - name: Cache Project
+ uses: Swatinem/rust-cache@v2
+
+ - name: Install Rust Toolchain
+ uses: actions-rs/toolchain@v1
+ with:
+ override: true
+ toolchain: ${{ matrix.rust-toolchain }}
+
+ - name: Run Tests
+ run: cargo test --manifest-path rhizome/Cargo.toml --all-features
+
+ run-node-tests:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+
+ defaults:
+ run:
+ working-directory: ./rhizome-wasm
+
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@v3
+
+ - name: Install wasm-pack
+ run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
+
+ - name: Cache Project
+ uses: Swatinem/rust-cache@v2
+
+ - name: Install Rust Toolchain
+ uses: actions-rs/toolchain@v1
+ with:
+ override: true
+ toolchain: stable
+
+ - name: Run Rust Headless Browser Tests
+ run: wasm-pack test --node
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..eea73cb
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,22 @@
+# Generated by Cargo
+# will have compiled files and executables
+**/target/
+Cargo.lock
+# These are backup files generated by rustfmt
+**/*.rs.bk
+
+# Ignore local environment settings
+.envrc.custom
+.direnv
+
+**/package-lock.json
+**/pkg/
+wasm-pack.log
+**/node_modules/
+
+# Other files + dirs
+private
+*.temp
+*.tmp
+**/.history
+**/.DS_Store
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..72af443
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,57 @@
+# See https://pre-commit.com for more information
+# pre-commit install
+# pre-commit install --hook-type commit-msg
+exclude: ^(LICENSE|LICENSE*)
+repos:
+ - repo: local
+ hooks:
+ - id: fmt
+ name: fmt
+ description: Format rust files.
+ entry: cargo fmt
+ language: system
+ types: [rust]
+ args: ["--all", "--", "--check"]
+ - id: cargo-check
+ name: cargo check
+ description: Check the package for errors.
+ entry: cargo check
+ language: system
+ types: [rust]
+ pass_filenames: false
+ - id: clippy
+ name: clippy
+ description: Lint via clippy
+ entry: cargo clippy
+ language: system
+ args: ["--workspace", "--", "-D", "warnings"]
+ types: [rust]
+ pass_filenames: false
+
+ - repo: https://github.com/DevinR528/cargo-sort
+ rev: v1.0.9
+ hooks:
+ - id: cargo-sort
+ args: ["-w"]
+
+ - repo: https://github.com/compilerla/conventional-pre-commit
+ rev: v2.1.1
+ hooks:
+ - id: conventional-pre-commit
+ stages:
+ - commit-msg
+
+ - repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v4.3.0
+ hooks:
+ - id: no-commit-to-branch
+ args: ["-b", "main"]
+ - id: check-merge-conflict
+ - id: trailing-whitespace
+ - id: end-of-file-fixer
+ - id: check-yaml
+ - id: check-json
+ - id: check-added-large-files
+ - id: detect-private-key
+ - id: check-executables-have-shebangs
+ - id: check-toml
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
new file mode 100644
index 0000000..e960505
--- /dev/null
+++ b/.release-please-manifest.json
@@ -0,0 +1,4 @@
+{
+ "rhizome": "0.1.0",
+ "rhizome-wasm": "0.1.0"
+}
diff --git a/.rustfmt.toml b/.rustfmt.toml
new file mode 100644
index 0000000..56de2dd
--- /dev/null
+++ b/.rustfmt.toml
@@ -0,0 +1,2 @@
+edition = "2021"
+imports_granularity = "Crate"
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..e69de29
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..428e868
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,108 @@
+# Code of Conduct
+
+**TL;DR Be kind, inclusive, and considerate.**
+
+In the interest of fostering an open, inclusive, and welcoming environment, all
+members, contributors, and maintainers interacting within our online community
+(including Discord, Discourse, etc.), on affiliated projects and repositories
+(including issues, pull requests, and discussions on Github), and/or involved
+with associated events pledge to accept and observe the following Code of
+Conduct.
+
+As members, contributors, and maintainers, we pledge to make participation in
+our projects and community a harassment-free experience, ensuring a safe
+environment for all, regardless of background, gender, gender identity and
+expression, age, sexual orientation, disability, physical appearance, body size,
+race, ethnicity, religion (or lack thereof), or any other dimension of
+diversity.
+
+Sexual language and imagery will not be accepted in any way. Be kind to others.
+Do not insult or put down people within the community. Behave professionally.
+Remember that harassment and sexist, racist, or exclusionary jokes are not
+appropriate in any form. Participants violating these rules may be sanctioned or
+expelled from the community and related projects.
+
+## Spelling it out.
+
+Harassment includes offensive verbal comments or actions related to or involving
+
+- background
+- gender
+- gender identity and expression
+- age
+- sexual orientation
+- disability
+- physical appearance
+- body size
+- race
+- ethnicity
+- religion (or lack thereof)
+- economic status
+- geographic location
+- technology choices
+- sexual imagery
+- deliberate intimidation
+- violence and threats of violence
+- stalking
+- doxing
+- inappropriate or unwelcome physical contact in public spaces
+- unwelcomed sexual attention
+- influencing unacceptable behavior
+- any other dimension of diversity
+
+## Our Responsibilities
+
+Maintainers of the community and associated projects are not only subject to the
+anti-harassment policy, but also responsible for executing the policy,
+moderating related forums, and for taking appropriate and fair corrective action
+in response to any instances of unacceptable behavior that breach the policy.
+
+Maintainers have the right to remove and reject comments, threads, commits,
+code, documentation, pull requests, issues, and contributions not aligned with
+this Code of Conduct.
+
+## Scope
+
+This Code of Conduct applies within all project and community spaces, as well as
+in any public spaces where an individual representing the community is involved.
+This covers
+
+- Interactions on the Github repository, including discussions, issues, pull
+ requests, commits, and wikis
+- Interactions on any affiliated Discord, Slack, IRC, or related online
+ communities and forums like Discourse, etc.
+- Any official project emails and social media posts
+- Individuals representing the community at public events like meetups, talks,
+ and presentations
+
+## Enforcement
+
+All instances of abusive, harassing, or otherwise unacceptable behavior should
+be reported by contacting the project and community maintainers at
+[quinn@fission.codes][support-email]. All complaints will be reviewed and
+investigated and will result in a response that is deemed necessary and
+appropriate to the circumstances.
+
+Maintainers of the community and associated projects are obligated to maintain
+confidentiality with regard to the reporter of an incident. Further details of
+specific enforcement policies may be posted separately.
+
+Anyone asked to stop abusive, harassing, or otherwise unacceptable behavior are
+expected to comply immediately and accept the response decided on by the
+maintainers of the community and associated projects.
+
+## Need help?
+
+If you are experiencing harassment, witness an incident or have concerns about
+content please contact us at [quinn@fission.codes][support-email].
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant, v2.1][contributor-cov],
+among other sources like [!!con’s Code of Conduct][!!con] and
+[Mozilla’s Community Participation Guidelines][mozilla].
+
+[!!con]: https://bangbangcon.com/conduct.html
+[contributor-cov]: https://www.contributor-covenant.org/version/2/1/code_of_conduct/
+[mozilla]: https://www.mozilla.org/en-US/about/governance/policies/participation/
+[support-email]: mailto:quinn@fission.codes
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..e7b0d2b
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,150 @@
+# Contributing to rhizome
+
+We welcome everyone to contribute what and where they can. Whether you are brand
+new, just want to contribute a little bit, or want to contribute a lot there is
+probably something you can help out with. Check out our
+[good first issues][good-first-issues] label for in the issues tab to see a list
+of issue that good for those new to the project.
+
+## Where to Get Help
+
+The main way to get help is on our [discord server](https://fission.codes/discord).server][https://fission.codes/discord].
+Though, this guide should help you get started. It may be slightly lengthy, but it's
+designed for those who are new so please don't let length intimidate you.
+
+## Code of Conduct
+
+Please be kind, inclusive, and considerate when interacting when interacting
+with others and follow our [code of conduct](./CODE_OF_CONDUCT.md).
+
+## How to Contribute
+
+If the code adds a feature that is not already present in an issue, you can
+create a new issue for the feature and add the pull request to it. If the code
+adds a feature that is not already present in an issue, you can create a new
+issue for the feature and add the pull request to it.
+
+### Contributing by Adding a Topic for Discussion
+
+#### Issues
+
+If you have found a bug and would like to report it or if you have a feature
+that you feel we should add, then we'd love it if you opened an issue! ❤️
+Before you do, please search the other issues to avoid creating a duplicate
+issue.
+
+To submit a new issue just hit the issue button and a choice between two
+templates should appear. Then, follow along with the template you chose. If you
+don't know how to fill in all parts of the template go ahead and skip those
+parts. You can edit the issue later.
+
+#### Discussion
+
+If you have a new discussion you want to start but it isn't a bug or feature
+add, then you can start a [GitHub discussion][gh-discussions]. Some examples of
+what kinds of things that are good discussion topics can include, but are not
+limited to the following:
+
+- Community announcements and/or asking the community for feedback
+- Discussing a new release
+- Asking questions, Q&A that isn't for sure a bug report
+
+### Contributing through Code
+
+In order to contribute through code follow the steps below. Note that you don't
+need to be the best programmer to contribute. Our discord is open for questions
+ 1. **Pick a feature** you would like to add or a bug you would like to fix
+ - If you wish to contribute but what you want to fix/add is not already
+ covered in an existing issue, please open a new issue.
+
+ 2. **Discuss** the issue with the rest of the community
+ - Before you write any code, it is recommended that you discuss your
+ intention to write the code on the issue you are attempting to edit.
+ - This helps to stop you from wasting your time duplicating the work of
+ others that maybe working on the same issue; at the same time.
+ - This step also allows you to get helpful pointers on the community on some
+ problems they may have encountered on similar issues.
+
+ 3. **Fork** the repository
+ - A fork creates a copy of the code on your Github, so you can work on it
+ separately from everyone else.
+ - You can learn more about forking [here][forking].
+
+ 4. Ensure that you have **commit signing** enabled
+ - This ensures that the code you submit was committed by you and not someone
+ else who claims to be you.
+ - You can learn more about how to setup commit signing [here][commit-signing].
+ - If you have already made some commits that you wish to put in a pull
+ request without signing them, then you can follow [this guide][post-signing]
+ on how to fix that.
+
+ 5. **Clone** the repository to your local computer
+ - This puts a copy of your fork on your computer so you can edit it
+ - You can learn more about cloning repositories [here][git-clone].
+
+ 6. **Build** the project
+ - For a detailed look on how to build rhizome look at our
+ [README file](./README.md).
+
+ 7. **Start writing** your code
+ - Open up your favorite code editor and make the changes that you wanted to
+ make to the repository.
+ - Make sure to test your code with the test command(s) found in our
+ [README file](./README.md).
+
+ 8. **Write tests** for your code
+ - If you are adding a new feature, you should write tests that ensure that
+ if someone make changes to the code it cannot break your new feature
+ without breaking the test.
+ - If your code adds a new feature, you should also write at least one
+ documentation test. The documentation test's purpose is to demonstrate and
+ document how to use the API feature.
+ - If your code fixes a bug, you should write tests that ensure that if
+ someone makes code changes in the future the bug does not re-emerge
+ without breaking test.
+ - Please create integration tests, if the addition is large enough to
+ warrant them, and unit tests.
+ * Unit tests are tests that ensure the functionality of a single
+ function or small section of code.
+ * Integration tests test large large sections of code.
+ * Read more about the differences [here][unit-and-integration].
+ - For more information on test organization, take a look [here][test-org].
+
+ 9. Ensure that the code that you made follows our Rust **coding guidelines**
+ - You can find a list of some Rust guidelines [here][rust-style-guide]. This
+ is a courtesy to the programmers that come after you. The easier your code
+ is to read, the easier it will be for the next person to make modifications.
+ - If you find it difficult to follow the guidelines or if the guidelines or
+ unclear, please reach out to us through our discord linked above, or you
+ can just continue and leave a comment at the pull request stage.
+
+ 10. **Commit and Push** your code
+ - This sends your changes to your repository branch.
+ - You can learn more about committing code [here][commiting-code] and
+ pushing it to a remote repository [here][push-remote].
+ - We use conventional commits for the names and description of commits.
+ You can find out more about them [here][conventional-commits].
+
+ 11. The final step is to create **pull request** to our main branch 🎉
+ - A pull request is how you merge the code you just worked so hard on with
+ the code everyone else has access to.
+ - Once you have submitted your pull request, we will review your code and
+ check to make sure the code implements the feature or fixes the bug. We
+ may leave some feedback and suggest edits. You can make the changes we
+ suggest by committing more code to your fork.
+ - You can learn more about pull requests [here][prs].
+
+
+[conventional-commits]: https://www.conventionalcommits.org/en/v1.0.0/
+[commiting-code]: https://docs.github.com/en/desktop/contributing-and-collaborating-using-github-desktop/making-changes-in-a-branch/committing-and-reviewing-changes-to-your-project
+[commit-signing]: https://www.freecodecamp.org/news/what-is-commit-signing-in-git/
+[forking]: https://docs.github.com/en/get-started/quickstart/fork-a-repo
+[gh-discussions]: https://docs.github.com/en/discussions
+[git-clone]: https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository
+[good-first-issues]: [https://build.prestashop-project.org/news/a-definition-of-the-good-first-issue-label/]
+[post-signing]: https://dev.to/jmarhee/signing-existing-commits-with-gpg-5b58
+[prs]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests
+[push-remote]: https://docs.github.com/en/get-started/using-git/pushing-commits-to-a-remote-repository
+[rust-style-guide]: https://rust-lang.github.io/api-guidelines/about.html
+[test-org]: https://doc.rust-lang.org/book/ch11-03-test-organization.html
+[unit-and-integration]: https://www.geeksforgeeks.org/difference-between-unit-testing-and-integration-testing/
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..2651a9b
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,16 @@
+[workspace]
+members = [
+ "examples",
+ "rhizome",
+ "rhizome-benches",
+ "rhizome-wasm"
+]
+
+[profile.release]
+# Tell `rustc` to optimize for small code size.
+opt-level = "s"
+
+# Speedup build on macOS
+# See https://blog.rust-lang.org/2021/03/25/Rust-1.51.0.html#splitting-debug-information
+[profile.dev]
+split-debuginfo = "unpacked"
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..2866df5
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2022 Quinn Wilton
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..8700f7e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,217 @@
+
+
+:warning: Work in progress :warning:
+
+##
+
+## Outline
+
+- [Crates](#crates)
+- [Usage](#usage)
+- [Testing the Project](#testing-the-project)
+- [Benchmarking the Project](#benchmarking-the-project)
+- [Setting-up rhizome-wasm](#setting-up-rhizome-wasm)
+- [Contributing](#contributing)
+- [Getting Help](#getting-help)
+- [External Resources](#external-resources)
+- [License](#license)
+
+## Crates
+
+- [rhizome](https://github.com/QuinnWilton/rhizome/tree/main/rhizome)
+- [rhizome-wasm](https://github.com/QuinnWilton/rhizome/tree/main/)
+
+## Usage
+
+- Add the following to the `[dependencies]` section of your `Cargo.toml` file
+ for using the rust-only `rhizome` crate/workspace:
+
+```toml
+rhizome = "0.1.0"
+```
+
+- Add the following to the `[dependencies]` section of your `Cargo.toml` file
+ for using `rhizome-wasm` crate/workspace:
+
+```toml
+rhizome-wasm = "0.1.0"
+```
+
+## Testing the Project
+
+- Run tests for crate/workspace `rhizome`:
+
+ ```console
+ cd rhizome && cargo test --all-features
+ ```
+
+- To run tests for crate/workspace `rhizome-wasm`, follow
+ the instructions in [rhizome-wasm](./rhizome-wasm#testing-the-project),
+ which leverages [wasm-pack][wasm-pack].
+
+## Benchmarking the Project
+
+For benchmarking and measuring performance, this workspaces provides
+a Rust-specific benchmarking package leveraging [criterion][criterion] and a
+`test_utils` feature flag for integrating [proptest][proptest] within the
+suite for working with [strategies][strategies] and sampling from randomly
+generated values.
+
+- Run benchmarks
+
+ ```console
+ cargo bench -p rhizome-benches
+ ```
+
+*Note*: Currently, this workspace only supports Rust-native benchmarking, as
+`wasm-bindgen` support for criterion is still [an open issue][criterion-bindgen].
+However, with some extra work, benchmarks can be compiled to [wasi][wasi] and
+run with [wasmer][wasmer]/[wasmtime][wasmtime] or in the brower with
+[webassembly.sh][wasmsh]. Please catch-up with wasm support for criterion on their
+[user-guide][criterion-user-guide].
+
+## Setting-up rhizome-wasm
+
+The Wasm targetted version of this project relies on [wasm-pack][wasm-pack]
+for building, testing, and publishing artifacts sutiable for
+[Node.js][node-js], web broswers, or bundlers like [webpack][webpack].
+
+Please read more on working with `wasm-pack` directly in
+[rhizome-wasm](./rhizome-wasm#set-up).
+
+## Contributing
+
+:balloon: We're thankful for any feedback and help in improving our project!
+We have a [contributing guide](./CONTRIBUTING.md) to help you get involved. We
+also adhere to our [Code of Conduct](./CODE_OF_CONDUCT.md).
+
+### Nix
+This repository contains a [Nix flake][nix-flake] that initiates both the Rust
+toolchain set in [rust-toolchain.toml](./rust-toolchain.toml) and a
+[pre-commit hook](#pre-commit-hook). It also installs helpful cargo binaries for
+development. Please install [nix][nix] and [direnv][direnv] to get started.
+
+Run `nix develop` or `direnv allow` to load the `devShell` flake output,
+according to your preference.
+
+### Formatting
+
+For formatting Rust in particular, please use `cargo +nightly fmt` as it uses
+specific nightly features we recommend by default.
+
+### Pre-commit Hook
+
+This library recommends using [pre-commit][pre-commit] for running pre-commit
+hooks. Please run this before every commit and/or push.
+
+- If you are doing interim commits locally, and for some reason if you _don't_
+ want pre-commit hooks to fire, you can run
+ `git commit -a -m "Your message here" --no-verify`.
+
+### Recommended Development Flow
+
+- We recommend leveraging [cargo-watch][cargo-watch],
+ [cargo-expand][cargo-expand] and [irust][irust] for Rust development.
+- We recommend using [cargo-udeps][cargo-udeps] for removing unused dependencies
+ before commits and pull-requests.
+
+### Conventional Commits
+
+This project *lightly* follows the [Conventional Commits
+convention][commit-spec-site] to help explain
+commit history and tie in with our release process. The full specification
+can be found [here][commit-spec]. We recommend prefixing your commits with
+a type of `fix`, `feat`, `docs`, `ci`, `refactor`, etc..., structured like so:
+
+```
+[optional scope]:
+
+[optional body]
+
+[optional footer(s)]
+```
+
+## Getting Help
+
+For usage questions, usecases, or issues reach out to us in our [Discord channel](https://fission.codes/discord).
+
+We would be happy to try to answer your question or try opening a new issue on Github.
+
+## External Resources
+
+These are references to specifications, talks and presentations, etc.
+
+## License
+
+This project is licensed under either of
+
+- Apache License, Version 2.0, ([LICENSE-APACHE](./LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
+- MIT license ([LICENSE-MIT](./LICENSE-MIT) or http://opensource.org/licenses/MIT)
+
+at your option.
+
+### Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally
+submitted for inclusion in the work by you, as defined in the Apache-2.0
+license, shall be dual licensed as above, without any additional terms or
+conditions.
+
+
+[apache]: https://www.apache.org/licenses/LICENSE-2.0
+[cargo-expand]: https://github.com/dtolnay/cargo-expand
+[cargo-udeps]: https://github.com/est31/cargo-udeps
+[cargo-watch]: https://github.com/watchexec/cargo-watch
+[commit-spec]: https://www.conventionalcommits.org/en/v1.0.0/#specification
+[commit-spec-site]: https://www.conventionalcommits.org/
+[criterion]: https://github.com/bheisler/criterion.rs
+[criterion-bindgen]: https://github.com/bheisler/criterion.rs/issues/270
+[direnv]:https://direnv.net/
+[irust]: https://github.com/sigmaSd/IRust
+[mit]: http://opensource.org/licenses/MIT
+[nix]:https://nixos.org/download.html
+[nix-flake]: https://nixos.wiki/wiki/Flakes
+[node-js]: https://nodejs.dev/en/
+[pre-commit]: https://pre-commit.com/
+[proptest]: https://github.com/proptest-rs/proptest
+[strategies]: https://docs.rs/proptest/latest/proptest/strategy/trait.Strategy.html
+[criterion-user-guide]: https://github.com/bheisler/criterion.rs/blob/version-0.4/book/src/user_guide/wasi.md
+[wasi]: https://wasi.dev/
+[wasmer]: https://wasmer.io/
+[wasmtime]: https://docs.wasmtime.dev/
+[wasmsh]: https://webassembly.sh/
+[wasm-pack]: https://rustwasm.github.io/docs/wasm-pack/
+[webpack]: https://webpack.js.org/
diff --git a/assets/a_logo.png b/assets/a_logo.png
new file mode 100644
index 0000000..3bb0c69
Binary files /dev/null and b/assets/a_logo.png differ
diff --git a/codecov.yml b/codecov.yml
new file mode 100644
index 0000000..478bb86
--- /dev/null
+++ b/codecov.yml
@@ -0,0 +1,18 @@
+ignore:
+ - "rhizome/tests"
+ - "rhizome-wasm"
+ - "rhizome-benches"
+ - "examples"
+
+comment:
+ layout: "reach, diff, flags, files"
+ require_changes: true
+
+github_checks:
+ annotations: false
+
+coverage:
+ status:
+ project:
+ default:
+ threshold: 5%
diff --git a/deny.toml b/deny.toml
new file mode 100644
index 0000000..dc47d3b
--- /dev/null
+++ b/deny.toml
@@ -0,0 +1,197 @@
+# This template contains all of the possible sections and their default values
+
+# Note that all fields that take a lint level have these possible values:
+# * deny - An error will be produced and the check will fail
+# * warn - A warning will be produced, but the check will not fail
+# * allow - No warning or error will be produced, though in some cases a note
+# will be
+
+# The values provided in this template are the default values that will be used
+# when any section or field is not specified in your own configuration
+
+# If 1 or more target triples (and optionally, target_features) are specified,
+# only the specified targets will be checked when running `cargo deny check`.
+# This means, if a particular package is only ever used as a target specific
+# dependency, such as, for example, the `nix` crate only being used via the
+# `target_family = "unix"` configuration, that only having windows targets in
+# this list would mean the nix crate, as well as any of its exclusive
+# dependencies not shared by any other crates, would be ignored, as the target
+# list here is effectively saying which targets you are building for.
+targets = [
+ # The triple can be any string, but only the target triples built in to
+ # rustc (as of 1.40) can be checked against actual config expressions
+ #{ triple = "x86_64-unknown-linux-musl" },
+ # You can also specify which target_features you promise are enabled for a
+ # particular target. target_features are currently not validated against
+ # the actual valid features supported by the target architecture.
+ #{ triple = "wasm32-unknown-unknown", features = ["atomics"] },
+]
+
+# This section is considered when running `cargo deny check advisories`
+# More documentation for the advisories section can be found here:
+# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html
+[advisories]
+# The path where the advisory database is cloned/fetched into
+db-path = "~/.cargo/advisory-db"
+# The url(s) of the advisory databases to use
+db-urls = ["https://github.com/rustsec/advisory-db"]
+# The lint level for security vulnerabilities
+vulnerability = "deny"
+# The lint level for unmaintained crates
+unmaintained = "warn"
+# The lint level for crates that have been yanked from their source registry
+yanked = "deny"
+# The lint level for crates with security notices. Note that as of
+# 2019-12-17 there are no security notice advisories in
+# https://github.com/rustsec/advisory-db
+notice = "warn"
+# A list of advisory IDs to ignore. Note that ignored advisories will still
+# output a note when they are encountered.
+ignore = [
+ #"RUSTSEC-0000-0000"
+]
+# Threshold for security vulnerabilities, any vulnerability with a CVSS score
+# lower than the range specified will be ignored. Note that ignored advisories
+# will still output a note when they are encountered.
+# * None - CVSS Score 0.0
+# * Low - CVSS Score 0.1 - 3.9
+# * Medium - CVSS Score 4.0 - 6.9
+# * High - CVSS Score 7.0 - 8.9
+# * Critical - CVSS Score 9.0 - 10.0
+#severity-threshold =
+
+# This section is considered when running `cargo deny check licenses`
+# More documentation for the licenses section can be found here:
+# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html
+[licenses]
+# The lint level for crates which do not have a detectable license
+unlicensed = "deny"
+# List of explicitly allowed licenses
+# See https://spdx.org/licenses/ for list of possible licenses
+# [possible values: any SPDX 3.7 short identifier (+ optional exception)].
+allow = [
+ "Apache-2.0",
+ "MIT",
+ "BSD-3-Clause"
+]
+# List of explicitly disallowed licenses
+# See https://spdx.org/licenses/ for list of possible licenses
+# [possible values: any SPDX 3.7 short identifier (+ optional exception)].
+deny = [
+ #"Nokia",
+]
+# Lint level for licenses considered copyleft
+copyleft = "deny"
+# Blanket approval or denial for OSI-approved or FSF Free/Libre licenses
+# * both - The license will be approved if it is both OSI-approved *AND* FSF
+# * either - The license will be approved if it is either OSI-approved *OR* FSF
+# * osi-only - The license will be approved if is OSI-approved *AND NOT* FSF
+# * fsf-only - The license will be approved if is FSF *AND NOT* OSI-approved
+# * neither - This predicate is ignored and the default lint level is used
+allow-osi-fsf-free = "neither"
+# Lint level used when no other predicates are matched
+# 1. License isn't in the allow or deny lists
+# 2. License isn't copyleft
+# 3. License isn't OSI/FSF, or allow-osi-fsf-free = "neither"
+default = "deny"
+# The confidence threshold for detecting a license from license text.
+# The higher the value, the more closely the license text must be to the
+# canonical license text of a valid SPDX license file.
+# [possible values: any between 0.0 and 1.0].
+confidence-threshold = 0.8
+# Allow 1 or more licenses on a per-crate basis, so that particular licenses
+# aren't accepted for every possible crate as with the normal allow list
+exceptions = [
+ # The Unicode-DFS-2016 license is necessary for unicode-ident because they
+ # use data from the unicode tables to generate the tables which are
+ # included in the application. We do not distribute those data files so
+ # this is not a problem for us. See https://github.com/dtolnay/unicode-ident/pull/9/files
+ { allow = ["Unicode-DFS-2016"], name = "unicode-ident", version = "*"},
+]
+
+# Some crates don't have (easily) machine readable licensing information,
+# adding a clarification entry for it allows you to manually specify the
+# licensing information
+#[[licenses.clarify]]
+# The name of the crate the clarification applies to
+#name = "ring"
+# The optional version constraint for the crate
+#version = "*"
+# The SPDX expression for the license requirements of the crate
+#expression = "MIT AND ISC AND OpenSSL"
+# One or more files in the crate's source used as the "source of truth" for
+# the license expression. If the contents match, the clarification will be used
+# when running the license check, otherwise the clarification will be ignored
+# and the crate will be checked normally, which may produce warnings or errors
+# depending on the rest of your configuration
+#license-files = [
+ # Each entry is a crate relative path, and the (opaque) hash of its contents
+ #{ path = "LICENSE", hash = 0xbd0eed23 }
+#]
+
+[licenses.private]
+# If true, ignores workspace crates that aren't published, or are only
+# published to private registries
+ignore = true
+# One or more private registries that you might publish crates to, if a crate
+# is only published to private registries, and ignore is true, the crate will
+# not have its license(s) checked
+registries = [
+ #"https://sekretz.com/registry
+]
+
+# This section is considered when running `cargo deny check bans`.
+# More documentation about the 'bans' section can be found here:
+# https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html
+[bans]
+# Lint level for when multiple versions of the same crate are detected
+multiple-versions = "warn"
+# Lint level for when a crate version requirement is `*`
+wildcards = "allow"
+# The graph highlighting used when creating dotgraphs for crates
+# with multiple versions
+# * lowest-version - The path to the lowest versioned duplicate is highlighted
+# * simplest-path - The path to the version with the fewest edges is highlighted
+# * all - Both lowest-version and simplest-path are used
+highlight = "all"
+# List of crates to deny
+deny = [
+ # Each entry the name of a crate and a version range. If version is
+ # not specified, all versions will be matched.
+ #{ name = "ansi_term", version = "=0.11.0" },
+]
+# Certain crates/versions that will be skipped when doing duplicate detection.
+skip = [
+ #{ name = "ansi_term", version = "=0.11.0" },
+]
+# Similarly to `skip` allows you to skip certain crates during duplicate
+# detection. Unlike skip, it also includes the entire tree of transitive
+# dependencies starting at the specified crate, up to a certain depth, which is
+# by default infinite
+skip-tree = [
+ #{ name = "ansi_term", version = "=0.11.0", depth = 20 },
+]
+
+# This section is considered when running `cargo deny check sources`.
+# More documentation about the 'sources' section can be found here:
+# https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html
+[sources]
+# Lint level for what to happen when a crate from a crate registry that is not
+# in the allow list is encountered
+unknown-registry = "deny"
+# Lint level for what to happen when a crate from a git repository that is not
+# in the allow list is encountered
+unknown-git = "deny"
+# List of URLs for allowed crate registries. Defaults to the crates.io index
+# if not specified. If it is specified but empty, no registries are allowed.
+allow-registry = ["https://github.com/rust-lang/crates.io-index"]
+# List of URLs for allowed Git repositories
+allow-git = []
+
+#[sources.allow-org]
+# 1 or more github.com organizations to allow git sources for
+#github = [""]
+# 1 or more gitlab.com organizations to allow git sources for
+#gitlab = [""]
+# 1 or more bitbucket.org organizations to allow git sources for
+#bitbucket = [""]
diff --git a/examples/Cargo.toml b/examples/Cargo.toml
new file mode 100644
index 0000000..b697de7
--- /dev/null
+++ b/examples/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "examples"
+version = "0.0.0"
+publish = false
+edition = "2021"
+authors = ["Quinn Wilton "]
+
+[dev-dependencies]
+rhizome = { path = "../rhizome", version = "0.1" }
+
+[[example]]
+name = "counterparts"
+path = "counterparts.rs"
diff --git a/examples/counterparts.rs b/examples/counterparts.rs
new file mode 100644
index 0000000..7622550
--- /dev/null
+++ b/examples/counterparts.rs
@@ -0,0 +1,6 @@
+use std::error::Error;
+
+pub fn main() -> Result<(), Box> {
+ println!("Alien Shore!");
+ Ok(())
+}
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000..fc9379a
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,84 @@
+{
+ description = "rhizome";
+
+ inputs = {
+ nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
+ flake-utils.url = "github:numtide/flake-utils";
+
+ rust-overlay = {
+ url = "github:oxalica/rust-overlay";
+ inputs.nixpkgs.follows = "nixpkgs";
+ inputs.flake-utils.follows = "flake-utils";
+ };
+ };
+
+ outputs =
+ { self
+ , nixpkgs
+ , flake-utils
+ , rust-overlay
+ } @ inputs:
+ flake-utils.lib.eachDefaultSystem (system:
+ let
+ overlays = [ (import rust-overlay) ];
+ pkgs = import nixpkgs { inherit system overlays; };
+
+ rust-toolchain =
+ (pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml).override {
+ extensions = [ "cargo" "clippy" "rustfmt" "rust-src" "rust-std" ];
+ targets = [ "wasm32-unknown-unknown" ];
+ };
+
+ nightly-rustfmt = pkgs.rust-bin.nightly.latest.rustfmt;
+
+ format-pkgs = with pkgs; [
+ nixpkgs-fmt
+ ];
+
+ cargo-installs = with pkgs; [
+ binaryen
+ cargo-deny
+ cargo-expand
+ cargo-sort
+ cargo-udeps
+ cargo-watch
+ wasm-pack
+ wasm-bindgen-cli
+ ];
+ in
+ rec
+ {
+ devShells.default = pkgs.mkShell {
+ name = "rhizome";
+ nativeBuildInputs = with pkgs; [
+ # The ordering of these two items is important. For nightly rustfmt to be used instead of
+ # the rustfmt provided by `rust-toolchain`, it must appear first in the list. This is
+ # because native build inputs are added to $PATH in the order they're listed here.
+ nightly-rustfmt
+ rust-toolchain
+ pre-commit
+ direnv
+ self.packages.${system}.irust
+ ] ++ format-pkgs ++ cargo-installs;
+
+ shellHook = ''
+ [ -e .git/hooks/pre-commit ] || pre-commit install --install-hooks && pre-commit install --hook-type commit-msg
+ '';
+ };
+
+ packages.irust = pkgs.rustPlatform.buildRustPackage rec {
+ pname = "irust";
+ version = "1.65.1";
+ src = pkgs.fetchFromGitHub {
+ owner = "sigmaSd";
+ repo = "IRust";
+ rev = "v${version}";
+ sha256 = "sha256-AMOND5q1XzNhN5smVJp+2sGl/OqbxkGPGuPBCE48Hik=";
+ };
+
+ doCheck = false;
+ cargoSha256 = "sha256-A24O3p85mCRVZfDyyjQcQosj/4COGNnqiQK2a7nCP6I=";
+ };
+ }
+ );
+}
diff --git a/release-please-config.json b/release-please-config.json
new file mode 100644
index 0000000..02ff649
--- /dev/null
+++ b/release-please-config.json
@@ -0,0 +1,11 @@
+{
+ "plugins": ["cargo-workspace"],
+ "changelog-path": "CHANGELOG.md",
+ "release-type": "rust",
+ "bump-minor-pre-major": true,
+ "bump-patch-for-minor-pre-major": true,
+ "packages": {
+ "rhizome": {},
+ "rhizome-wasm": {}
+ }
+}
diff --git a/rhizome-benches/Cargo.toml b/rhizome-benches/Cargo.toml
new file mode 100644
index 0000000..c67149b
--- /dev/null
+++ b/rhizome-benches/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+name = "rhizome-benches"
+version = "0.0.0"
+publish = false
+edition = "2021"
+authors = ["Quinn Wilton "]
+
+[dependencies]
+rhizome = { path = "../rhizome", version = "0.1", features = ["test_utils"] }
+
+[dev-dependencies]
+criterion = { version = "0.4", default-features = false }
+
+[[bench]]
+name = "a_benchmark"
+harness = false
diff --git a/rhizome-benches/benches/a_benchmark.rs b/rhizome-benches/benches/a_benchmark.rs
new file mode 100644
index 0000000..432d1ec
--- /dev/null
+++ b/rhizome-benches/benches/a_benchmark.rs
@@ -0,0 +1,15 @@
+use criterion::{criterion_group, criterion_main, Criterion};
+
+pub fn add_benchmark(c: &mut Criterion) {
+ let mut rvg = rhizome::test_utils::Rvg::deterministic();
+ let int_val_1 = rvg.sample(&(0..100i32));
+ let int_val_2 = rvg.sample(&(0..100i32));
+
+ c.bench_function("add", |b| {
+ b.iter(|| {
+ rhizome::add(int_val_1, int_val_2);
+ })
+ });
+}
+criterion_group!(benches, add_benchmark);
+criterion_main!(benches);
diff --git a/rhizome-wasm/Cargo.toml b/rhizome-wasm/Cargo.toml
new file mode 100644
index 0000000..1cb9a22
--- /dev/null
+++ b/rhizome-wasm/Cargo.toml
@@ -0,0 +1,45 @@
+[package]
+name = "rhizome-wasm"
+version = "0.1.0"
+description = ""
+keywords = []
+categories = []
+include = ["/src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
+license = "Apache-2.0 or MIT"
+readme = "README.md"
+edition = "2021"
+rust-version = "1.64"
+documentation = "https://docs.rs/rhizome-wasm"
+repository = "https://github.com/QuinnWilton/rhizome/tree/main/rhizome-wasm"
+authors = ["Quinn Wilton "]
+
+[lib]
+crate-type = ["cdylib", "rlib"]
+path = "src/lib.rs"
+
+[dependencies]
+# The `console_error_panic_hook` crate provides better debugging of panics by
+# logging them with `console.error`. This is great for development, but requires
+# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
+# code size when deploying.
+console_error_panic_hook = { version = "0.1", optional = true }
+js-sys = { version = "0.3", optional = true }
+tracing = "0.1"
+wasm-bindgen = { version = "0.2", optional = true, features = ["serde-serialize"] }
+wasm-bindgen-futures = { version = "0.4", optional = true }
+web-sys = { version = "0.3", optional = true }
+rhizome = { path = "../rhizome", version = "0.1" }
+
+[dev-dependencies]
+wasm-bindgen-test = "0.3"
+
+[features]
+default = ["js"]
+full = ["js", "web"]
+js = [
+ "console_error_panic_hook",
+ "js-sys",
+ "wasm-bindgen",
+ "wasm-bindgen-futures"
+]
+web = ["web-sys"]
diff --git a/rhizome-wasm/README.md b/rhizome-wasm/README.md
new file mode 100644
index 0000000..8ddec07
--- /dev/null
+++ b/rhizome-wasm/README.md
@@ -0,0 +1,131 @@
+
+
+:warning: Work in progress :warning:
+
+##
+
+Description.
+
+## Outline
+
+- [Set-up](#set-up)
+- [Build for Javascript](#build-for-javascript)
+- [Testing the Project](#testing-the-project)
+- [Publishing a Package](#publishing-a-package)
+- [License](#license)
+
+## Set-up
+
+We'll use [`wasm-pack`][wasm-pack] for building, testing, and publishing
+our Wasm project.
+
+### Build for Javascript
+
+The `wasm-pack build` command will compile the code in this directory into
+Wasm and generate a `pkg` folder by default, containing the Wasm binary, a
+Javascript-wrapper file, the rhizome-wasm README (and version), and a
+`package.json` file.
+
+- Targetting node:
+
+ ```console
+ wasm-pack build --target nodejs
+ ```
+
+- Targetting browswers:
+
+ ```console
+ wasm-pack build --target web
+ ```
+
+- Targetting bundlers like [webpack][webpack]:
+
+ ```console
+ wasm-pack build --target bundler
+ ```
+
+## Testing the Project
+
+For running tests in the current directory, use one of these commands:
+
+- Run tests expected to execute in [Node.js][node-js]:
+
+```console
+wasm-pack test --node
+```
+
+- Run browser tests in a headless browwer:
+
+```console
+wasm-pack test --headless --firefox --chrome --safari
+```
+
+*Note*: Make sure you have the appropriate browser installed when running
+locally.
+
+## Publishing a Package
+
+Once you've [built the package](#build-for-javascript), which lives under
+`pkg` by default (or a sub-directory of your choosing), you can pack and
+publish it to [npm][npm] via (given credentials):
+
+```console
+wasm-pack publish
+```
+
+## License
+
+This project is licensed under either of
+
+- Apache License, Version 2.0, ([LICENSE-APACHE](./LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
+- MIT license ([LICENSE-MIT](./LICENSE-MIT) or http://opensource.org/licenses/MIT)
+
+at your option.
+
+### Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally
+submitted for inclusion in the work by you, as defined in the Apache-2.0
+license, shall be dual licensed as above, without any additional terms or
+conditions.
+
+
+[apache]: https://www.apache.org/licenses/LICENSE-2.0
+[mit]: http://opensource.org/licenses/MIT
+[node-js]: https://nodejs.dev/en/
+[npm]: https://www.npmjs.com/
+[wasm-pack]: https://rustwasm.github.io/docs/wasm-pack/
+[webpack]: https://webpack.js.org/
diff --git a/rhizome-wasm/src/lib.rs b/rhizome-wasm/src/lib.rs
new file mode 100644
index 0000000..1e76b0d
--- /dev/null
+++ b/rhizome-wasm/src/lib.rs
@@ -0,0 +1,55 @@
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![warn(missing_debug_implementations, missing_docs, rust_2018_idioms)]
+#![deny(unreachable_pub, private_in_public)]
+#![cfg(target_arch = "wasm32")]
+
+//! rhizome
+
+use wasm_bindgen::prelude::wasm_bindgen;
+
+/// Add two integers together.
+#[wasm_bindgen]
+pub fn add(a: i32, b: i32) -> i32 {
+ a + b
+}
+
+//------------------------------------------------------------------------------
+// Utilities
+//------------------------------------------------------------------------------
+
+/// Panic hook lets us get better error messages if our Rust code ever panics.
+///
+/// For more details see
+///
+#[wasm_bindgen(js_name = "setPanicHook")]
+pub fn set_panic_hook() {
+ #[cfg(feature = "console_error_panic_hook")]
+ console_error_panic_hook::set_once();
+}
+
+#[wasm_bindgen]
+extern "C" {
+ // For alerting
+ pub(crate) fn alert(s: &str);
+ // For logging in the console.
+ #[wasm_bindgen(js_namespace = console)]
+ pub fn log(s: &str);
+}
+
+//------------------------------------------------------------------------------
+// Macros
+//------------------------------------------------------------------------------
+
+/// Return a representation of an object owned by JS.
+#[macro_export]
+macro_rules! value {
+ ($value:expr) => {
+ wasm_bindgen::JsValue::from($value)
+ };
+}
+
+/// Calls the wasm_bindgen console.log.
+#[macro_export]
+macro_rules! console_log {
+ ($($t:tt)*) => ($crate::log(&format_args!($($t)*).to_string()))
+}
diff --git a/rhizome-wasm/tests/web.rs b/rhizome-wasm/tests/web.rs
new file mode 100644
index 0000000..5c07050
--- /dev/null
+++ b/rhizome-wasm/tests/web.rs
@@ -0,0 +1,10 @@
+//! Test suite for the Web and headless browsers.
+
+use wasm_bindgen_test::{wasm_bindgen_test, wasm_bindgen_test_configure};
+wasm_bindgen_test_configure!(run_in_browser);
+
+#[wasm_bindgen_test]
+fn test_add() {
+ assert_eq!(rhizome_wasm::add(3, 2), 5);
+ rhizome_wasm::console_log!("{}", "Test passes!");
+}
diff --git a/rhizome/.dockerignore b/rhizome/.dockerignore
new file mode 100644
index 0000000..b94f2b7
--- /dev/null
+++ b/rhizome/.dockerignore
@@ -0,0 +1,7 @@
+*
+
+!Cargo.lock
+!Cargo.toml
+!src
+
+src/bin
diff --git a/rhizome/Cargo.toml b/rhizome/Cargo.toml
new file mode 100644
index 0000000..01a251d
--- /dev/null
+++ b/rhizome/Cargo.toml
@@ -0,0 +1,26 @@
+[package]
+name = "rhizome"
+version = "0.1.0"
+description = ""
+keywords = []
+categories = []
+include = ["/src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
+license = "Apache-2.0 or MIT"
+readme = "README.md"
+edition = "2021"
+rust-version = "1.64"
+documentation = "https://docs.rs/rhizome"
+repository = "https://github.com/QuinnWilton/rhizome/tree/main/rhizome"
+authors = ["Quinn Wilton "]
+
+[lib]
+path = "src/lib.rs"
+
+[dependencies]
+anyhow = "1.0"
+proptest = { version = "1.0", optional = true }
+tracing = "0.1"
+
+[features]
+default = []
+test_utils = ["proptest"]
diff --git a/rhizome/LICENSE b/rhizome/LICENSE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/rhizome/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/rhizome/README.md b/rhizome/README.md
new file mode 100644
index 0000000..7da23f2
--- /dev/null
+++ b/rhizome/README.md
@@ -0,0 +1,57 @@
+
+
+:warning: Work in progress :warning:
+
+##
+
+Description.
+
+## License
+
+This project is licensed under either of
+
+- Apache License, Version 2.0, ([LICENSE-APACHE](./LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
+- MIT license ([LICENSE-MIT](./LICENSE-MIT) or http://opensource.org/licenses/MIT)
+
+at your option.
+
+### Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally
+submitted for inclusion in the work by you, as defined in the Apache-2.0
+license, shall be dual licensed as above, without any additional terms or
+conditions.
+
+
+[apache]: https://www.apache.org/licenses/LICENSE-2.0
+[mit]: http://opensource.org/licenses/MIT
diff --git a/rhizome/src/lib.rs b/rhizome/src/lib.rs
new file mode 100644
index 0000000..2fdca10
--- /dev/null
+++ b/rhizome/src/lib.rs
@@ -0,0 +1,30 @@
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![warn(missing_debug_implementations, missing_docs, rust_2018_idioms)]
+#![deny(unreachable_pub, private_in_public)]
+
+//! rhizome
+
+/// Test utilities.
+#[cfg(any(test, feature = "test_utils"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "test_utils")))]
+pub mod test_utils;
+
+/// Add two integers together.
+pub fn add(a: i32, b: i32) -> i32 {
+ a + b
+}
+
+/// Multiplies two integers together.
+pub fn mult(a: i32, b: i32) -> i32 {
+ a * b
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_mult() {
+ assert_eq!(mult(3, 2), 6);
+ }
+}
diff --git a/rhizome/src/test_utils/mod.rs b/rhizome/src/test_utils/mod.rs
new file mode 100644
index 0000000..72277df
--- /dev/null
+++ b/rhizome/src/test_utils/mod.rs
@@ -0,0 +1,4 @@
+/// Random value generator for sampling data.
+mod rvg;
+
+pub use rvg::*;
diff --git a/rhizome/src/test_utils/rvg.rs b/rhizome/src/test_utils/rvg.rs
new file mode 100644
index 0000000..72cd795
--- /dev/null
+++ b/rhizome/src/test_utils/rvg.rs
@@ -0,0 +1,63 @@
+use proptest::{
+ collection::vec,
+ strategy::{Strategy, ValueTree},
+ test_runner::{Config, TestRunner},
+};
+
+/// A random value generator (RVG), which, given proptest strategies, will
+/// generate random values based on those strategies.
+#[derive(Debug, Default)]
+pub struct Rvg {
+ runner: TestRunner,
+}
+
+impl Rvg {
+ /// Creates a new RVG with the default random number generator.
+ pub fn new() -> Self {
+ Rvg {
+ runner: TestRunner::new(Config::default()),
+ }
+ }
+
+ /// Creates a new RVG with a deterministic random number generator,
+ /// using the same seed across test runs.
+ pub fn deterministic() -> Self {
+ Rvg {
+ runner: TestRunner::deterministic(),
+ }
+ }
+
+ /// Samples a value for the given strategy.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use rhizome::test_utils::Rvg;
+ ///
+ /// let mut rvg = Rvg::new();
+ /// let int = rvg.sample(&(0..100i32));
+ /// ```
+ pub fn sample(&mut self, strategy: &S) -> S::Value {
+ strategy
+ .new_tree(&mut self.runner)
+ .expect("No value can be generated")
+ .current()
+ }
+
+ /// Samples a vec of some length with a value for the given strategy.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use rhizome::test_utils::Rvg;
+ ///
+ /// let mut rvg = Rvg::new();
+ /// let ints = rvg.sample_vec(&(0..100i32), 10);
+ /// ```
+ pub fn sample_vec(&mut self, strategy: &S, len: usize) -> Vec {
+ vec(strategy, len..=len)
+ .new_tree(&mut self.runner)
+ .expect("No value can be generated")
+ .current()
+ }
+}
diff --git a/rhizome/tests/integration_test.rs b/rhizome/tests/integration_test.rs
new file mode 100644
index 0000000..e6b7f2f
--- /dev/null
+++ b/rhizome/tests/integration_test.rs
@@ -0,0 +1,4 @@
+#[test]
+fn test_add() {
+ assert_eq!(rhizome::add(3, 2), 5);
+}
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
new file mode 100644
index 0000000..292fe49
--- /dev/null
+++ b/rust-toolchain.toml
@@ -0,0 +1,2 @@
+[toolchain]
+channel = "stable"