Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include Message Descriptor information #336

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions prost-build/src/code_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ impl<'a> CodeGenerator<'a> {
debug!(" message: {:?}", message.name());

let message_name = message.name().to_string();
let package_name = self.package.clone();
let fq_message_name = format!(
"{}{}.{}",
if self.package.is_empty() { "" } else { "." },
Expand Down Expand Up @@ -187,6 +188,9 @@ impl<'a> CodeGenerator<'a> {
self.buf
.push_str("#[derive(Clone, PartialEq, ::prost::Message)]\n");
self.push_indent();
self.buf
.push_str(format!("#[prost(package=\"{}\")]\n", package_name).as_str());
self.push_indent();
self.buf.push_str("pub struct ");
self.buf.push_str(&to_upper_camel(&message_name));
self.buf.push_str(" {\n");
Expand Down
2 changes: 1 addition & 1 deletion prost-derive/src/field/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ impl fmt::Display for Label {
}

/// Get the items belonging to the 'prost' list attribute, e.g. `#[prost(foo, bar="baz")]`.
fn prost_attrs(attrs: Vec<Attribute>) -> Vec<Meta> {
pub(crate) fn prost_attrs(attrs: Vec<Attribute>) -> Vec<Meta> {
attrs
.iter()
.flat_map(Attribute::parse_meta)
Expand Down
30 changes: 28 additions & 2 deletions prost-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ use proc_macro2::Span;
use quote::quote;
use syn::{
punctuated::Punctuated, Data, DataEnum, DataStruct, DeriveInput, Expr, Fields, FieldsNamed,
FieldsUnnamed, Ident, Variant,
FieldsUnnamed, Ident, Meta, Variant,
};

mod field;
use crate::field::Field;
use crate::field::{prost_attrs, Field};

fn try_message(input: TokenStream) -> Result<TokenStream, Error> {
let input: DeriveInput = syn::parse(input)?;
Expand All @@ -29,6 +29,20 @@ fn try_message(input: TokenStream) -> Result<TokenStream, Error> {
Data::Union(..) => bail!("Message can not be derived for a union"),
};

let pkg_name = prost_attrs(input.attrs.clone())
.iter()
.find(|meta| meta.path().is_ident("package"))
.and_then(|meta| match meta {
Meta::NameValue(v) => match &v.lit {
syn::Lit::Str(lit) => Some(lit.value().clone()),
_ => None,
},
_ => None,
})
.unwrap_or_else(|| String::from("prost"));

let type_url = format!("type.googleapis.com/{}.{}", pkg_name, ident);

let generics = &input.generics;
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();

Expand Down Expand Up @@ -204,6 +218,18 @@ fn try_message(input: TokenStream) -> Result<TokenStream, Error> {
}
}

impl #impl_generics ::prost::MessageDescriptor for #ident #ty_generics #where_clause {
fn message_name(&self) -> &'static str {
stringify!(#ident)
}
fn package_name(&self) -> &'static str {
#pkg_name
}
fn type_url(&self) -> &'static str {
#type_url
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the above methods should be associated functions instead. Someone will be able to use Foo::type_url() instead of constructing Foo and then calling the method.

For example this is how pack/unpack to Any will be implemented with associated functions:

fn pack_to_any<M>(msg: M) -> prost_types::Any
where
    M: prost::Message + prost::MessageDescriptor,
{
    prost_types::Any {
        type_url: M::type_url().to_owned(),
        value: msg.encode_to_vec(),
    }
}

fn unpack_from_any<M>(msg: prost_types::Any) -> Option<M>
where
    M: prost::Message + prost::MessageDescriptor + Default,
{
    if msg.type_url == M::type_url() {
        Some(M::decode(&msg.value[..]).ok()?)
    } else {
        None
    }
}


impl #impl_generics ::core::default::Default for #ident #ty_generics #where_clause {
fn default() -> Self {
#ident {
Expand Down
4 changes: 4 additions & 0 deletions prost-types/src/compiler.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/// The version number of protocol compiler.
#[derive(Clone, PartialEq, ::prost::Message)]
#[prost(package="google.protobuf.compiler")]
pub struct Version {
#[prost(int32, optional, tag="1")]
pub major: ::core::option::Option<i32>,
Expand All @@ -14,6 +15,7 @@ pub struct Version {
}
/// An encoded CodeGeneratorRequest is written to the plugin's stdin.
#[derive(Clone, PartialEq, ::prost::Message)]
#[prost(package="google.protobuf.compiler")]
pub struct CodeGeneratorRequest {
/// The .proto files that were explicitly listed on the command-line. The
/// code generator should generate code only for these files. Each file's
Expand Down Expand Up @@ -45,6 +47,7 @@ pub struct CodeGeneratorRequest {
}
/// The plugin writes an encoded CodeGeneratorResponse to stdout.
#[derive(Clone, PartialEq, ::prost::Message)]
#[prost(package="google.protobuf.compiler")]
pub struct CodeGeneratorResponse {
/// Error message. If non-empty, code generation failed. The plugin process
/// should exit with status code zero even if it reports an error in this way.
Expand All @@ -67,6 +70,7 @@ pub struct CodeGeneratorResponse {
pub mod code_generator_response {
/// Represents a single generated file.
#[derive(Clone, PartialEq, ::prost::Message)]
#[prost(package="google.protobuf.compiler.CodeGeneratorResponse")]
pub struct File {
/// The file name, relative to the output directory. The name must not
/// contain "." or ".." components and must be relative, not be absolute (so,
Expand Down
Loading