Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into support-explicit-nulls
Browse files Browse the repository at this point in the history
  • Loading branch information
tustvold committed Oct 26, 2022
2 parents 87f3788 + 11ad26a commit 2424a4a
Show file tree
Hide file tree
Showing 9 changed files with 484 additions and 104 deletions.
3 changes: 3 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ jobs:
- run:
name: Cargo test (use integers for enums)
command: cargo test --workspace --features use-integers-for-enums
- run:
name: Cargo test (preserve proto field names)
command: cargo test --workspace --features preserve-proto-field-names
- cache_save

workflows:
Expand Down
128 changes: 102 additions & 26 deletions pbjson-build/src/generator/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,20 @@ pub fn generate_message<W: Write>(
ignore_unknown_fields: bool,
btree_map_paths: &[String],
emit_fields: bool,
preserve_proto_field_names: bool,
) -> Result<()> {
let rust_type = resolver.rust_type(&message.path);

// Generate Serialize
write_serialize_start(0, &rust_type, writer)?;
write_message_serialize(resolver, 2, message, writer, emit_fields)?;
write_message_serialize(
resolver,
2,
message,
writer,
emit_fields,
preserve_proto_field_names,
)?;
write_serialize_end(0, writer)?;

// Generate Deserialize
Expand Down Expand Up @@ -106,15 +114,23 @@ fn write_message_serialize<W: Write>(
message: &Message,
writer: &mut W,
emit_fields: bool,
preserve_proto_field_names: bool,
) -> Result<()> {
write_struct_serialize_start(indent, message, writer, emit_fields)?;

for field in &message.fields {
write_serialize_field(resolver, indent, field, writer, emit_fields)?;
write_serialize_field(
resolver,
indent,
field,
writer,
emit_fields,
preserve_proto_field_names,
)?;
}

for one_of in &message.one_ofs {
write_serialize_one_of(indent, resolver, one_of, writer)?;
write_serialize_one_of(indent, resolver, one_of, writer, preserve_proto_field_names)?;
}

write_struct_serialize_end(indent, writer)
Expand Down Expand Up @@ -218,14 +234,21 @@ fn write_serialize_variable<W: Write>(
field: &Field,
variable: Variable<'_>,
writer: &mut W,
preserve_proto_field_names: bool,
) -> Result<()> {
let json_name = field.json_name();
let field_name = if preserve_proto_field_names {
field.name.as_str()
} else {
json_name.as_str()
};
match &field.field_type {
FieldType::Scalar(scalar) => write_serialize_scalar_variable(
indent,
*scalar,
field.field_modifier,
variable,
field.json_name(),
field_name,
writer,
),
FieldType::Enum(path) => {
Expand All @@ -250,7 +273,7 @@ fn write_serialize_variable<W: Write>(
writer,
"{}struct_ser.serialize_field(\"{}\", &v)?;",
Indent(indent),
field.json_name()
field_name,
)
}
FieldType::Map(_, value_type)
Expand Down Expand Up @@ -302,15 +325,15 @@ fn write_serialize_variable<W: Write>(
writer,
"{}struct_ser.serialize_field(\"{}\", &v)?;",
Indent(indent),
field.json_name()
field_name,
)
}
_ => {
writeln!(
writer,
"{}struct_ser.serialize_field(\"{}\", {})?;",
Indent(indent),
field.json_name(),
field_name,
variable.as_ref
)
}
Expand All @@ -322,7 +345,7 @@ fn write_serialize_scalar_variable<W: Write>(
scalar: ScalarType,
field_modifier: FieldModifier,
variable: Variable<'_>,
json_name: String,
field_name: &str,
writer: &mut W,
) -> Result<()> {
let conversion = match scalar {
Expand All @@ -333,7 +356,7 @@ fn write_serialize_scalar_variable<W: Write>(
writer,
"{}struct_ser.serialize_field(\"{}\", {})?;",
Indent(indent),
json_name,
field_name,
variable.as_ref
)
}
Expand All @@ -345,7 +368,7 @@ fn write_serialize_scalar_variable<W: Write>(
writer,
"{}struct_ser.serialize_field(\"{}\", &{}.iter().map({}).collect::<Vec<_>>())?;",
Indent(indent),
json_name,
field_name,
variable.raw,
conversion
)
Expand All @@ -355,7 +378,7 @@ fn write_serialize_scalar_variable<W: Write>(
writer,
"{}struct_ser.serialize_field(\"{}\", {}(&{}).as_str())?;",
Indent(indent),
json_name,
field_name,
conversion,
variable.raw,
)
Expand All @@ -369,6 +392,7 @@ fn write_serialize_field<W: Write>(
field: &Field,
writer: &mut W,
emit_fields: bool,
preserve_proto_field_names: bool,
) -> Result<()> {
let as_ref = format!("&self.{}", field.rust_field_name());
let variable = Variable {
Expand All @@ -379,7 +403,14 @@ fn write_serialize_field<W: Write>(

match &field.field_modifier {
FieldModifier::Required => {
write_serialize_variable(resolver, indent, field, variable, writer)?;
write_serialize_variable(
resolver,
indent,
field,
variable,
writer,
preserve_proto_field_names,
)?;
}
FieldModifier::Optional => {
writeln!(
Expand All @@ -393,14 +424,28 @@ fn write_serialize_field<W: Write>(
as_unref: "*v",
raw: "v",
};
write_serialize_variable(resolver, indent + 1, field, variable, writer)?;
write_serialize_variable(
resolver,
indent + 1,
field,
variable,
writer,
preserve_proto_field_names,
)?;
writeln!(writer, "{}}}", Indent(indent))?;
}
FieldModifier::Repeated | FieldModifier::UseDefault => {
write!(writer, "{}if ", Indent(indent))?;
write_field_empty_predicate(field, writer, emit_fields)?;
writeln!(writer, " {{")?;
write_serialize_variable(resolver, indent + 1, field, variable, writer)?;
write_serialize_variable(
resolver,
indent + 1,
field,
variable,
writer,
preserve_proto_field_names,
)?;
writeln!(writer, "{}}}", Indent(indent))?;
}
}
Expand All @@ -412,6 +457,7 @@ fn write_serialize_one_of<W: Write>(
resolver: &Resolver<'_>,
one_of: &OneOf,
writer: &mut W,
preserve_proto_field_names: bool,
) -> Result<()> {
writeln!(
writer,
Expand All @@ -434,7 +480,14 @@ fn write_serialize_one_of<W: Write>(
as_unref: "*v",
raw: "v",
};
write_serialize_variable(resolver, indent + 3, field, variable, writer)?;
write_serialize_variable(
resolver,
indent + 3,
field,
variable,
writer,
preserve_proto_field_names,
)?;
writeln!(writer, "{}}}", Indent(indent + 2))?;
}

Expand Down Expand Up @@ -610,14 +663,26 @@ fn write_deserialize_field_name<W: Write>(
) -> Result<()> {
let fields: Vec<_> = message
.all_fields()
.map(|field| (field.json_name(), field.rust_type_name()))
.map(|field| {
let json_name = field.json_name();
// only carry the original proto name if it's different from the provided json name
let proto_name =
Some(field.name.as_str()).filter(|proto_name| proto_name != &json_name);
(json_name, field.rust_type_name(), proto_name)
})
.collect();

write_fields_array(writer, indent, fields.iter().map(|(name, _)| name.as_str()))?;
write_fields_array(
writer,
indent,
fields.iter().flat_map(|(json_name, _, proto_name)| {
proto_name.iter().copied().chain([json_name.as_str()])
}),
)?;
write_fields_enum(
writer,
indent,
fields.iter().map(|(_, name)| name.as_str()),
fields.iter().map(|(_, type_name, _)| type_name.as_str()),
ignore_unknown_fields,
)?;

Expand Down Expand Up @@ -647,14 +712,25 @@ fn write_deserialize_field_name<W: Write>(

if !fields.is_empty() {
writeln!(writer, "{}match value {{", Indent(indent + 4))?;
for (json_name, type_name) in &fields {
writeln!(
writer,
"{}\"{}\" => Ok(GeneratedField::{}),",
Indent(indent + 5),
json_name,
type_name
)?;
for (json_name, type_name, proto_name) in &fields {
if let Some(proto_name) = proto_name {
writeln!(
writer,
"{}\"{}\" | \"{}\" => Ok(GeneratedField::{}),",
Indent(indent + 5),
json_name,
proto_name,
type_name
)?;
} else {
writeln!(
writer,
"{}\"{}\" => Ok(GeneratedField::{}),",
Indent(indent + 5),
json_name,
type_name
)?;
}
}
if ignore_unknown_fields {
writeln!(
Expand Down
9 changes: 9 additions & 0 deletions pbjson-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ pub struct Builder {
btree_map_paths: Vec<String>,
emit_fields: bool,
use_integers_for_enums: bool,
preserve_proto_field_names: bool,
}

impl Builder {
Expand Down Expand Up @@ -191,6 +192,13 @@ impl Builder {
self
}

/// Output fields with their original names as defined in their proto schemas, instead of
/// lowerCamelCase
pub fn preserve_proto_field_names(&mut self) -> &mut Self {
self.preserve_proto_field_names = true;
self
}

/// Generates code for all registered types where `prefixes` contains a prefix of
/// the fully-qualified path of the type
pub fn build<S: AsRef<str>>(&mut self, prefixes: &[S]) -> Result<()> {
Expand Down Expand Up @@ -279,6 +287,7 @@ impl Builder {
self.ignore_unknown_fields,
&self.btree_map_paths,
self.emit_fields,
self.preserve_proto_field_names,
)?
}
}
Expand Down
1 change: 1 addition & 0 deletions pbjson-test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ ignore-unknown-fields = []
btree = []
emit-fields = []
use-integers-for-enums = []
preserve-proto-field-names = []

[dev-dependencies]
chrono = "0.4"
Expand Down
4 changes: 4 additions & 0 deletions pbjson-test/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ fn main() -> Result<()> {
builder.use_integers_for_enums();
}

if cfg!(feature = "preserve-proto-field-names") {
builder.preserve_proto_field_names();
}

builder.build(&[".test"])?;

Ok(())
Expand Down
Loading

0 comments on commit 2424a4a

Please sign in to comment.