Skip to content

Commit

Permalink
Merge pull request #1 from ryankurte/fix/revert-7940dfd-#502
Browse files Browse the repository at this point in the history
Fix/revert 7940dfd tokio-rs#502
  • Loading branch information
subashch6 authored Aug 20, 2021
2 parents 32bc87c + 9d1ef8a commit 5352bb1
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 326 deletions.
5 changes: 2 additions & 3 deletions conformance/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,8 @@ fn main() -> io::Result<()> {
Err(error) => conformance_response::Result::ParseError(format!("{:?}", error)),
};

let response = ConformanceResponse {
result: Some(result),
};
let mut response = ConformanceResponse::default();
response.result = Some(result);

let len = response.encoded_len();
bytes.clear();
Expand Down
151 changes: 68 additions & 83 deletions prost-build/src/code_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,31 @@ use prost_types::{

use crate::ast::{Comments, Method, Service};
use crate::extern_paths::ExternPaths;
use crate::ident::{to_snake, to_upper_camel};
use crate::ident::{match_ident, to_snake, to_upper_camel};
use crate::message_graph::MessageGraph;
use crate::{BytesType, Config, MapType};
use crate::Config;

#[derive(PartialEq)]
enum Syntax {
Proto2,
Proto3,
}

#[derive(PartialEq)]
enum BytesTy {
Vec,
Bytes,
}

impl BytesTy {
fn as_str(&self) -> &'static str {
match self {
BytesTy::Vec => "\"vec\"",
BytesTy::Bytes => "\"bytes\"",
}
}
}

