1 use crate::rust;
2 use crate::rust_name::RustIdent;
3 use crate::strx;
4 
5 // Copy-pasted from libsyntax.
ident_start(c: char) -> bool6 fn ident_start(c: char) -> bool {
7     (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'
8 }
9 
10 // Copy-pasted from libsyntax.
ident_continue(c: char) -> bool11 fn ident_continue(c: char) -> bool {
12     (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_'
13 }
14 
proto_path_to_rust_mod(path: &str) -> RustIdent15 pub(crate) fn proto_path_to_rust_mod(path: &str) -> RustIdent {
16     let without_dir = strx::remove_to(path, std::path::is_separator);
17     let without_suffix = strx::remove_suffix(without_dir, ".proto");
18 
19     let name = without_suffix
20         .chars()
21         .enumerate()
22         .map(|(i, c)| {
23             let valid = if i == 0 {
24                 ident_start(c)
25             } else {
26                 ident_continue(c)
27             };
28             if valid {
29                 c
30             } else {
31                 '_'
32             }
33         })
34         .collect::<String>();
35 
36     let name = if rust::is_rust_keyword(&name) {
37         format!("{}_pb", name)
38     } else {
39         name
40     };
41     RustIdent::from(name)
42 }
43 
44 #[cfg(test)]
45 mod test {
46 
47     use super::proto_path_to_rust_mod;
48     use crate::rust_name::RustIdent;
49 
50     #[test]
test_mod_path_proto_ext()51     fn test_mod_path_proto_ext() {
52         assert_eq!(
53             RustIdent::from("proto"),
54             proto_path_to_rust_mod("proto.proto")
55         );
56     }
57 
58     #[test]
test_mod_path_unknown_ext()59     fn test_mod_path_unknown_ext() {
60         assert_eq!(
61             RustIdent::from("proto_proto3"),
62             proto_path_to_rust_mod("proto.proto3")
63         );
64     }
65 
66     #[test]
test_mod_path_empty_ext()67     fn test_mod_path_empty_ext() {
68         assert_eq!(RustIdent::from("proto"), proto_path_to_rust_mod("proto"));
69     }
70 
71     #[test]
test_mod_path_dir()72     fn test_mod_path_dir() {
73         assert_eq!(
74             RustIdent::from("baz"),
75             proto_path_to_rust_mod("foo/bar/baz.proto"),
76         )
77     }
78 
79     #[cfg(target_os = "windows")]
80     #[test]
test_mod_path_dir_backslashes()81     fn test_mod_path_dir_backslashes() {
82         assert_eq!(
83             RustIdent::from("baz"),
84             proto_path_to_rust_mod("foo\\bar\\baz.proto"),
85         )
86     }
87 }
88