use crate::rust; use crate::rust_name::RustIdent; use crate::strx; // Copy-pasted from libsyntax. fn ident_start(c: char) -> bool { (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' } // Copy-pasted from libsyntax. fn ident_continue(c: char) -> bool { (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' } pub(crate) fn proto_path_to_rust_mod(path: &str) -> RustIdent { let without_dir = strx::remove_to(path, std::path::is_separator); let without_suffix = strx::remove_suffix(without_dir, ".proto"); let name = without_suffix .chars() .enumerate() .map(|(i, c)| { let valid = if i == 0 { ident_start(c) } else { ident_continue(c) }; if valid { c } else { '_' } }) .collect::(); let name = if rust::is_rust_keyword(&name) { format!("{}_pb", name) } else { name }; RustIdent::from(name) } #[cfg(test)] mod test { use super::proto_path_to_rust_mod; use crate::rust_name::RustIdent; #[test] fn test_mod_path_proto_ext() { assert_eq!( RustIdent::from("proto"), proto_path_to_rust_mod("proto.proto") ); } #[test] fn test_mod_path_unknown_ext() { assert_eq!( RustIdent::from("proto_proto3"), proto_path_to_rust_mod("proto.proto3") ); } #[test] fn test_mod_path_empty_ext() { assert_eq!(RustIdent::from("proto"), proto_path_to_rust_mod("proto")); } #[test] fn test_mod_path_dir() { assert_eq!( RustIdent::from("baz"), proto_path_to_rust_mod("foo/bar/baz.proto"), ) } #[cfg(target_os = "windows")] #[test] fn test_mod_path_dir_backslashes() { assert_eq!( RustIdent::from("baz"), proto_path_to_rust_mod("foo\\bar\\baz.proto"), ) } }