Skip to content

Commit 69a4aa5

Browse files
committed
capt
1 parent f46b6ff commit 69a4aa5

File tree

8 files changed

+759
-4
lines changed

8 files changed

+759
-4
lines changed

.vscode/settings.json

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"rust-analyzer.linkedProjects": [
3+
".\\tuples\\Cargo.toml",
4+
".\\tuples\\Cargo.toml",
5+
".\\tuples\\Cargo.toml"
6+
],
7+
"rust-analyzer.showUnlinkedFileNotification": false
8+
}

code_gen/src/code_gen.rs

+45
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pub fn code_gen(out_dir: &Path) {
3030
gen_cloned(&ctx, &out_dir);
3131
gen_call(&ctx, &out_dir);
3232
gen_apply_tuple(&ctx, &out_dir);
33+
gen_capt(&ctx, &out_dir);
3334
}
3435

3536
#[allow(dead_code)]
@@ -1275,6 +1276,15 @@ fn gen_apply_tuple_size(ctx: &Ctx, size: usize) -> TokenStream {
12751276
type DynFnOnce = dyn FnOnce(#(#nts),*) -> R;
12761277
type DynFnMut = dyn FnMut(#(#nts),*) -> R;
12771278
type DynFn = dyn Fn(#(#nts),*) -> R;
1279+
type FnPtr = fn(#(#nts),*) -> R;
1280+
}
1281+
1282+
impl<F: FnOnce(#(#nts),*) -> R, R, #(#nts),*> ApplyTupleMeta<(#(#nts,)*)> for F {
1283+
type Output = R;
1284+
type DynFnOnce = dyn FnOnce(#(#nts),*) -> R;
1285+
type DynFnMut = dyn FnMut(#(#nts),*) -> R;
1286+
type DynFn = dyn Fn(#(#nts),*) -> R;
1287+
type FnPtr = fn(#(#nts),*) -> R;
12781288
}
12791289

12801290
impl<F: FnOnce(#(#nts),*) -> R, R, #(#nts),*> ApplyTupleOnce<(#(#nts,)*)> for F {
@@ -1299,3 +1309,38 @@ fn gen_apply_tuple_size(ctx: &Ctx, size: usize) -> TokenStream {
12991309
};
13001310
tks
13011311
}
1312+
1313+
fn gen_capt(ctx: &Ctx, out_dir: &Path) {
1314+
let items = (1..33usize).map(|i| gen_capt_size(ctx, i));
1315+
let tks = quote! { #(#items)* };
1316+
let mut code = tks.to_string();
1317+
code.insert_str(0, "// This file is by code gen, do not modify\n\n");
1318+
let dest_path = Path::new(out_dir).join("capt.rs");
1319+
fs::write(&dest_path, code).unwrap();
1320+
}
1321+
1322+
fn gen_capt_size(ctx: &Ctx, size: usize) -> TokenStream {
1323+
let nts = &ctx.nts[0..size];
1324+
let nvs = &ctx.nvs[0..size];
1325+
let name = format_ident!("capt_{}", size);
1326+
let name_mut = format_ident!("capt_mut_{}", size);
1327+
let name_once = format_ident!("capt_once_{}", size);
1328+
let tks = quote! {
1329+
#[doc = "Manually capture the variables required by the closure"]
1330+
pub fn #name<C, #(#nts),*, R, F: Fn(&C, #(#nts),*) -> R>(c: C, f: F) -> impl Fn(#(#nts),*) -> R {
1331+
move |#(#nvs,)*| f(&c, #(#nvs,)*)
1332+
}
1333+
1334+
#[doc = "Manually capture the variables required by the closure"]
1335+
pub fn #name_mut<C, #(#nts),*, R, F: FnMut(&mut C, #(#nts),*) -> R>(mut c: C, mut f: F) -> impl FnMut(#(#nts),*) -> R {
1336+
move |#(#nvs,)*| f(&mut c, #(#nvs,)*)
1337+
}
1338+
1339+
#[doc = "Manually capture the variables required by the closure"]
1340+
pub fn #name_once<C, #(#nts),*, R, F: FnOnce(C, #(#nts),*) -> R>(c: C, f: F) -> impl FnOnce(#(#nts),*) -> R {
1341+
move |#(#nvs,)*| f(c, #(#nvs,)*)
1342+
}
1343+
1344+
};
1345+
tks
1346+
}

tuples/Cargo.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ license = "MIT"
88
name = "tuples"
99
readme = "../README.md"
1010
repository = "https://github.com/libsugar/tuplers"
11-
version = "1.11.0"
11+
version = "1.12.0"
1212

1313
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1414

@@ -32,6 +32,7 @@ default = [
3232
"cloned",
3333
"tuple_call",
3434
"re-exports",
35+
"capt",
3536
]
3637
flatten = []
3738
re-exports = []
@@ -48,3 +49,4 @@ tuple_call = []
4849
tuple_iter = []
4950
tuple_map = []
5051
tuple_meta = []
52+
capt = []

tuples/src/apply_tuple.rs

+10
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@ pub trait TupleFnMeta<R> {
66
type DynFnOnce: ?Sized;
77
type DynFnMut: ?Sized;
88
type DynFn: ?Sized;
9+
type FnPtr;
10+
}
11+
12+
/// Apply tuple meta
13+
pub trait ApplyTupleMeta<Tuple> {
14+
type Output;
15+
type DynFnOnce: ?Sized;
16+
type DynFnMut: ?Sized;
17+
type DynFn: ?Sized;
18+
type FnPtr;
919
}
1020

1121
/// Apply tuple as args to FnOnce

tuples/src/capt.rs

+38-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,44 @@
1+
//! Manually capture the variables required by the closure
2+
13
/// Manually capture the variables required by the closure
2-
pub fn capt0<T, R, F: Fn(&T) -> R>(v: T, f: F) -> impl Fn() -> R {
4+
pub fn capt_0<T, R, F: Fn(&T) -> R>(v: T, f: F) -> impl Fn() -> R {
35
move || f(&v)
46
}
57

68
/// Manually capture the variables required by the closure
7-
pub fn capt1<T, A, R, F: Fn(&T, A) -> R>(v: T, f: F) -> impl Fn(A) -> R {
8-
move |a| f(&v, a)
9+
pub fn capt_mut_0<T, R, F: FnMut(&mut T) -> R>(mut v: T, mut f: F) -> impl FnMut() -> R {
10+
move || f(&mut v)
11+
}
12+
13+
/// Manually capture the variables required by the closure
14+
pub fn capt_once_0<T, R, F: FnOnce(T) -> R>(v: T, f: F) -> impl FnOnce() -> R {
15+
move || f(v)
16+
}
17+
18+
include!("./gen/capt.rs");
19+
20+
#[test]
21+
fn test1() {
22+
let a = capt_0(1, |a| *a);
23+
let r = a();
24+
assert_eq!(r, 1);
25+
}
26+
27+
#[test]
28+
fn test2() {
29+
let a = capt_1(2, |a, b| *a * b);
30+
let r = a(3);
31+
assert_eq!(r, 6);
32+
}
33+
34+
#[test]
35+
fn test3() {
36+
let mut a = capt_mut_1(2, |a, b| {
37+
*a *= b;
38+
*a
39+
});
40+
let r = a(3);
41+
assert_eq!(r, 6);
42+
let r = a(3);
43+
assert_eq!(r, 18);
944
}

0 commit comments

Comments
 (0)