From 3a5c66d5f236eaece05dbd9fd1e1a00a3ab98259 Mon Sep 17 00:00:00 2001 From: Juan Alvarez Date: Sat, 14 Dec 2019 14:08:28 -0600 Subject: [PATCH] fix(build): snake_case service names (#190) --- examples/src/routeguide/client.rs | 2 +- examples/src/routeguide/server.rs | 6 +++--- interop/src/client.rs | 2 +- interop/src/server.rs | 8 ++++---- tests/included_service/src/lib.rs | 2 +- tonic-build/src/client.rs | 4 ++-- tonic-build/src/lib.rs | 28 ++++++++++++++++++++++++++++ tonic-build/src/server.rs | 4 ++-- 8 files changed, 42 insertions(+), 14 deletions(-) diff --git a/examples/src/routeguide/client.rs b/examples/src/routeguide/client.rs index cb43440..e59f8d6 100644 --- a/examples/src/routeguide/client.rs +++ b/examples/src/routeguide/client.rs @@ -12,7 +12,7 @@ pub mod route_guide { tonic::include_proto!("routeguide"); } -use route_guide::routeguide_client::RouteGuideClient; +use route_guide::route_guide_client::RouteGuideClient; async fn print_features(client: &mut RouteGuideClient) -> Result<(), Box> { let rectangle = Rectangle { diff --git a/examples/src/routeguide/server.rs b/examples/src/routeguide/server.rs index 097f103..caf7154 100644 --- a/examples/src/routeguide/server.rs +++ b/examples/src/routeguide/server.rs @@ -14,7 +14,7 @@ pub mod routeguide { tonic::include_proto!("routeguide"); } -use routeguide::{routeguide_server, Feature, Point, Rectangle, RouteNote, RouteSummary}; +use routeguide::{route_guide_server, Feature, Point, Rectangle, RouteNote, RouteSummary}; #[derive(Debug)] pub struct RouteGuide { @@ -22,7 +22,7 @@ pub struct RouteGuide { } #[tonic::async_trait] -impl routeguide_server::RouteGuide for RouteGuide { +impl route_guide_server::RouteGuide for RouteGuide { async fn get_feature(&self, request: Request) -> Result, Status> { println!("GetFeature = {:?}", request); @@ -154,7 +154,7 @@ async fn main() -> Result<(), Box> { features: Arc::new(data::load()), }; - let svc = routeguide_server::RouteGuideServer::new(route_guide); + let svc = route_guide_server::RouteGuideServer::new(route_guide); Server::builder().add_service(svc).serve(addr).await?; diff --git a/interop/src/client.rs b/interop/src/client.rs index 277edeb..ce6e6e6 100644 --- a/interop/src/client.rs +++ b/interop/src/client.rs @@ -1,5 +1,5 @@ use crate::{ - pb::testservice_client::*, pb::unimplementedservice_client::*, pb::*, test_assert, + pb::test_service_client::*, pb::unimplemented_service_client::*, pb::*, test_assert, TestAssertion, }; use futures_util::{future, stream, StreamExt}; diff --git a/interop/src/server.rs b/interop/src/server.rs index 2b613d1..581969c 100644 --- a/interop/src/server.rs +++ b/interop/src/server.rs @@ -5,8 +5,8 @@ use std::pin::Pin; use std::time::Duration; use tonic::{Code, Request, Response, Status}; -pub use pb::testservice_server::TestServiceServer; -pub use pb::unimplementedservice_server::UnimplementedServiceServer; +pub use pb::test_service_server::TestServiceServer; +pub use pb::unimplemented_service_server::UnimplementedServiceServer; #[derive(Default, Clone)] pub struct TestService; @@ -18,7 +18,7 @@ type Stream = Pin< >; #[tonic::async_trait] -impl pb::testservice_server::TestService for TestService { +impl pb::test_service_server::TestService for TestService { async fn empty_call(&self, _request: Request) -> Result { Ok(Response::new(Empty {})) } @@ -154,7 +154,7 @@ impl pb::testservice_server::TestService for TestService { pub struct UnimplementedService; #[tonic::async_trait] -impl pb::unimplementedservice_server::UnimplementedService for UnimplementedService { +impl pb::unimplemented_service_server::UnimplementedService for UnimplementedService { async fn unimplemented_call(&self, _req: Request) -> Result { Err(Status::unimplemented("")) } diff --git a/tests/included_service/src/lib.rs b/tests/included_service/src/lib.rs index be30849..749e19d 100644 --- a/tests/included_service/src/lib.rs +++ b/tests/included_service/src/lib.rs @@ -5,4 +5,4 @@ pub mod pb { // Ensure that an RPC service, defined before including a file that defines // another service in a different protocol buffer package, is not incorrectly // cleared from the context of its package. -type _Test = dyn pb::topservice_server::TopService; +type _Test = dyn pb::top_service_server::TopService; diff --git a/tonic-build/src/client.rs b/tonic-build/src/client.rs index bd83c14..d8f6941 100644 --- a/tonic-build/src/client.rs +++ b/tonic-build/src/client.rs @@ -1,11 +1,11 @@ -use crate::generate_doc_comments; +use crate::{generate_doc_comments, naive_snake_case}; use proc_macro2::TokenStream; use prost_build::{Method, Service}; use quote::{format_ident, quote}; pub(crate) fn generate(service: &Service, proto: &str) -> TokenStream { let service_ident = quote::format_ident!("{}Client", service.name); - let client_mod = quote::format_ident!("{}_client", service.name.to_ascii_lowercase()); + let client_mod = quote::format_ident!("{}_client", naive_snake_case(&service.name)); let methods = generate_methods(service, proto); let connect = generate_connect(&service_ident); diff --git a/tonic-build/src/lib.rs b/tonic-build/src/lib.rs index aca9a1c..6c1ce2b 100644 --- a/tonic-build/src/lib.rs +++ b/tonic-build/src/lib.rs @@ -321,3 +321,31 @@ fn replace_wellknown(proto_path: &str, method: &Method) -> (TokenStream, TokenSt (request, response) } + +fn naive_snake_case(name: &str) -> String { + let mut s = String::new(); + let mut it = name.chars().peekable(); + + while let Some(x) = it.next() { + s.push(x.to_ascii_lowercase()); + if let Some(y) = it.peek() { + if y.is_uppercase() { + s.push('_'); + } + } + } + + s +} + +#[test] +fn test_snake_case() { + for case in &[ + ("Service", "service"), + ("ThatHasALongName", "that_has_a_long_name"), + ("greeter", "greeter"), + ("ABCServiceX", "a_b_c_service_x"), + ] { + assert_eq!(naive_snake_case(case.0), case.1) + } +} diff --git a/tonic-build/src/server.rs b/tonic-build/src/server.rs index fab3fe8..cb8f52f 100644 --- a/tonic-build/src/server.rs +++ b/tonic-build/src/server.rs @@ -1,4 +1,4 @@ -use crate::{generate_doc_comment, generate_doc_comments}; +use crate::{generate_doc_comment, generate_doc_comments, naive_snake_case}; use proc_macro2::{Span, TokenStream}; use prost_build::{Method, Service}; use quote::quote; @@ -9,7 +9,7 @@ pub(crate) fn generate(service: &Service, proto_path: &str) -> TokenStream { let server_service = quote::format_ident!("{}Server", service.name); let server_trait = quote::format_ident!("{}", service.name); - let server_mod = quote::format_ident!("{}_server", service.name.to_ascii_lowercase()); + let server_mod = quote::format_ident!("{}_server", naive_snake_case(&service.name)); let generated_trait = generate_trait(service, proto_path, server_trait.clone()); let service_doc = generate_doc_comments(&service.comments.leading);