From 3b717dc9a2336f91c4d533ee437c2afd6860f528 Mon Sep 17 00:00:00 2001 From: Matthijs Brobbel Date: Wed, 14 Sep 2022 17:28:18 +0200 Subject: [PATCH 1/3] fix: escape keywords in typename --- pbjson-build/src/descriptor.rs | 12 +++++++++++- pbjson-test/build.rs | 1 + pbjson-test/protos/escape.proto | 14 ++++++++++++++ pbjson-test/src/lib.rs | 10 ++++++++++ 4 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 pbjson-test/protos/escape.proto diff --git a/pbjson-build/src/descriptor.rs b/pbjson-build/src/descriptor.rs index 7ecdb37..6e557f0 100644 --- a/pbjson-build/src/descriptor.rs +++ b/pbjson-build/src/descriptor.rs @@ -12,6 +12,8 @@ use prost_types::{ FileDescriptorProto, FileDescriptorSet, MessageOptions, OneofDescriptorProto, }; +use crate::escape::escape_ident; + #[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] pub struct Package { path: Vec, @@ -68,7 +70,7 @@ impl TypeName { pub fn to_snake_case(&self) -> String { use heck::ToSnakeCase; - self.0.to_snake_case() + escape_ident(self.0.to_snake_case()) } pub fn to_upper_camel_case(&self) -> String { @@ -299,4 +301,12 @@ mod tests { String::from("foo_bar.baz.boo") ) } + + #[test] + fn escape_keywords() { + assert_eq!( + Package::new("type.abstract").to_string(), + "r#type.r#abstract" + ); + } } diff --git a/pbjson-test/build.rs b/pbjson-test/build.rs index f594a4b..650a48d 100644 --- a/pbjson-test/build.rs +++ b/pbjson-test/build.rs @@ -13,6 +13,7 @@ fn main() -> Result<()> { root.join("syntax3.proto"), root.join("common.proto"), root.join("duplicate_name.proto"), + root.join("escape.proto"), ]; // Tell cargo to recompile if any of these proto files are changed diff --git a/pbjson-test/protos/escape.proto b/pbjson-test/protos/escape.proto new file mode 100644 index 0000000..018bf84 --- /dev/null +++ b/pbjson-test/protos/escape.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; +package test.abstract.type.escape; + +message Target { + Abstract abstract = 1; +} + +message Abstract { + Type type = 1; +} + +message Type { + bool example = 1; +} diff --git a/pbjson-test/src/lib.rs b/pbjson-test/src/lib.rs index ab5b3c5..2324e73 100644 --- a/pbjson-test/src/lib.rs +++ b/pbjson-test/src/lib.rs @@ -36,6 +36,16 @@ pub mod test { include!(concat!(env!("OUT_DIR"), "/test.duplicate_name.rs")); include!(concat!(env!("OUT_DIR"), "/test.duplicate_name.serde.rs")); } + pub mod escape { + include!(concat!( + env!("OUT_DIR"), + "/test.r#abstract.r#type.escape.rs" + )); + include!(concat!( + env!("OUT_DIR"), + "/test.r#abstract.r#type.escape.serde.rs" + )); + } } #[cfg(test)] From 05352b104f15e4b81e0a2f0ca664749d919b18f6 Mon Sep 17 00:00:00 2001 From: Matthijs Brobbel Date: Tue, 20 Sep 2022 14:04:03 +0200 Subject: [PATCH 2/3] fix: rename typename's `to_snake_case` to `to_snake_case_ident` --- pbjson-build/src/descriptor.rs | 6 +++--- pbjson-build/src/resolver.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pbjson-build/src/descriptor.rs b/pbjson-build/src/descriptor.rs index 6e557f0..7bd5168 100644 --- a/pbjson-build/src/descriptor.rs +++ b/pbjson-build/src/descriptor.rs @@ -21,9 +21,9 @@ pub struct Package { impl Display for Package { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.path[0].to_snake_case())?; + write!(f, "{}", self.path[0].to_snake_case_ident())?; for element in &self.path[1..self.path.len()] { - write!(f, ".{}", element.to_snake_case())?; + write!(f, ".{}", element.to_snake_case_ident())?; } Ok(()) } @@ -68,7 +68,7 @@ impl TypeName { Self(s) } - pub fn to_snake_case(&self) -> String { + pub fn to_snake_case_ident(&self) -> String { use heck::ToSnakeCase; escape_ident(self.0.to_snake_case()) } diff --git a/pbjson-build/src/resolver.rs b/pbjson-build/src/resolver.rs index 5d1d68f..8d9d4bb 100644 --- a/pbjson-build/src/resolver.rs +++ b/pbjson-build/src/resolver.rs @@ -75,7 +75,7 @@ impl<'a> Resolver<'a> { while let Some(i) = iter.next() { match iter.peek() { Some(_) => { - ret.push_str(i.to_snake_case().as_str()); + ret.push_str(i.to_snake_case_ident().as_str()); ret.push_str("::"); } None => { From c608e46ffe4ea6057d2e5eea9fca479e52640293 Mon Sep 17 00:00:00 2001 From: Matthijs Brobbel Date: Tue, 20 Sep 2022 14:11:12 +0200 Subject: [PATCH 3/3] test: add serde test for escape.proto --- pbjson-test/src/lib.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/pbjson-test/src/lib.rs b/pbjson-test/src/lib.rs index 2324e73..fba4edb 100644 --- a/pbjson-test/src/lib.rs +++ b/pbjson-test/src/lib.rs @@ -50,6 +50,8 @@ pub mod test { #[cfg(test)] mod tests { + use std::error::Error; + use super::*; use crate::test::syntax3::kitchen_sink::MixedCase; use chrono::TimeZone; @@ -417,4 +419,27 @@ mod tests { decoded.string_value = None; verify(&decoded, r#"{}"#); } + + #[test] + fn test_escaped() -> Result<(), Box> { + use super::test::escape::{Abstract, Target, Type}; + + let r#type = Type { example: true }; + let r#abstract = Abstract { + r#type: Some(r#type), + }; + let target = Target { + r#abstract: Some(r#abstract), + }; + + let encoded = serde_json::to_string(&target)?; + + let expected = r#"{"abstract":{"type":{"example":true}}}"#; + assert_eq!(encoded, expected); + + let decoded = serde_json::from_str::(&encoded)?; + assert_eq!(decoded, target); + + Ok(()) + } }