tinc_build/codegen/
utils.rs

1use syn::Ident;
2
3use super::prost_sanatize;
4
5pub(crate) fn field_ident_from_str(s: impl AsRef<str>) -> Ident {
6    syn::parse_str(&prost_sanatize::to_snake(s.as_ref())).unwrap()
7}
8
9pub(crate) fn type_ident_from_str(s: impl AsRef<str>) -> Ident {
10    syn::parse_str(&prost_sanatize::to_upper_camel(s.as_ref())).unwrap()
11}
12
13pub(crate) fn get_common_import_path(package: &str, end: &str) -> syn::Path {
14    let start_parts: Vec<&str> = package.split('.').collect();
15    let mut end_parts: Vec<&str> = end.split('.').collect();
16
17    let end_part = type_ident_from_str(end_parts.pop().expect("end path must not be empty")).to_string();
18
19    let common_len = start_parts.iter().zip(&end_parts).take_while(|(a, b)| a == b).count();
20
21    let num_supers = start_parts.len().saturating_sub(common_len);
22
23    let mut path_parts = Vec::new();
24
25    for _ in 0..num_supers {
26        path_parts.push("super".to_string());
27    }
28
29    for end_part in end_parts[common_len..].iter() {
30        path_parts.push(field_ident_from_str(end_part).to_string());
31    }
32
33    path_parts.push(end_part);
34
35    syn::parse_str(&path_parts.join("::")).expect("failed to parse path")
36}
37
38#[cfg(test)]
39#[cfg_attr(coverage_nightly, coverage(off))]
40mod tests {
41    use quote::ToTokens;
42
43    use super::*;
44
45    #[test]
46    fn test_get_common_import_path() {
47        assert_eq!(
48            get_common_import_path("a.b.c", "a.b.d").to_token_stream().to_string(),
49            syn::parse_str::<syn::Path>("super::D").unwrap().to_token_stream().to_string()
50        );
51        assert_eq!(
52            get_common_import_path("a.b.c", "a.b.c.d").to_token_stream().to_string(),
53            syn::parse_str::<syn::Path>("D").unwrap().to_token_stream().to_string()
54        );
55        assert_eq!(
56            get_common_import_path("a.b.c", "a.b.c").to_token_stream().to_string(),
57            syn::parse_str::<syn::Path>("super::C").unwrap().to_token_stream().to_string()
58        );
59        assert_eq!(
60            get_common_import_path("a.b.c", "a.b").to_token_stream().to_string(),
61            syn::parse_str::<syn::Path>("super::super::B")
62                .unwrap()
63                .to_token_stream()
64                .to_string()
65        );
66    }
67}