{"id":33931644,"url":"https://github.com/tylerreisinger/cache-macro","last_synced_at":"2026-04-05T01:31:30.004Z","repository":{"id":40280912,"uuid":"158003148","full_name":"tylerreisinger/cache-macro","owner":"tylerreisinger","description":"A procedural attribute macro to automatically cache the results of a function call with given args.","archived":false,"fork":false,"pushed_at":"2019-03-14T15:59:25.000Z","size":48,"stargazers_count":65,"open_issues_count":2,"forks_count":8,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-01-14T01:08:31.983Z","etag":null,"topics":["cache","lru","procedural-macros","rust"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tylerreisinger.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-11-17T16:29:33.000Z","updated_at":"2025-03-20T00:23:07.000Z","dependencies_parsed_at":"2022-06-28T17:49:35.134Z","dependency_job_id":null,"html_url":"https://github.com/tylerreisinger/cache-macro","commit_stats":null,"previous_names":["tylerreisinger/lru-cache-macro"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/tylerreisinger/cache-macro","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tylerreisinger%2Fcache-macro","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tylerreisinger%2Fcache-macro/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tylerreisinger%2Fcache-macro/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tylerreisinger%2Fcache-macro/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tylerreisinger","download_url":"https://codeload.github.com/tylerreisinger/cache-macro/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tylerreisinger%2Fcache-macro/sbom","scorecard":{"id":905032,"data":{"date":"2025-08-11","repo":{"name":"github.com/tylerreisinger/cache-macro","commit":"02bdf08f1969d95c54b87be305926ff0bc7661c0"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.2,"checks":[{"name":"Code-Review","score":1,"reason":"Found 4/23 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 12 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-24T17:02:26.904Z","repository_id":40280912,"created_at":"2025-08-24T17:02:26.904Z","updated_at":"2025-08-24T17:02:26.904Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31421869,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-05T00:25:07.052Z","status":"ssl_error","status_checked_at":"2026-04-05T00:25:05.923Z","response_time":60,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cache","lru","procedural-macros","rust"],"created_at":"2025-12-12T12:55:28.759Z","updated_at":"2026-04-05T01:31:29.994Z","avatar_url":"https://github.com/tylerreisinger.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"cache-macro\n================\n[![Build Status](https://travis-ci.org/tylerreisinger/cache-macro.svg?branch=master)](https://travis-ci.org/tylerreisinger/cache_macro)\n[![cache-macro on docs.rs][docsrs-image]][docsrs]\n[![cache-macro on crates.io][crates-image]][crates]\n\n[docsrs-image]: https://docs.rs/cache-macro/badge.svg\n[docsrs]: https://docs.rs/cache-macro\n[crates-image]: https://img.shields.io/crates/v/cache-macro.svg\n[crates]: https://crates.io/crates/cache-macro/\n\nA procedural macro to automatically cache the result of a function given a set of inputs.\n\nPreviously named 'lru-cache-macros', but renamed to reflect the broadening of scope.\n\n# Example:\n\n```rust\nuse cache_macro::cache;\nuse lru_cache::LruCache;\n\n#[cache(LruCache : LruCache::new(20))]\nfn fib(x: u32) -\u003e u64 {\n    println!(\"{:?}\", x);\n    if x \u003c= 1 {\n        1\n    } else {\n        fib(x - 1) + fib(x - 2)\n    }\n}\n\nassert_eq!(fib(19), 6765);\n```\n\nThe above example only calls `fib` twenty times, with the values from 0 to 19. All intermediate\nresults because of the recursion hit the cache.\n\n# Usage:\n\nSimply place `#[cache(CacheType : constructor)]` above your function. The function must obey a few properties\nto use lru_cache:\n\n* All arguments and return values must implement `Clone`.\n* The function may not take `self` in any form.\n\nThe `LruCache` type used must accept two generic parameters `\u003cArgs, Return\u003e` and must support methods\n`get_mut(\u0026K) -\u003e Option\u003c\u0026mut V\u003e` and `insert(K, V)`. The `lru-cache` (for LRU caching)\nand `expiring_map` (for time-to-live caching) crates currently meet these requirements.\n\nCurrently, this crate only works on nightly rust. However, once the 2018 edition stabilizes as well as the\nprocedural macro diagnostic interface, it should be able to run on stable.\n\n# Configuration:\n\nThe lru_cache macro can be configured by adding additional attributes under `#[cache(...)]`.\n\nAll configuration attributes take the form `#[cache_cfg(...)]`. The available attributes are:\n\n* `#[cache_cfg(ignore_args = ...)]`\n\nThis allows certain arguments to be ignored for the purposes of caching. That means they are not part of the\nhash table key and thus should never influence the output of the function. It can be useful for diagnostic settings,\nreturning the number of times executed, or other introspection purposes.\n\n`ignore_args` takes a comma-separated list of variable identifiers to ignore.\n\n### Example:\n```rust\nuse cache_macro::cache;\nuse lru_cache::LruCache;\n#[cache(LruCache : LruCache::new(20))]\n#[cache_cfg(ignore_args = call_count)]\nfn fib(x: u64, call_count: \u0026mut u32) -\u003e u64 {\n    *call_count += 1;\n    if x \u003c= 1 {\n        1\n    } else {\n        fib(x - 1, call_count) + fib(x - 2, call_count)\n    }\n}\n\nlet mut call_count = 0;\nassert_eq!(fib(39, \u0026mut call_count), 102_334_155);\nassert_eq!(call_count, 40);\n```\n\nThe `call_count` argument can vary, caching is only done based on `x`.\n\n* `#[cache_cfg(thread_local)]`\n\nStore the cache in thread-local storage instead of global static storage. This avoids the overhead of Mutex locking,\nbut each thread will be given its own cache, and all caching will not affect any other thread.\n\nExpanding on the first example:\n\n```rust\nuse cache_macro::cache;\nuse lru_cache::LruCache;\n\n#[cache(LruCache : LruCache::new(20))]\n#[cache_cfg(thread_local)]\nfn fib(x: u32) -\u003e u64 {\n    println!(\"{:?}\", x);\n    if x \u003c= 1 {\n        1\n    } else {\n        fib(x - 1) + fib(x - 2)\n    }\n}\n\nassert_eq!(fib(19), 6765);\n```\n\n# Details\nThe created cache is stored as a static variable protected by a mutex unless the `#[cache_cfg(thread_local)]`\nconfiguration is added.\n\nWith the default settings, the fibonacci example will generate the following code:\n\n```rust\nfn __lru_base_fib(x: u32) -\u003e u64 {\n    if x \u003c= 1 { 1 } else { fib(x - 1) + fib(x - 2) }\n}\nfn fib(x: u32) -\u003e u64 {\n    use lazy_static::lazy_static;\n    use std::sync::Mutex;\n\n    lazy_static! {\n        static ref cache: Mutex\u003c::lru_cache::LruCache\u003c(u32,), u64\u003e\u003e =\n            Mutex::new(::lru_cache::LruCache::new(20usize));\n    }\n\n    let cloned_args = (x.clone(),);\n    let mut cache_unlocked = cache.lock().unwrap();\n    let stored_result = cache_unlocked.get_mut(\u0026cloned_args);\n    if let Some(stored_result) = stored_result {\n        return stored_result.clone();\n    };\n    drop(cache_unlocked);\n    let ret = __lru_base_fib(x);\n    let mut cache_unlocked = cache.lock().unwrap();\n    cache_unlocked.insert(cloned_args, ret.clone());\n    ret\n}\n\n```\n\nWhereas, if you use the `#[lru_config(thread_local)]` the generated code will look like:\n\n\n```rust\nfn __lru_base_fib(x: u32) -\u003e u64 {\n    if x \u003c= 1 { 1 } else { fib(x - 1) + fib(x - 2) }\n}\nfn fib(x: u32) -\u003e u64 {\n    use std::cell::UnsafeCell;\n    use std::thread_local;\n\n    thread_local!(\n         static cache: UnsafeCell\u003c::lru_cache::LruCache\u003c(u32,), u64\u003e\u003e =\n             UnsafeCell::new(::lru_cache::LruCache::new(20usize));\n    );\n\n    cache.with(|c|\n        {\n            let mut cache_ref = unsafe { \u0026mut *c.get() };\n            let cloned_args = (x.clone(),);\n            let stored_result = cache_ref.get_mut(\u0026cloned_args);\n            if let Some(stored_result) = stored_result {\n                stored_result.clone()\n            } else {\n                let ret = __lru_base_fib(x);\n                cache_ref.insert(cloned_args, ret.clone());\n                ret\n            }\n        })\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftylerreisinger%2Fcache-macro","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftylerreisinger%2Fcache-macro","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftylerreisinger%2Fcache-macro/lists"}