tinc_build/
extern_paths.rs

1use std::collections::BTreeMap;
2
3use quote::ToTokens;
4use syn::parse_quote;
5
6use crate::Mode;
7use crate::codegen::prost_sanatize::to_upper_camel;
8use crate::codegen::utils::{field_ident_from_str, type_ident_from_str};
9use crate::types::ProtoPath;
10
11#[derive(Clone)]
12pub(crate) struct ExternPaths {
13    paths: BTreeMap<ProtoPath, syn::Path>,
14}
15
16impl std::fmt::Debug for ExternPaths {
17    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18        let mut map = f.debug_map();
19
20        for (key, value) in &self.paths {
21            map.key(&key.as_ref());
22            map.value(&value.to_token_stream().to_string());
23        }
24
25        Ok(())
26    }
27}
28
29impl ExternPaths {
30    pub(crate) fn new(mode: Mode) -> Self {
31        let mut paths = BTreeMap::new();
32
33        paths.insert(ProtoPath::new("google.protobuf"), parse_quote!(::tinc::well_known::#mode));
34        paths.insert(ProtoPath::new("tinc"), parse_quote!(::tinc::well_known::#mode::tinc));
35
36        Self { paths }
37    }
38
39    pub(crate) fn resolve(&self, path: &str) -> Option<syn::Path> {
40        if let Some(path) = self.paths.get(path) {
41            return Some(path.clone());
42        }
43
44        for (idx, _) in path.rmatch_indices('.') {
45            if let Some(rust_path) = self.paths.get(&path[..idx]) {
46                let mut segments = path[idx + 1..].split('.');
47                let ident_type = segments.next_back().map(to_upper_camel).map(type_ident_from_str);
48                let segments = segments.map(field_ident_from_str).chain(ident_type);
49
50                return Some(parse_quote!(
51                    #rust_path::#(#segments)::*
52                ));
53            }
54        }
55
56        None
57    }
58
59    pub(crate) fn contains(&self, path: &str) -> bool {
60        if self.paths.contains_key(path) {
61            return true;
62        }
63
64        for (idx, _) in path.rmatch_indices('.') {
65            if self.paths.contains_key(&path[..idx]) {
66                return true;
67            }
68        }
69
70        false
71    }
72
73    pub(crate) fn paths(&self) -> std::collections::btree_map::Iter<'_, ProtoPath, syn::Path> {
74        self.paths.iter()
75    }
76}