From c9b676b3716eb5e81f3ebd067ad58d1e33ab18ee Mon Sep 17 00:00:00 2001 From: Andrew Gazelka Date: Fri, 17 Jan 2025 18:43:44 -0800 Subject: [PATCH] initial commit --- .github/workflows/build.yml | 141 +++++++ .gitignore | 1 + Cargo.lock | 552 ++++++++++++++++++++++++++ Cargo.toml | 14 + README.md | 0 clippy.toml | 3 + crates/smart-cache-macro/Cargo.toml | 21 + crates/smart-cache-macro/src/lib.rs | 110 +++++ crates/smart-cache/Cargo.toml | 21 + crates/smart-cache/src/lib.rs | 68 ++++ crates/smart-cache/tests/something.rs | 16 + deny.toml | 52 +++ rustfmt.toml | 21 + 13 files changed, 1020 insertions(+) create mode 100644 .github/workflows/build.yml create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 README.md create mode 100644 clippy.toml create mode 100644 crates/smart-cache-macro/Cargo.toml create mode 100644 crates/smart-cache-macro/src/lib.rs create mode 100644 crates/smart-cache/Cargo.toml create mode 100644 crates/smart-cache/src/lib.rs create mode 100644 crates/smart-cache/tests/something.rs create mode 100644 deny.toml create mode 100644 rustfmt.toml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..0b6280d --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,141 @@ +name: Build + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + merge_group: + branches: [ main ] + +env: + CARGO_TERM_COLOR: always + RUST_TOOLCHAIN: nightly-2024-05-06 + +jobs: + machete: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install cargo-machete + uses: taiki-e/install-action@v2 + with: + tool: cargo-machete + + - name: Run cargo machete + run: | + cargo machete + + test: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ env.RUST_TOOLCHAIN }} + + - uses: Swatinem/rust-cache@v2 + with: + cache-on-failure: true + + - name: Run cargo test + run: | + cargo test --workspace --all-features + + deny: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install cargo-deny + uses: taiki-e/install-action@v2 + with: + tool: cargo-deny + + - name: Run cargo deny + run: | + cargo deny check -D warnings + + fmt: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - uses: dtolnay/rust-toolchain@master + with: + components: rustfmt + toolchain: ${{ env.RUST_TOOLCHAIN }} + + - name: Run rustfmt + run: | + cargo fmt --all -- --check + + docs: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ env.RUST_TOOLCHAIN }} + + - uses: Swatinem/rust-cache@v2 + with: + cache-on-failure: true + - name: Run cargo doc + run: | + cargo doc --workspace --no-deps --all-features + env: + RUSTDOCFLAGS: -D warnings + + clippy: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Rust toolchain + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ env.RUST_TOOLCHAIN }} + components: clippy + + - uses: Swatinem/rust-cache@v2 + with: + cache-on-failure: true + + - name: Clippy check + run: cargo clippy --workspace --benches --tests --examples --all-features -- -D warnings + + clippy-macos: + runs-on: macos-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Rust toolchain and cache + uses: dtolnay/rust-toolchain@master + with: + components: clippy + toolchain: ${{ env.RUST_TOOLCHAIN }} + + + - uses: Swatinem/rust-cache@v2 + with: + cache-on-failure: true + + - name: Clippy check + run: cargo clippy --workspace --benches --tests --examples --all-features -- -D warnings diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..681a94e --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,552 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "bitflags" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" + +[[package]] +name = "block-buffer" +version = "0.11.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fd016a0ddc7cb13661bf5576073ce07330a693f8608a1320b4e20561cc12cdc" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "bytecheck" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50c8f430744b23b54ad15161fcbc22d82a29b73eacbe425fea23ec822600bc6f" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "rancor", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523363cbe1df49b68215efdf500b103ac3b0fb4836aed6d15689a076eadb8fff" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "bytes" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "const-oid" +version = "0.10.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ff6be19477a1bd5441f382916a89bc2a0b2c35db6d41e0f6e8538bf6d6463f" + +[[package]] +name = "cpufeatures" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.2.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0b8ce8218c97789f16356e7896b3714f26c2ee1079b79c0b7ae7064bb9089fa" +dependencies = [ + "getrandom", + "hybrid-array", + "rand_core", +] + +[[package]] +name = "digest" +version = "0.11.0-pre.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf2e3d6615d99707295a9673e889bf363a04b2a466bd320c65a72536f7577379" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", +] + +[[package]] +name = "dirs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + +[[package]] +name = "hybrid-array" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2d35805454dc9f8662a98d6d61886ffe26bd465f5960e0e55345c70d5c0d2a9" +dependencies = [ + "typenum", +] + +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + +[[package]] +name = "indexmap" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags", + "libc", +] + +[[package]] +name = "munge" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64142d38c84badf60abf06ff9bd80ad2174306a5b11bd4706535090a30a419df" +dependencies = [ + "munge_macro", +] + +[[package]] +name = "munge_macro" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bb5c1d8184f13f7d0ccbeeca0def2f9a181bce2624302793005f5ca8aa62e5e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "proc-macro2" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "ptr_meta" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe9e76f66d3f9606f44e45598d155cb13ecf09f4a28199e48daf8c8fc937ea90" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca414edb151b4c8d125c12566ab0d74dc9cdba36fb80eb7b848c15f495fd32d1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "quote" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rancor" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf5f7161924b9d1cea0e4cabc97c372cea92b5f927fc13c6bca67157a0ad947" +dependencies = [ + "ptr_meta", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redb" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea0a72cd7140de9fc3e318823b883abf819c20d478ec89ce880466dc2ef263c6" +dependencies = [ + "libc", +] + +[[package]] +name = "redox_users" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[package]] +name = "rend" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a35e8a6bf28cd121053a66aa2e6a2e3eaffad4a60012179f0e864aa5ffeff215" +dependencies = [ + "bytecheck", +] + +[[package]] +name = "rkyv" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b11a153aec4a6ab60795f8ebe2923c597b16b05bb1504377451e705ef1a45323" +dependencies = [ + "bytecheck", + "bytes", + "hashbrown", + "indexmap", + "munge", + "ptr_meta", + "rancor", + "rend", + "rkyv_derive", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "beb382a4d9f53bd5c0be86b10d8179c3f8a14c30bf774ff77096ed6581e35981" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sha2" +version = "0.11.0-pre.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "540c0893cce56cdbcfebcec191ec8e0f470dd1889b6e7a0b503e310a94a168f5" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] +name = "smart-cache" +version = "0.1.0" +dependencies = [ + "dirs", + "eyre", + "once_cell", + "redb", + "rkyv", + "smart-cache-macro", + "tracing", +] + +[[package]] +name = "smart-cache-macro" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "sha2", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tinyvec" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +dependencies = [ + "once_cell", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "uuid" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "744018581f9a3454a9e15beb8a33b017183f1e7c0cd170232a2d1453b23a51c4" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..c6b6fa1 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,14 @@ +[workspace] +members = ["crates/*"] +resolver = "2" + +[workspace.lints.rust] +rust_2018_idioms = { level = "deny", priority = -1 } + +[workspace.lints.clippy] +complexity = { level = "deny", priority = -1 } +nursery = { level = "deny", priority = -1 } +pedantic = { level = "deny", priority = -1 } +perf = { level = "deny", priority = -1 } +style = { level = "deny", priority = -1 } +suspicious = { level = "deny", priority = -1 } diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/clippy.toml b/clippy.toml new file mode 100644 index 0000000..5ad7f93 --- /dev/null +++ b/clippy.toml @@ -0,0 +1,3 @@ +# https://doc.rust-lang.org/nightly/clippy/lint_configuration.html +cognitive-complexity-threshold = 5 +excessive-nesting-threshold = 4 diff --git a/crates/smart-cache-macro/Cargo.toml b/crates/smart-cache-macro/Cargo.toml new file mode 100644 index 0000000..3b61ea6 --- /dev/null +++ b/crates/smart-cache-macro/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "smart-cache-macro" +version = "0.1.0" +edition = "2021" +authors = ["Andrew Gazelka "] +description = "Procedural macros for smart-cache" +license = "MIT OR Apache-2.0" +repository = "https://github.com/andrewgazelka/smart-cache" +documentation = "https://docs.rs/smart-cache-macro" +readme = "../../README.md" +keywords = ["cache", "macro", "proc-macro"] +categories = ["caching", "development-tools"] + +[lib] +proc-macro = true + +[dependencies] +quote = "1.0" +syn = { version = "2.0", features = ["full"] } +proc-macro2 = "1.0" +sha2 = "0.11.0-pre.4" diff --git a/crates/smart-cache-macro/src/lib.rs b/crates/smart-cache-macro/src/lib.rs new file mode 100644 index 0000000..82d57ae --- /dev/null +++ b/crates/smart-cache-macro/src/lib.rs @@ -0,0 +1,110 @@ +use proc_macro::TokenStream; +use proc_macro2::Span; +use quote::quote; +use sha2::{Digest, Sha256}; +use syn::{parse_macro_input, FnArg, Ident, ItemFn, Pat, ReturnType}; + +fn hash_token_stream(tokens: &proc_macro2::TokenStream) -> [u8; 32] { + // Convert TokenStream to a string representation + let token_string = tokens.to_string(); + + // Create a new SHA-256 hasher + let mut hasher = Sha256::new(); + + // Update hasher with token string bytes + hasher.update(token_string.as_bytes()); + + // Finalize and return the hash as bytes + hasher.finalize().into() +} + +#[proc_macro_attribute] +pub fn cached(_attr: TokenStream, item: TokenStream) -> TokenStream { + let mut input_fn = parse_macro_input!(item as ItemFn); + + let mut fn_with_name_inner = input_fn.clone(); + fn_with_name_inner.sig.ident = Ident::new("inner", Span::call_site()); + + let fn_with_name_inner_tokens = quote! { + #fn_with_name_inner + }; + + let inner_fn_hash = hash_token_stream(&fn_with_name_inner_tokens); + + // Convert the [u8; 32] to a literal array expression + let inner_fn_hash_literal = quote! { + [ + #(#inner_fn_hash,)* + ] + }; + + let fn_inputs = &input_fn.sig.inputs; + let fn_output = match &input_fn.sig.output { + ReturnType::Default => quote!(()), + ReturnType::Type(_, ty) => quote!(#ty), + }; + + let param_names: Vec<_> = fn_inputs + .iter() + .filter_map(|arg| match arg { + FnArg::Typed(pat_type) => { + if let Pat::Ident(pat_ident) = &*pat_type.pat { + Some(&pat_ident.ident) + } else { + None + } + } + _ => None, + }) + .collect(); + + let param_types: Vec<_> = fn_inputs + .iter() + .filter_map(|arg| match arg { + FnArg::Typed(pat_type) => Some(&pat_type.ty), + _ => None, + }) + .collect(); + + let new_block = quote! {{ + #fn_with_name_inner + + use rkyv::{with::InlineAsBox, Archive, Deserialize, Serialize}; + + #[derive(Archive, Serialize, Deserialize, Debug)] + struct CacheKey<'a> { + #( + #[rkyv(with = InlineAsBox)] + #param_names: &'a #param_types, + )* + _function_hash: [u8; 32], + } + + let key = CacheKey { + #(#param_names: &#param_names,)* + _function_hash: #inner_fn_hash_literal, + }; + println!("{key:?}"); + let key_bytes = rkyv::to_bytes::(&key).unwrap(); + + if let Some(cached_result) = smart_cache::get_cached(&*key_bytes) { + let cached_result = &*cached_result; + let cached_result: &rkyv::Archived<#fn_output> = rkyv::access::<_, rkyv::rancor::Error>(cached_result).unwrap(); + let cached_result: #fn_output = rkyv::deserialize::<#fn_output, rkyv::rancor::Error>(cached_result).unwrap(); + return cached_result; + } + + let result = inner(#(#param_names,)*); + + let value_bytes = rkyv::to_bytes::(&result).unwrap(); + let _ = smart_cache::set_cached(&key_bytes, &value_bytes); + + result + }}; + + input_fn.block = syn::parse2(new_block).unwrap(); + + TokenStream::from(quote! { + #input_fn + }) +} diff --git a/crates/smart-cache/Cargo.toml b/crates/smart-cache/Cargo.toml new file mode 100644 index 0000000..02aae69 --- /dev/null +++ b/crates/smart-cache/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "smart-cache" +version = "0.1.0" +edition = "2021" +authors = ["Andrew Gazelka "] +description = "A smart caching library for Rust with automatic invalidation" +license = "MIT OR Apache-2.0" +repository = "https://github.com/andrewgazelka/smart-cache" +documentation = "https://docs.rs/smart-cache" +readme = "../../README.md" +keywords = ["cache", "caching", "persistence", "database"] +categories = ["caching", "database"] + +[dependencies] +smart-cache-macro = { version = "0.1.0", path = "../smart-cache-macro" } +redb = "2.4.0" +rkyv = "0.8.9" +eyre = "0.6" +once_cell = "1.0" +tracing = "0.1" +dirs = "6.0.0" diff --git a/crates/smart-cache/src/lib.rs b/crates/smart-cache/src/lib.rs new file mode 100644 index 0000000..8b9d54e --- /dev/null +++ b/crates/smart-cache/src/lib.rs @@ -0,0 +1,68 @@ +use std::path::PathBuf; + +use eyre::Result; +use once_cell::sync::Lazy; +use redb::{Database, ReadableTable, TableDefinition}; +use tracing::{debug, trace}; + +// Define the table that will store our cache entries +const CACHE_TABLE: TableDefinition<&[u8], &[u8]> = TableDefinition::new("cache"); + +static DB: Lazy = Lazy::new(|| { + let cache_dir = dirs::cache_dir() + .unwrap_or_else(|| PathBuf::from(".cache")) + .join("smart-cache"); + std::fs::create_dir_all(&cache_dir).expect("failed to create cache directory"); + + let db_path = cache_dir.join("cache.redb"); + Database::create(db_path).expect("failed to create cache database") +}); + +/// Internal function used by the macro to get a cached value +#[doc(hidden)] +pub fn get_cached(key_bytes: &[u8]) -> Option> { + trace!("Attempting cache lookup"); + + match DB.begin_read() { + Ok(txn) => match txn.open_table(CACHE_TABLE) { + Ok(table) => match table.get(key_bytes) { + Ok(Some(value)) => { + debug!("Cache hit"); + Some(value.value().to_vec()) + } + Ok(None) => { + debug!("Cache miss"); + None + } + Err(e) => { + debug!("Cache error: {}", e); + None + } + }, + Err(e) => { + debug!("Failed to open table: {}", e); + None + } + }, + Err(e) => { + debug!("Failed to begin read transaction: {}", e); + None + } + } +} + +/// Internal function used by the macro to set a cached value +#[doc(hidden)] +pub fn set_cached(key: &[u8], value: &[u8]) -> Result<()> { + trace!("Caching value"); + + let write_txn = DB.begin_write()?; + { + let mut table = write_txn.open_table(CACHE_TABLE)?; + table.insert(key, value)?; + } + write_txn.commit()?; + + debug!("Successfully cached value"); + Ok(()) +} diff --git a/crates/smart-cache/tests/something.rs b/crates/smart-cache/tests/something.rs new file mode 100644 index 0000000..abba2d4 --- /dev/null +++ b/crates/smart-cache/tests/something.rs @@ -0,0 +1,16 @@ +use smart_cache_macro::cached; + +#[cached] +fn expensive_computation(x: String, y: i32) -> String { + use std::{thread, time::Duration}; + + thread::sleep(Duration::from_secs(3)); + + format!("example computation {}_{}", x, y) +} + +#[test] +fn test_cached() { + let x = expensive_computation("hello".to_string(), 2); + println!("{x}"); +} \ No newline at end of file diff --git a/deny.toml b/deny.toml new file mode 100644 index 0000000..4987076 --- /dev/null +++ b/deny.toml @@ -0,0 +1,52 @@ +[graph] +targets = ["aarch64-apple-darwin", "x86_64-apple-darwin", "aarch64-unknown-linux-gnu", "x86_64-unknown-linux-gnu"] + +all-features = false +no-default-features = false + +[output] +feature-depth = 1 + +[advisories] +ignore = [] + +[licenses] +allow = [ + "MIT", + "Apache-2.0", + "Unicode-DFS-2016", +] + +confidence-threshold = 0.8 + +exceptions = [] + +[licenses.private] +ignore = true +registries = [] + +[bans] +multiple-versions = "warn" +wildcards = "allow" +highlight = "all" +workspace-default-features = "allow" +external-default-features = "allow" + +allow = [] + +deny = [] + +skip = [] + +skip-tree = [] + +[sources] +unknown-registry = "warn" +unknown-git = "warn" +allow-registry = ["https://github.com/rust-lang/crates.io-index"] +allow-git = [] + +[sources.allow-org] +github = [] +gitlab = [] +bitbucket = [] \ No newline at end of file diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..7073741 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,21 @@ +combine_control_expr = true +comment_width = 100 # https://lkml.org/lkml/2020/5/29/1038 +condense_wildcard_suffixes = true +control_brace_style = "AlwaysSameLine" +edition = "2021" +format_code_in_doc_comments = true +format_macro_bodies = true +format_macro_matchers = true +format_strings = true +group_imports = "StdExternalCrate" +imports_granularity = "Crate" +merge_derives = false +newline_style = "Unix" +normalize_comments = true +normalize_doc_attributes = true +overflow_delimited_expr = true +reorder_impl_items = true +reorder_imports = true +unstable_features = true +wrap_comments = true +