tinc_build/
extern_paths.rs1use 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}