1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
use std::panic::Location;

use dptree::{di::DependencyMap, Handler, HandlerDescription};

struct CollectLocations {
    locations: Vec<(&'static str, &'static Location<'static>)>,
}

#[track_caller]
fn collector(name: &'static str) -> CollectLocations {
    CollectLocations { locations: vec![(name, Location::caller())] }
}

impl HandlerDescription for CollectLocations {
    #[track_caller]
    fn entry() -> Self {
        collector("entry")
    }

    #[track_caller]
    fn user_defined() -> Self {
        collector("user_defined")
    }

    #[track_caller]
    fn merge_chain(&self, other: &Self) -> Self {
        let locations = self
            .locations
            .iter()
            .chain(&other.locations)
            .copied()
            .chain([("chain", Location::caller())])
            .collect();

        Self { locations }
    }

    #[track_caller]
    fn merge_branch(&self, other: &Self) -> Self {
        let locations = self
            .locations
            .iter()
            .chain(&other.locations)
            .copied()
            .chain([("branch", Location::caller())])
            .collect();

        Self { locations }
    }

    #[track_caller]
    fn map() -> Self {
        collector("map")
    }

    #[track_caller]
    fn map_async() -> Self {
        collector("map_async")
    }

    #[track_caller]
    fn filter() -> Self {
        collector("filter")
    }

    #[track_caller]
    fn filter_async() -> Self {
        collector("filter_async")
    }

    #[track_caller]
    fn filter_map() -> Self {
        collector("filter_map")
    }

    #[track_caller]
    fn filter_map_async() -> Self {
        collector("filter_map_async")
    }

    #[track_caller]
    fn endpoint() -> Self {
        collector("endpoint")
    }
}

fn get_locations<'a, 'b>(
    handler: &'a Handler<'b, impl Send + Sync + 'b, impl Send + Sync + 'b, CollectLocations>,
) -> &'a [(&'static str, &'static Location<'static>)] {
    &handler.description().locations
}

fn main() {
    #[rustfmt::skip]
    let some_tree: Handler<DependencyMap, _, _> = dptree::entry()
        .branch(
            dptree::filter(|| true)
                .endpoint(|| async {})
        )
        .branch(
            dptree::filter_async(|| async { true })
                .chain(dptree::filter_map(|| Some(1) ))
                .endpoint(|| async {})
        );

    get_locations(&some_tree).iter().for_each(|(name, loc)| println!("{name: <12} @ {loc}"));
}