1use super::*;
2
3#[track_caller]
4fn invalid_reference() -> ! {
5 panic!("`--reference` must be `<crate>,<full/flat/skip-root>,<type name>");
6}
7
8pub struct ReferenceStage {
9 name: String,
10 style: ReferenceStyle,
11 path: String,
12}
13
14impl Default for ReferenceStage {
15 fn default() -> Self {
16 Self {
17 name: String::new(),
18 style: ReferenceStyle::Full,
19 path: String::new(),
20 }
21 }
22}
23
24impl ReferenceStage {
25 #[track_caller]
26 pub fn parse(arg: &str) -> Self {
27 let arg: Vec<_> = arg.split(',').collect();
28
29 if arg.len() != 3 {
30 invalid_reference();
31 }
32
33 Self {
34 name: arg[0].to_string(),
35 style: ReferenceStyle::parse(arg[1]),
36 path: arg[2].to_string(),
37 }
38 }
39}
40
41#[derive(Debug, PartialEq)]
42pub enum ReferenceStyle {
43 Full,
44 Flat,
45 SkipRoot, // used by windows and windows-sys crates
46}
47
48impl ReferenceStyle {
49 #[track_caller]
50 fn parse(arg: &str) -> Self {
51 match arg {
52 "full" => Self::Full,
53 "flat" => Self::Flat,
54 "skip-root" => Self::SkipRoot,
55 _ => invalid_reference(),
56 }
57 }
58}
59
60#[derive(Debug)]
61pub struct Reference {
62 pub name: String, // crate name like "windows"
63 pub types: TypeMap, // what this reference provides
64 pub style: ReferenceStyle, // how to generate the type path
65}
66
67#[derive(Debug, Default)]
68pub struct References(Vec<Reference>);
69
70impl References {
71 pub fn new(reader: &'static Reader, stage: Vec<ReferenceStage>) -> Self {
72 Self(
73 stage
74 .into_iter()
75 .map(|stage| {
76 let filter = Filter::new(reader, &[&stage.path], &[]);
77 let types = TypeMap::filter(reader, &filter, &References::default());
78
79 Reference {
80 name: stage.name,
81 style: stage.style,
82 types,
83 }
84 })
85 .collect(),
86 )
87 }
88
89 pub fn contains(&self, name: TypeName) -> Option<&Reference> {
90 self.0
91 .iter()
92 .find(|reference| reference.types.contains_key(&name))
93 }
94}
95