Skip to content

Commit dc8a022

Browse files
committed
宏实现
1 parent a97c3db commit dc8a022

File tree

9 files changed

+470
-22
lines changed

9 files changed

+470
-22
lines changed

Cargo.lock

+19-8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+9-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
[workspace]
2+
members = ["algorithm-macro"]
3+
14
[package]
25
name = "algorithm"
36
version = "0.1.7"
@@ -11,12 +14,15 @@ keywords = ["arc", "lru", "lfu", "timerwheel", "slab"]
1114
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1215

1316
[dependencies]
14-
lazy_static="1.4.0"
17+
lazy_static="1.5.0"
1518
hashbrown="0.14"
1619

20+
[dependencies.algorithm-macro]
21+
path = "algorithm-macro"
22+
1723
[dev-dependencies]
1824
rand="0.8.5"
19-
libc="0.2"
25+
libc="0.2.158"
2026
slab = "0.4.9"
2127

2228
[profile.release]
@@ -26,4 +32,4 @@ debug = true
2632
[features]
2733
default = ["hashbrown", "ttl"]
2834
hashbrown=[]
29-
ttl=[]
35+
ttl=[]

README.md

+21
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,27 @@ fn main() {
210210
```
211211

212212

213+
# 添加宏支持, 可快速的缓存函数的结果
214+
215+
216+
```rust
217+
use algorithm::LruCache;
218+
use algorithm_macro::cache;
219+
220+
#[cache(LruCache : LruCache::new(20))]
221+
#[cache_cfg(ignore_args = call_count)]
222+
#[cache_cfg(thread)]
223+
fn fib(x: u64, call_count: &mut u32) -> u64 {
224+
*call_count += 1;
225+
if x <= 1 {
226+
1
227+
} else {
228+
fib(x - 1, call_count) + fib(x - 2, call_count)
229+
}
230+
}
231+
```
232+
如此就可以快速将函数的执行结果进行缓存加速.
233+
213234
## Star History
214235

215236
[![Star History Chart](https://api.star-history.com/svg?repos=tickbh/algorithm-rs&type=Date)](https://star-history.com/#tickbh/algorithm-rs&Date)

algorithm-macro/Cargo.toml

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[package]
2+
name = "algorithm-macro"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
[dependencies]
9+
quote = "1.0.36"
10+
lazy_static = "1.2.0"
11+
proc-macro2 = "1.0.86"
12+
13+
[dependencies.syn]
14+
version = "2.0.74"
15+
features = ["full", "extra-traits"]
16+
17+
[lib]
18+
proc-macro = true

algorithm-macro/src/config.rs

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
use std::default::Default;
2+
use std::collections::HashSet;
3+
4+
use quote::ToTokens;
5+
use syn::{self, Token, parenthesized};
6+
use syn::parse::{Parse, ParseStream};
7+
8+
pub struct Config {
9+
pub ignore_args: HashSet<syn::Ident>,
10+
pub use_thread: bool,
11+
}
12+
13+
struct IgnoreArgsAttrib {
14+
ignore_args: HashSet<syn::Ident>,
15+
}
16+
17+
enum ConfigAttrib {
18+
IgnoreArgs(IgnoreArgsAttrib),
19+
UseTread,
20+
}
21+
22+
const CONFIG_ATTRIBUTE_NAME: &'static str = "cache_cfg";
23+
24+
impl Config {
25+
// Parse any additional attributes present after `lru_cache` and return a configuration object
26+
// created from their contents. Additionally, return any attributes that were not handled here.
27+
pub fn parse_from_attributes(attribs: &[syn::Attribute]) -> syn::Result<(Config, Vec<syn::Attribute>)> {
28+
let mut parsed_attributes = Vec::new();
29+
let mut remaining_attributes = Vec::new();
30+
31+
for attrib in attribs {
32+
let segs = &attrib.path().segments;
33+
if segs.len() > 0 {
34+
if segs[0].ident == CONFIG_ATTRIBUTE_NAME {
35+
let tokens = attrib.meta.to_token_stream();
36+
let parsed = syn::parse2::<ConfigAttrib>(tokens)?;
37+
parsed_attributes.push(parsed);
38+
}
39+
else {
40+
remaining_attributes.push(attrib.clone());
41+
}
42+
}
43+
}
44+
45+
let mut config: Config = Default::default();
46+
47+
for parsed_attrib in parsed_attributes {
48+
match parsed_attrib {
49+
ConfigAttrib::IgnoreArgs(val) => config.ignore_args = val.ignore_args,
50+
ConfigAttrib::UseTread => config.use_thread = true,
51+
}
52+
}
53+
54+
Ok((config, remaining_attributes))
55+
}
56+
}
57+
58+
impl Default for Config {
59+
fn default() -> Config {
60+
Config {
61+
ignore_args: HashSet::new(),
62+
use_thread: false,
63+
}
64+
}
65+
}
66+
67+
impl Parse for ConfigAttrib {
68+
fn parse(input: ParseStream) -> syn::parse::Result<Self> {
69+
let _name = input.parse::<syn::Ident>()?;
70+
let content;
71+
let _paren = parenthesized!(content in input);
72+
let name = content.parse::<syn::Ident>()?;
73+
match &name.to_string()[..] {
74+
"ignore_args" => Ok(ConfigAttrib::IgnoreArgs(content.parse::<IgnoreArgsAttrib>()?)),
75+
"thread" => Ok(ConfigAttrib::UseTread),
76+
_ => Err(syn::parse::Error::new(
77+
name.span(), format!("unrecognized config option '{}'", name.to_string())
78+
))
79+
}
80+
}
81+
}
82+
83+
impl Parse for IgnoreArgsAttrib {
84+
fn parse(input: ParseStream) -> syn::parse::Result<Self> {
85+
input.parse::<Token![=]>()?;
86+
let elems = syn::punctuated::Punctuated::<syn::Ident, Token![,]>::parse_terminated(input)?;
87+
Ok(IgnoreArgsAttrib {
88+
ignore_args: elems.into_iter().collect(),
89+
})
90+
}
91+
}

0 commit comments

Comments
 (0)