pub struct CodeGenerator<'a> {
config: &'a mut Config,
package: String,
Expand Down Expand Up @@ -252,25 +267,24 @@ impl<'a> CodeGenerator<'a> {
fn append_type_attributes(&mut self, fq_message_name: &str) {
assert_eq!(b'.', fq_message_name.as_bytes()[0]);
// TODO: this clone is dirty, but expedious.
if let Some(attributes) = self.config.type_attributes.get(fq_message_name).cloned() {
self.push_indent();
self.buf.push_str(&attributes);
self.buf.push('\n');
for (matcher, attribute) in self.config.type_attributes.clone() {
if match_ident(&matcher, fq_message_name, None) {
self.push_indent();
self.buf.push_str(&attribute);
self.buf.push('\n');
}
}
}

fn append_field_attributes(&mut self, fq_message_name: &str, field_name: &str) {
assert_eq!(b'.', fq_message_name.as_bytes()[0]);
// TODO: this clone is dirty, but expedious.
if let Some(attributes) = self
.config
.field_attributes
.get_field(fq_message_name, field_name)
.cloned()
{
self.push_indent();
self.buf.push_str(&attributes);
self.buf.push('\n');
for (matcher, attribute) in self.config.field_attributes.clone() {
if match_ident(&matcher, fq_message_name, Some(field_name)) {
self.push_indent();
self.buf.push_str(&attribute);
self.buf.push('\n');
}
}
}

Expand Down Expand Up @@ -307,14 +321,9 @@ impl<'a> CodeGenerator<'a> {
self.buf.push_str(&type_tag);

if type_ == Type::Bytes {
let bytes_type = self
.config
.bytes_type
.get_field(fq_message_name, field.name())
.copied()
.unwrap_or_default();
self.buf.push('=');
self.buf
.push_str(&format!("={:?}", bytes_type.annotation()));
.push_str(self.bytes_backing_type(&field, fq_message_name).as_str());
}

match field.label() {
Expand Down Expand Up @@ -419,28 +428,34 @@ impl<'a> CodeGenerator<'a> {
self.append_doc(fq_message_name, Some(field.name()));
self.push_indent();

let map_type = self
let btree_map = self
.config
.map_type
.get_field(fq_message_name, field.name())
.copied()
.unwrap_or_default();
.btree_map
.iter()
.any(|matcher| match_ident(matcher, fq_message_name, Some(field.name())));
let (annotation_ty, lib_name, rust_ty) = if btree_map {
("btree_map", "::prost::alloc::collections", "BTreeMap")
} else {
("map", "::std::collections", "HashMap")
};

let key_tag = self.field_type_tag(key);
let value_tag = self.map_value_type_tag(value);

self.buf.push_str(&format!(
"#[prost({}=\"{}, {}\", tag=\"{}\")]\n",
map_type.annotation(),
annotation_ty,
key_tag,
value_tag,
field.number()
));
self.append_field_attributes(fq_message_name, field.name());
self.push_indent();
self.buf.push_str(&format!(
"pub {}: {}<{}, {}>,\n",
"pub {}: {}::{}<{}, {}>,\n",
to_snake(field.name()),
map_type.rust_type(),
lib_name,
rust_ty,
key_ty,
value_ty
));
Expand Down Expand Up @@ -562,15 +577,12 @@ impl<'a> CodeGenerator<'a> {
}

fn append_doc(&mut self, fq_name: &str, field_name: Option<&str>) {
let append_doc = if let Some(field_name) = field_name {
self.config
.disable_comments
.get_field(fq_name, field_name)
.is_none()
} else {
self.config.disable_comments.get(fq_name).is_none()
};
if append_doc {
if !self
.config
.disable_comments
.iter()
.any(|matcher| match_ident(matcher, fq_name, field_name))
{
Comments::from_location(self.location()).append_with_indent(self.depth, &mut self.buf)
}
}
Expand Down Expand Up @@ -744,14 +756,10 @@ impl<'a> CodeGenerator<'a> {
Type::Int64 | Type::Sfixed64 | Type::Sint64 => String::from("i64"),
Type::Bool => String::from("bool"),
Type::String => String::from("::prost::alloc::string::String"),
Type::Bytes => self
.config
.bytes_type
.get_field(fq_message_name, field.name())
.copied()
.unwrap_or_default()
.rust_type()
.to_owned(),
Type::Bytes => match self.bytes_backing_type(field, fq_message_name) {
BytesTy::Bytes => String::from("::prost::bytes::Bytes"),
BytesTy::Vec => String::from("::prost::alloc::vec::Vec<u8>"),
},
Type::Group | Type::Message => self.resolve_ident(field.type_name()),
}
}
Expand Down Expand Up @@ -834,6 +842,19 @@ impl<'a> CodeGenerator<'a> {
}
}

fn bytes_backing_type(&self, field: &FieldDescriptorProto, fq_message_name: &str) -> BytesTy {
let bytes = self
.config
.bytes
.iter()
.any(|matcher| match_ident(matcher, fq_message_name, Some(field.name())));
if bytes {
BytesTy::Bytes
} else {
BytesTy::Vec
}
}

/// Returns `true` if the field options includes the `deprecated` option.
fn deprecated(&self, field: &FieldDescriptorProto) -> bool {
field
Expand Down Expand Up @@ -995,42 +1016,6 @@ fn strip_enum_prefix<'a>(prefix: &str, name: &'a str) -> &'a str {
}
}

impl MapType {
/// The `prost-derive` annotation type corresponding to the map type.
fn annotation(&self) -> &'static str {
match self {
MapType::HashMap => "map",
MapType::BTreeMap => "btree_map",
}
}

/// The fully-qualified Rust type corresponding to the map type.
fn rust_type(&self) -> &'static str {
match self {
MapType::HashMap => "::std::collections::HashMap",
MapType::BTreeMap => "::prost::alloc::collections::BTreeMap",
}
}
}

impl BytesType {
/// The `prost-derive` annotation type corresponding to the bytes type.
fn annotation(&self) -> &'static str {
match self {
BytesType::Vec => "vec",
BytesType::Bytes => "bytes",
}
}

/// The fully-qualified Rust type corresponding to the bytes type.
fn rust_type(&self) -> &'static str {
match self {
BytesType::Vec => "::prost::alloc::vec::Vec<u8>",
BytesType::Bytes => "::prost::bytes::Bytes",
}
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
74 changes: 74 additions & 0 deletions prost-build/src/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,40 @@ pub fn to_upper_camel(s: &str) -> String {
ident
}

/// Matches a 'matcher' against a fully qualified identifier.
pub fn match_ident(matcher: &str, fq_name: &str, field_name: Option<&str>) -> bool {
assert_eq!(b'.', fq_name.as_bytes()[0]);

if matcher.is_empty() {
return false;
} else if matcher == "." {
return true;
}

let match_paths = matcher.split('.').collect::<Vec<_>>();
let field_paths = {
let mut paths = fq_name.split('.').collect::<Vec<_>>();
if let Some(field_name) = field_name {
paths.push(field_name);
}
paths
};

if &matcher[..1] == "." {
// Prefix match.
if match_paths.len() > field_paths.len() {
false
} else {
match_paths[..] == field_paths[..match_paths.len()]
}
// Suffix match.
} else if match_paths.len() > field_paths.len() {
false
} else {
match_paths[..] == field_paths[field_paths.len() - match_paths.len()..]
}
}

#[cfg(test)]
mod tests {

Expand Down Expand Up @@ -159,4 +193,44 @@ mod tests {
assert_eq!("FuzzBuster", &to_upper_camel("FuzzBuster"));
assert_eq!("Self_", &to_upper_camel("self"));
}

#[test]
fn test_match_ident() {
// Prefix matches
assert!(match_ident(".", ".foo.bar.Baz", Some("buzz")));
assert!(match_ident(".foo", ".foo.bar.Baz", Some("buzz")));
assert!(match_ident(".foo.bar", ".foo.bar.Baz", Some("buzz")));
assert!(match_ident(".foo.bar.Baz", ".foo.bar.Baz", Some("buzz")));
assert!(match_ident(
".foo.bar.Baz.buzz",
".foo.bar.Baz",
Some("buzz")
));

assert!(!match_ident(".fo", ".foo.bar.Baz", Some("buzz")));
assert!(!match_ident(".foo.", ".foo.bar.Baz", Some("buzz")));
assert!(!match_ident(".buzz", ".foo.bar.Baz", Some("buzz")));
assert!(!match_ident(".Baz.buzz", ".foo.bar.Baz", Some("buzz")));

// Suffix matches
assert!(match_ident("buzz", ".foo.bar.Baz", Some("buzz")));
assert!(match_ident("Baz.buzz", ".foo.bar.Baz", Some("buzz")));
assert!(match_ident("bar.Baz.buzz", ".foo.bar.Baz", Some("buzz")));
assert!(match_ident(
"foo.bar.Baz.buzz",
".foo.bar.Baz",
Some("buzz")
));

assert!(!match_ident("buz", ".foo.bar.Baz", Some("buzz")));
assert!(!match_ident("uz", ".foo.bar.Baz", Some("buzz")));

// Type names
assert!(match_ident("Baz", ".foo.bar.Baz", None));
assert!(match_ident(".", ".foo.bar.Baz", None));
assert!(match_ident(".foo.bar", ".foo.bar.Baz", None));
assert!(match_ident(".foo.bar.Baz", ".foo.bar.Baz", None));
assert!(!match_ident(".fo", ".foo.bar.Baz", None));
assert!(!match_ident(".buzz.Baz", ".foo.bar.Baz", None));
}
}
Loading

0 comments on commit 5352bb1

Please sign in to comment.