Skip to content

Commit

Permalink
Tuple struct support (#706)
Browse files Browse the repository at this point in the history
Co-authored-by: Lucio Franco <luciofranco14@gmail.com>
  • Loading branch information
ldm0 and LucioFranco committed Sep 28, 2022
1 parent 7b9d55b commit a1a3603
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 43 deletions.
3 changes: 1 addition & 2 deletions prost-build/src/ident.rs
Expand Up @@ -77,8 +77,7 @@ mod tests {
assert_eq!("field_name9", &to_snake("field_Name9"));
assert_eq!("field_name10", &to_snake("Field_Name10"));

// TODO(withoutboats/heck#3)
//assert_eq!("field_name11", &to_snake("FIELD_NAME11"));
assert_eq!("field_name11", &to_snake("FIELD_NAME11"));
assert_eq!("field_name12", &to_snake("FIELD_name12"));
assert_eq!("field_name13", &to_snake("__field_name13"));
assert_eq!("field_name14", &to_snake("__Field_name14"));
Expand Down
2 changes: 1 addition & 1 deletion prost-derive/src/field/map.rs
Expand Up @@ -257,7 +257,7 @@ impl Field {
}

/// Returns methods to embed in the message.
pub fn methods(&self, ident: &Ident) -> Option<TokenStream> {
pub fn methods(&self, ident: &TokenStream) -> Option<TokenStream> {
if let ValueTy::Scalar(scalar::Ty::Enumeration(ty)) = &self.value_ty {
let key_ty = self.key_ty.rust_type();
let key_ref_ty = self.key_ty.rust_ref_type();
Expand Down
4 changes: 2 additions & 2 deletions prost-derive/src/field/mod.rs
Expand Up @@ -10,7 +10,7 @@ use std::slice;
use anyhow::{bail, Error};
use proc_macro2::TokenStream;
use quote::quote;
use syn::{Attribute, Ident, Lit, LitBool, Meta, MetaList, MetaNameValue, NestedMeta};
use syn::{Attribute, Lit, LitBool, Meta, MetaList, MetaNameValue, NestedMeta};

#[derive(Clone)]
pub enum Field {
Expand Down Expand Up @@ -164,7 +164,7 @@ impl Field {
}
}

pub fn methods(&self, ident: &Ident) -> Option<TokenStream> {
pub fn methods(&self, ident: &TokenStream) -> Option<TokenStream> {
match *self {
Field::Scalar(ref scalar) => scalar.methods(ident),
Field::Map(ref map) => map.methods(ident),
Expand Down
23 changes: 17 additions & 6 deletions prost-derive/src/field/scalar.rs
Expand Up @@ -4,7 +4,9 @@ use std::fmt;
use anyhow::{anyhow, bail, Error};
use proc_macro2::{Span, TokenStream};
use quote::{quote, ToTokens, TokenStreamExt};
use syn::{parse_str, Ident, Lit, LitByteStr, Meta, MetaList, MetaNameValue, NestedMeta, Path};
use syn::{
parse_str, Ident, Index, Lit, LitByteStr, Meta, MetaList, MetaNameValue, NestedMeta, Path,
};

use crate::field::{bool_attr, set_option, tag_attr, Label};

Expand Down Expand Up @@ -267,12 +269,21 @@ impl Field {
}

/// Returns methods to embed in the message.
pub fn methods(&self, ident: &Ident) -> Option<TokenStream> {
pub fn methods(&self, ident: &TokenStream) -> Option<TokenStream> {
let mut ident_str = ident.to_string();
if ident_str.starts_with("r#") {
ident_str = ident_str[2..].to_owned();
}

// Prepend `get_` for getter methods of tuple structs.
let get = match syn::parse_str::<Index>(&ident_str) {
Ok(index) => {
let get = Ident::new(&format!("get_{}", index.index), Span::call_site());
quote!(#get)
}
Err(_) => quote!(#ident),
};

if let Ty::Enumeration(ref ty) = self.ty {
let set = Ident::new(&format!("set_{}", ident_str), Span::call_site());
let set_doc = format!("Sets `{}` to the provided enum value.", ident_str);
Expand All @@ -285,7 +296,7 @@ impl Field {
);
quote! {
#[doc=#get_doc]
pub fn #ident(&self) -> #ty {
pub fn #get(&self) -> #ty {
#ty::from_i32(self.#ident).unwrap_or(#default)
}

Expand All @@ -303,7 +314,7 @@ impl Field {
);
quote! {
#[doc=#get_doc]
pub fn #ident(&self) -> #ty {
pub fn #get(&self) -> #ty {
self.#ident.and_then(#ty::from_i32).unwrap_or(#default)
}

Expand All @@ -322,7 +333,7 @@ impl Field {
let push_doc = format!("Appends the provided enum value to `{}`.", ident_str);
quote! {
#[doc=#iter_doc]
pub fn #ident(&self) -> ::core::iter::FilterMap<
pub fn #get(&self) -> ::core::iter::FilterMap<
::core::iter::Cloned<::core::slice::Iter<i32>>,
fn(i32) -> ::core::option::Option<#ty>,
> {
Expand Down Expand Up @@ -351,7 +362,7 @@ impl Field {

Some(quote! {
#[doc=#get_doc]
pub fn #ident(&self) -> #ty {
pub fn #get(&self) -> #ty {
match self.#ident {
#match_some
::core::option::Option::None => #default,
Expand Down
52 changes: 32 additions & 20 deletions prost-derive/src/lib.rs
Expand Up @@ -12,7 +12,7 @@ use proc_macro2::Span;
use quote::quote;
use syn::{
punctuated::Punctuated, Data, DataEnum, DataStruct, DeriveInput, Expr, Fields, FieldsNamed,
FieldsUnnamed, Ident, Variant,
FieldsUnnamed, Ident, Index, Variant,
};

mod field;
Expand All @@ -32,32 +32,36 @@ fn try_message(input: TokenStream) -> Result<TokenStream, Error> {
let generics = &input.generics;
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();

let fields = match variant_data {
let (is_struct, fields) = match variant_data {
DataStruct {
fields: Fields::Named(FieldsNamed { named: fields, .. }),
..
}
| DataStruct {
} => (true, fields.into_iter().collect()),
DataStruct {
fields:
Fields::Unnamed(FieldsUnnamed {
unnamed: fields, ..
}),
..
} => fields.into_iter().collect(),
} => (false, fields.into_iter().collect()),
DataStruct {
fields: Fields::Unit,
..
} => Vec::new(),
} => (false, Vec::new()),
};

let mut next_tag: u32 = 1;
let mut fields = fields
.into_iter()
.enumerate()
.flat_map(|(idx, field)| {
let field_ident = field
.ident
.unwrap_or_else(|| Ident::new(&idx.to_string(), Span::call_site()));
.flat_map(|(i, field)| {
let field_ident = field.ident.map(|x| quote!(#x)).unwrap_or_else(|| {
let index = Index {
index: i as u32,
span: Span::call_site(),
};
quote!(#index)
});
match Field::new(field.attrs, Some(next_tag)) {
Ok(Some(field)) => {
next_tag = field.tags().iter().max().map(|t| t + 1).unwrap_or(next_tag);
Expand Down Expand Up @@ -124,17 +128,27 @@ fn try_message(input: TokenStream) -> Result<TokenStream, Error> {
)
};

// TODO
let is_struct = true;

let clear = fields
.iter()
.map(|&(ref field_ident, ref field)| field.clear(quote!(self.#field_ident)));

let default = fields.iter().map(|&(ref field_ident, ref field)| {
let value = field.default();
quote!(#field_ident: #value,)
});
let default = if is_struct {
let default = fields.iter().map(|(field_ident, field)| {
let value = field.default();
quote!(#field_ident: #value,)
});
quote! {#ident {
#(#default)*
}}
} else {
let default = fields.iter().map(|(_, field)| {
let value = field.default();
quote!(#value,)
});
quote! {#ident (
#(#default)*
)}
};

let methods = fields
.iter()
Expand Down Expand Up @@ -206,9 +220,7 @@ fn try_message(input: TokenStream) -> Result<TokenStream, Error> {

impl #impl_generics ::core::default::Default for #ident #ty_generics #where_clause {
fn default() -> Self {
#ident {
#(#default)*
}
#default
}
}

Expand Down
3 changes: 0 additions & 3 deletions src/encoding.rs
Expand Up @@ -1603,9 +1603,6 @@ mod test {
#[test]
fn varint() {
fn check(value: u64, mut encoded: &[u8]) {
// TODO(rust-lang/rust-clippy#5494)
#![allow(clippy::clone_double_ref)]

// Small buffer.
let mut buf = Vec::with_capacity(1);
encode_varint(value, &mut buf);
Expand Down
14 changes: 5 additions & 9 deletions tests/src/debug.rs
Expand Up @@ -56,21 +56,17 @@ fn basic() {
);
}

/*
TODO(tokio-rs/prost#56):
/// A special case with a tuple struct
#[test]
fn tuple_struct() {
#[derive(Clone, PartialEq, Message)]
struct NewType(
#[prost(enumeration="BasicEnumeration", tag="5")]
i32,
#[derive(Clone, PartialEq, prost::Message)]
struct NewType(#[prost(enumeration = "BasicEnumeration", tag = "5")] i32);
assert_eq!(
format!("{:?}", NewType(BasicEnumeration::TWO as i32)),
"NewType(TWO)"
);
assert_eq!(format!("{:?}", NewType(BasicEnumeration::TWO as i32)), "NewType(TWO)");
assert_eq!(format!("{:?}", NewType(42)), "NewType(42)");
}
*/

#[derive(Clone, PartialEq, prost::Oneof)]
pub enum OneofWithEnum {
Expand Down

0 comments on commit a1a3603

Please sign in to comment.