├── .cargo └── config.toml ├── .editorconfig ├── .github ├── semantic.yml └── workflows │ └── ci.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── licenserc.toml ├── rust-toolchain.toml ├── rustfmt.toml ├── taplo.toml ├── template ├── Cargo.toml └── src │ └── lib.rs ├── typos.toml └── xtask ├── Cargo.toml └── src └── main.rs /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2025 FastLabs Developers 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | [alias] 16 | x = "run --package x --" 17 | 18 | [env] 19 | CARGO_WORKSPACE_DIR = { value = "", relative = true } 20 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | indent_style = space 6 | insert_final_newline = true 7 | trim_trailing_whitespace = true 8 | 9 | [*.toml] 10 | indent_size = tab 11 | tab_width = 2 12 | -------------------------------------------------------------------------------- /.github/semantic.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2025 FastLabs Developers 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # The pull request's title should be fulfilled the following pattern: 16 | # 17 | # [optional scope]: 18 | # 19 | # ... where valid types and scopes can be found below; for example: 20 | # 21 | # build(maven): One level down for native profile 22 | # 23 | # More about configurations on https://github.com/Ezard/semantic-prs#configuration 24 | 25 | enabled: true 26 | 27 | titleOnly: true 28 | 29 | types: 30 | - feat 31 | - fix 32 | - docs 33 | - style 34 | - refactor 35 | - perf 36 | - test 37 | - build 38 | - ci 39 | - chore 40 | - revert 41 | 42 | targetUrl: https://github.com/fast/template/blob/main/.github/semantic.yml 43 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2025 FastLabs Developers 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | name: CI 16 | on: 17 | pull_request: 18 | branches: [ main ] 19 | push: 20 | branches: [ main ] 21 | 22 | # Concurrency strategy: 23 | # github.workflow: distinguish this workflow from others 24 | # github.event_name: distinguish `push` event from `pull_request` event 25 | # github.event.number: set to the number of the pull request if `pull_request` event 26 | # github.run_id: otherwise, it's a `push` event, only cancel if we rerun the workflow 27 | # 28 | # Reference: 29 | # https://docs.github.com/en/actions/using-jobs/using-concurrency 30 | # https://docs.github.com/en/actions/learn-github-actions/contexts#github-context 31 | concurrency: 32 | group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event.number || github.run_id }} 33 | cancel-in-progress: true 34 | 35 | jobs: 36 | check: 37 | name: Check 38 | runs-on: ubuntu-22.04 39 | steps: 40 | - uses: actions/checkout@v4 41 | - name: Install toolchain 42 | uses: dtolnay/rust-toolchain@nightly 43 | with: 44 | components: rustfmt,clippy 45 | - uses: Swatinem/rust-cache@v2 46 | - uses: taiki-e/install-action@v2 47 | with: 48 | tool: typos-cli,taplo-cli,hawkeye 49 | - run: cargo +nightly x lint 50 | 51 | test: 52 | name: Run tests 53 | strategy: 54 | matrix: 55 | os: [ ubuntu-22.04, macos-14, windows-2022 ] 56 | rust-version: [ "1.80.0", "stable" ] 57 | runs-on: ${{ matrix.os }} 58 | steps: 59 | - uses: actions/checkout@v4 60 | - uses: Swatinem/rust-cache@v2 61 | - name: Delete rust-toolchain.toml 62 | run: rm rust-toolchain.toml 63 | - name: Install toolchain 64 | uses: dtolnay/rust-toolchain@master 65 | with: 66 | toolchain: ${{ matrix.rust-version }} 67 | - name: Run unit tests 68 | run: cargo x test --no-capture 69 | shell: bash 70 | 71 | required: 72 | name: Required 73 | runs-on: ubuntu-22.04 74 | if: ${{ always() }} 75 | needs: 76 | - check 77 | - test 78 | steps: 79 | - name: Guardian 80 | run: | 81 | if [[ ! ( \ 82 | "${{ needs.check.result }}" == "success" \ 83 | && "${{ needs.test.result }}" == "success" \ 84 | ) ]]; then 85 | echo "Required jobs haven't been completed successfully." 86 | exit -1 87 | fi 88 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "anstream" 7 | version = "0.6.18" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" 10 | dependencies = [ 11 | "anstyle", 12 | "anstyle-parse", 13 | "anstyle-query", 14 | "anstyle-wincon", 15 | "colorchoice", 16 | "is_terminal_polyfill", 17 | "utf8parse", 18 | ] 19 | 20 | [[package]] 21 | name = "anstyle" 22 | version = "1.0.10" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" 25 | 26 | [[package]] 27 | name = "anstyle-parse" 28 | version = "0.2.6" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" 31 | dependencies = [ 32 | "utf8parse", 33 | ] 34 | 35 | [[package]] 36 | name = "anstyle-query" 37 | version = "1.1.2" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" 40 | dependencies = [ 41 | "windows-sys", 42 | ] 43 | 44 | [[package]] 45 | name = "anstyle-wincon" 46 | version = "3.0.6" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" 49 | dependencies = [ 50 | "anstyle", 51 | "windows-sys", 52 | ] 53 | 54 | [[package]] 55 | name = "bitflags" 56 | version = "2.6.0" 57 | source = "registry+https://github.com/rust-lang/crates.io-index" 58 | checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" 59 | 60 | [[package]] 61 | name = "clap" 62 | version = "4.5.23" 63 | source = "registry+https://github.com/rust-lang/crates.io-index" 64 | checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" 65 | dependencies = [ 66 | "clap_builder", 67 | "clap_derive", 68 | ] 69 | 70 | [[package]] 71 | name = "clap_builder" 72 | version = "4.5.23" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" 75 | dependencies = [ 76 | "anstream", 77 | "anstyle", 78 | "clap_lex", 79 | "strsim", 80 | ] 81 | 82 | [[package]] 83 | name = "clap_derive" 84 | version = "4.5.18" 85 | source = "registry+https://github.com/rust-lang/crates.io-index" 86 | checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" 87 | dependencies = [ 88 | "heck", 89 | "proc-macro2", 90 | "quote", 91 | "syn", 92 | ] 93 | 94 | [[package]] 95 | name = "clap_lex" 96 | version = "0.7.4" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" 99 | 100 | [[package]] 101 | name = "colorchoice" 102 | version = "1.0.3" 103 | source = "registry+https://github.com/rust-lang/crates.io-index" 104 | checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" 105 | 106 | [[package]] 107 | name = "either" 108 | version = "1.13.0" 109 | source = "registry+https://github.com/rust-lang/crates.io-index" 110 | checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" 111 | 112 | [[package]] 113 | name = "env_home" 114 | version = "0.1.0" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" 117 | 118 | [[package]] 119 | name = "errno" 120 | version = "0.3.10" 121 | source = "registry+https://github.com/rust-lang/crates.io-index" 122 | checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" 123 | dependencies = [ 124 | "libc", 125 | "windows-sys", 126 | ] 127 | 128 | [[package]] 129 | name = "heck" 130 | version = "0.5.0" 131 | source = "registry+https://github.com/rust-lang/crates.io-index" 132 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 133 | 134 | [[package]] 135 | name = "is_terminal_polyfill" 136 | version = "1.70.1" 137 | source = "registry+https://github.com/rust-lang/crates.io-index" 138 | checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" 139 | 140 | [[package]] 141 | name = "libc" 142 | version = "0.2.169" 143 | source = "registry+https://github.com/rust-lang/crates.io-index" 144 | checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" 145 | 146 | [[package]] 147 | name = "linux-raw-sys" 148 | version = "0.4.14" 149 | source = "registry+https://github.com/rust-lang/crates.io-index" 150 | checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" 151 | 152 | [[package]] 153 | name = "proc-macro2" 154 | version = "1.0.92" 155 | source = "registry+https://github.com/rust-lang/crates.io-index" 156 | checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" 157 | dependencies = [ 158 | "unicode-ident", 159 | ] 160 | 161 | [[package]] 162 | name = "quote" 163 | version = "1.0.38" 164 | source = "registry+https://github.com/rust-lang/crates.io-index" 165 | checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" 166 | dependencies = [ 167 | "proc-macro2", 168 | ] 169 | 170 | [[package]] 171 | name = "rustix" 172 | version = "0.38.42" 173 | source = "registry+https://github.com/rust-lang/crates.io-index" 174 | checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" 175 | dependencies = [ 176 | "bitflags", 177 | "errno", 178 | "libc", 179 | "linux-raw-sys", 180 | "windows-sys", 181 | ] 182 | 183 | [[package]] 184 | name = "strsim" 185 | version = "0.11.1" 186 | source = "registry+https://github.com/rust-lang/crates.io-index" 187 | checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 188 | 189 | [[package]] 190 | name = "syn" 191 | version = "2.0.95" 192 | source = "registry+https://github.com/rust-lang/crates.io-index" 193 | checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a" 194 | dependencies = [ 195 | "proc-macro2", 196 | "quote", 197 | "unicode-ident", 198 | ] 199 | 200 | [[package]] 201 | name = "template" 202 | version = "0.1.0" 203 | 204 | [[package]] 205 | name = "unicode-ident" 206 | version = "1.0.14" 207 | source = "registry+https://github.com/rust-lang/crates.io-index" 208 | checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" 209 | 210 | [[package]] 211 | name = "utf8parse" 212 | version = "0.2.2" 213 | source = "registry+https://github.com/rust-lang/crates.io-index" 214 | checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" 215 | 216 | [[package]] 217 | name = "which" 218 | version = "7.0.1" 219 | source = "registry+https://github.com/rust-lang/crates.io-index" 220 | checksum = "fb4a9e33648339dc1642b0e36e21b3385e6148e289226f657c809dee59df5028" 221 | dependencies = [ 222 | "either", 223 | "env_home", 224 | "rustix", 225 | "winsafe", 226 | ] 227 | 228 | [[package]] 229 | name = "windows-sys" 230 | version = "0.59.0" 231 | source = "registry+https://github.com/rust-lang/crates.io-index" 232 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 233 | dependencies = [ 234 | "windows-targets", 235 | ] 236 | 237 | [[package]] 238 | name = "windows-targets" 239 | version = "0.52.6" 240 | source = "registry+https://github.com/rust-lang/crates.io-index" 241 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 242 | dependencies = [ 243 | "windows_aarch64_gnullvm", 244 | "windows_aarch64_msvc", 245 | "windows_i686_gnu", 246 | "windows_i686_gnullvm", 247 | "windows_i686_msvc", 248 | "windows_x86_64_gnu", 249 | "windows_x86_64_gnullvm", 250 | "windows_x86_64_msvc", 251 | ] 252 | 253 | [[package]] 254 | name = "windows_aarch64_gnullvm" 255 | version = "0.52.6" 256 | source = "registry+https://github.com/rust-lang/crates.io-index" 257 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 258 | 259 | [[package]] 260 | name = "windows_aarch64_msvc" 261 | version = "0.52.6" 262 | source = "registry+https://github.com/rust-lang/crates.io-index" 263 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 264 | 265 | [[package]] 266 | name = "windows_i686_gnu" 267 | version = "0.52.6" 268 | source = "registry+https://github.com/rust-lang/crates.io-index" 269 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 270 | 271 | [[package]] 272 | name = "windows_i686_gnullvm" 273 | version = "0.52.6" 274 | source = "registry+https://github.com/rust-lang/crates.io-index" 275 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 276 | 277 | [[package]] 278 | name = "windows_i686_msvc" 279 | version = "0.52.6" 280 | source = "registry+https://github.com/rust-lang/crates.io-index" 281 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 282 | 283 | [[package]] 284 | name = "windows_x86_64_gnu" 285 | version = "0.52.6" 286 | source = "registry+https://github.com/rust-lang/crates.io-index" 287 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 288 | 289 | [[package]] 290 | name = "windows_x86_64_gnullvm" 291 | version = "0.52.6" 292 | source = "registry+https://github.com/rust-lang/crates.io-index" 293 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 294 | 295 | [[package]] 296 | name = "windows_x86_64_msvc" 297 | version = "0.52.6" 298 | source = "registry+https://github.com/rust-lang/crates.io-index" 299 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 300 | 301 | [[package]] 302 | name = "winsafe" 303 | version = "0.0.19" 304 | source = "registry+https://github.com/rust-lang/crates.io-index" 305 | checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" 306 | 307 | [[package]] 308 | name = "x" 309 | version = "0.0.0" 310 | dependencies = [ 311 | "clap", 312 | "which", 313 | ] 314 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2025 FastLabs Developers 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | [workspace] 16 | members = ["template", "xtask"] 17 | resolver = "2" 18 | 19 | [workspace.package] 20 | edition = "2021" 21 | homepage = "https://github.com/fast/template" 22 | license = "Apache-2.0" 23 | readme = "README.md" 24 | repository = "https://github.com/fast/template" 25 | rust-version = "1.80.0" 26 | 27 | [workspace.lints.rust] 28 | unknown_lints = "deny" 29 | 30 | [workspace.lints.clippy] 31 | dbg_macro = "deny" 32 | 33 | [workspace.metadata.release] 34 | pre-release-commit-message = "chore: release v{{version}}" 35 | shared-version = true 36 | sign-tag = true 37 | tag-name = "v{{version}}" 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Fast template for developing a new Rust project 2 | 3 | Use this repository as a GitHub template to quickly start a new Rust project. 4 | 5 | ## License 6 | 7 | This project is licensed under [Apache License, Version 2.0](LICENSE). 8 | -------------------------------------------------------------------------------- /licenserc.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2025 FastLabs Developers 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | headerPath = "Apache-2.0.txt" 16 | 17 | includes = ['**/*.proto', '**/*.rs', '**/*.yml', '**/*.yaml', '**/*.toml'] 18 | 19 | [properties] 20 | copyrightOwner = "FastLabs Developers" 21 | inceptionYear = 2025 22 | -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2025 FastLabs Developers 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | [toolchain] 16 | channel = "stable" 17 | components = ["cargo", "rustfmt", "clippy", "rust-analyzer"] 18 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2025 FastLabs Developers 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | comment_width = 120 16 | format_code_in_doc_comments = true 17 | group_imports = "StdExternalCrate" 18 | imports_granularity = "Item" 19 | wrap_comments = true 20 | -------------------------------------------------------------------------------- /taplo.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2025 FastLabs Developers 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | include = ["Cargo.toml", "**/*.toml"] 16 | 17 | [formatting] 18 | # Align consecutive entries vertically. 19 | align_entries = false 20 | # Append trailing commas for multi-line arrays. 21 | array_trailing_comma = true 22 | # Expand arrays to multiple lines that exceed the maximum column width. 23 | array_auto_expand = true 24 | # Collapse arrays that don't exceed the maximum column width and don't contain comments. 25 | array_auto_collapse = true 26 | # Omit white space padding from single-line arrays 27 | compact_arrays = true 28 | # Omit white space padding from the start and end of inline tables. 29 | compact_inline_tables = false 30 | # Maximum column width in characters, affects array expansion and collapse, this doesn't take whitespace into account. 31 | # Note that this is not set in stone, and works on a best-effort basis. 32 | column_width = 80 33 | # Indent based on tables and arrays of tables and their subtables, subtables out of order are not indented. 34 | indent_tables = false 35 | # The substring that is used for indentation, should be tabs or spaces (but technically can be anything). 36 | indent_string = ' ' 37 | # Add trailing newline at the end of the file if not present. 38 | trailing_newline = true 39 | # Alphabetically reorder keys that are not separated by empty lines. 40 | reorder_keys = true 41 | # Maximum amount of allowed consecutive blank lines. This does not affect the whitespace at the end of the document, as it is always stripped. 42 | allowed_blank_lines = 1 43 | # Use CRLF for line endings. 44 | crlf = false 45 | -------------------------------------------------------------------------------- /template/Cargo.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2025 FastLabs Developers 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | [package] 16 | name = "template" 17 | version = "0.1.0" 18 | 19 | edition.workspace = true 20 | homepage.workspace = true 21 | license.workspace = true 22 | readme.workspace = true 23 | repository.workspace = true 24 | rust-version.workspace = true 25 | 26 | [dependencies] 27 | 28 | [lints] 29 | workspace = true 30 | -------------------------------------------------------------------------------- /template/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2025 FastLabs Developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | pub fn hello() { 16 | println!("Hello, world!"); 17 | } 18 | -------------------------------------------------------------------------------- /typos.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2025 FastLabs Developers 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | [default.extend-words] 16 | 17 | [files] 18 | extend-exclude = [] 19 | -------------------------------------------------------------------------------- /xtask/Cargo.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2025 FastLabs Developers 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | [package] 16 | name = "x" 17 | publish = false 18 | 19 | edition.workspace = true 20 | homepage.workspace = true 21 | license.workspace = true 22 | readme.workspace = true 23 | repository.workspace = true 24 | rust-version.workspace = true 25 | 26 | [package.metadata.release] 27 | release = false 28 | 29 | [dependencies] 30 | clap = { version = "4.5.23", features = ["derive"] } 31 | which = { version = "7.0.1" } 32 | 33 | [lints] 34 | workspace = true 35 | -------------------------------------------------------------------------------- /xtask/src/main.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2025 FastLabs Developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use std::process::Command as StdCommand; 16 | 17 | use clap::Parser; 18 | use clap::Subcommand; 19 | 20 | #[derive(Parser)] 21 | struct Command { 22 | #[clap(subcommand)] 23 | sub: SubCommand, 24 | } 25 | 26 | impl Command { 27 | fn run(self) { 28 | match self.sub { 29 | SubCommand::Build(cmd) => cmd.run(), 30 | SubCommand::Lint(cmd) => cmd.run(), 31 | SubCommand::Test(cmd) => cmd.run(), 32 | } 33 | } 34 | } 35 | 36 | #[derive(Subcommand)] 37 | enum SubCommand { 38 | #[clap(about = "Compile workspace packages.")] 39 | Build(CommandBuild), 40 | #[clap(about = "Run format and clippy checks.")] 41 | Lint(CommandLint), 42 | #[clap(about = "Run unit tests.")] 43 | Test(CommandTest), 44 | } 45 | 46 | #[derive(Parser)] 47 | struct CommandBuild { 48 | #[arg(long, help = "Assert that `Cargo.lock` will remain unchanged.")] 49 | locked: bool, 50 | } 51 | 52 | impl CommandBuild { 53 | fn run(self) { 54 | run_command(make_build_cmd(self.locked)); 55 | } 56 | } 57 | 58 | #[derive(Parser)] 59 | struct CommandTest { 60 | #[arg(long, help = "Run tests serially and do not capture output.")] 61 | no_capture: bool, 62 | } 63 | 64 | impl CommandTest { 65 | fn run(self) { 66 | run_command(make_test_cmd(self.no_capture, true, &[])); 67 | } 68 | } 69 | 70 | #[derive(Parser)] 71 | #[clap(name = "lint")] 72 | struct CommandLint { 73 | #[arg(long, help = "Automatically apply lint suggestions.")] 74 | fix: bool, 75 | } 76 | 77 | impl CommandLint { 78 | fn run(self) { 79 | run_command(make_clippy_cmd(self.fix)); 80 | run_command(make_format_cmd(self.fix)); 81 | run_command(make_taplo_cmd(self.fix)); 82 | run_command(make_typos_cmd()); 83 | run_command(make_hawkeye_cmd(self.fix)); 84 | } 85 | } 86 | 87 | fn find_command(cmd: &str) -> StdCommand { 88 | match which::which(cmd) { 89 | Ok(exe) => { 90 | let mut cmd = StdCommand::new(exe); 91 | cmd.current_dir(env!("CARGO_WORKSPACE_DIR")); 92 | cmd 93 | } 94 | Err(err) => { 95 | panic!("{cmd} not found: {err}"); 96 | } 97 | } 98 | } 99 | 100 | fn ensure_installed(bin: &str, crate_name: &str) { 101 | if which::which(bin).is_err() { 102 | let mut cmd = find_command("cargo"); 103 | cmd.args(["install", crate_name]); 104 | run_command(cmd); 105 | } 106 | } 107 | 108 | fn run_command(mut cmd: StdCommand) { 109 | println!("{cmd:?}"); 110 | let status = cmd.status().expect("failed to execute process"); 111 | assert!(status.success(), "command failed: {status}"); 112 | } 113 | 114 | fn make_build_cmd(locked: bool) -> StdCommand { 115 | let mut cmd = find_command("cargo"); 116 | cmd.args([ 117 | "build", 118 | "--workspace", 119 | "--all-features", 120 | "--tests", 121 | "--examples", 122 | "--benches", 123 | "--bins", 124 | ]); 125 | if locked { 126 | cmd.arg("--locked"); 127 | } 128 | cmd 129 | } 130 | 131 | fn make_test_cmd(no_capture: bool, default_features: bool, features: &[&str]) -> StdCommand { 132 | let mut cmd = find_command("cargo"); 133 | cmd.args(["test", "--workspace"]); 134 | if !default_features { 135 | cmd.arg("--no-default-features"); 136 | } 137 | if !features.is_empty() { 138 | cmd.args(["--features", features.join(",").as_str()]); 139 | } 140 | if no_capture { 141 | cmd.args(["--", "--nocapture"]); 142 | } 143 | cmd 144 | } 145 | 146 | fn make_format_cmd(fix: bool) -> StdCommand { 147 | let mut cmd = find_command("cargo"); 148 | cmd.args(["fmt", "--all"]); 149 | if !fix { 150 | cmd.arg("--check"); 151 | } 152 | cmd 153 | } 154 | 155 | fn make_clippy_cmd(fix: bool) -> StdCommand { 156 | let mut cmd = find_command("cargo"); 157 | cmd.args([ 158 | "clippy", 159 | "--tests", 160 | "--all-features", 161 | "--all-targets", 162 | "--workspace", 163 | ]); 164 | if fix { 165 | cmd.args(["--allow-staged", "--allow-dirty", "--fix"]); 166 | } else { 167 | cmd.args(["--", "-D", "warnings"]); 168 | } 169 | cmd 170 | } 171 | 172 | fn make_hawkeye_cmd(fix: bool) -> StdCommand { 173 | ensure_installed("hawkeye", "hawkeye"); 174 | let mut cmd = find_command("hawkeye"); 175 | if fix { 176 | cmd.args(["format", "--fail-if-updated=false"]); 177 | } else { 178 | cmd.args(["check"]); 179 | } 180 | cmd 181 | } 182 | 183 | fn make_typos_cmd() -> StdCommand { 184 | ensure_installed("typos", "typos-cli"); 185 | find_command("typos") 186 | } 187 | 188 | fn make_taplo_cmd(fix: bool) -> StdCommand { 189 | ensure_installed("taplo", "taplo-cli"); 190 | let mut cmd = find_command("taplo"); 191 | if fix { 192 | cmd.args(["format"]); 193 | } else { 194 | cmd.args(["format", "--check"]); 195 | } 196 | cmd 197 | } 198 | 199 | fn main() { 200 | let cmd = Command::parse(); 201 | cmd.run() 202 | } 203 | --------------------------------------------------------------------------------