Skip to content

Commit

Permalink
Update prost utils
Browse files Browse the repository at this point in the history
  • Loading branch information
tinrab committed Dec 22, 2023
1 parent fd0ac5a commit 6144e15
Show file tree
Hide file tree
Showing 22 changed files with 615 additions and 361 deletions.
12 changes: 6 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "bomboni"
version = "0.1.44"
version = "0.1.47"
authors = ["Tin Rabzelj <tin@flinect.com>"]
description = "Utility Library for Rust"
repository = "https://github.com/tinrab/bomboni"
Expand Down Expand Up @@ -38,9 +38,9 @@ tokio = ["bomboni_common/tokio"]
tonic = ["bomboni_proto/tonic", "bomboni_request/tonic"]

[dependencies]
bomboni_common = { path = "bomboni_common", version = "0.1.44" }
bomboni_common = { path = "bomboni_common", version = "0.1.47" }

bomboni_prost = { path = "bomboni_prost", version = "0.1.44", optional = true }
bomboni_proto = { path = "bomboni_proto", version = "0.1.44", optional = true }
bomboni_request = { path = "bomboni_request", version = "0.1.44", optional = true }
bomboni_template = { path = "bomboni_template", version = "0.1.44", optional = true }
bomboni_prost = { path = "bomboni_prost", version = "0.1.47", optional = true }
bomboni_proto = { path = "bomboni_proto", version = "0.1.47", optional = true }
bomboni_request = { path = "bomboni_request", version = "0.1.47", optional = true }
bomboni_template = { path = "bomboni_template", version = "0.1.47", optional = true }
2 changes: 1 addition & 1 deletion bomboni_common/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "bomboni_common"
version = "0.1.44"
version = "0.1.47"
authors = ["Tin Rabzelj <tin@flinect.com>"]
description = "Common things for Bomboni library."
repository = "https://github.com/tinrab/bomboni"
Expand Down
4 changes: 2 additions & 2 deletions bomboni_prost/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "bomboni_prost"
version = "0.1.44"
version = "0.1.47"
authors = ["Tin Rabzelj <tin@flinect.com>"]
description = "Utilities for working with prost. Part of Bomboni library."
repository = "https://github.com/tinrab/bomboni"
Expand All @@ -18,7 +18,7 @@ itertools = "0.12.0"
convert_case = "0.6.0"
prost = "0.12.3"
prost-types = "0.12.3"
proc-macro2 = "1.0.70"
proc-macro2 = "1.0.71"
syn = { version = "2.0.42", features = ["full"] }
quote = "1.0.33"
prettyplease = "0.2.15"
2 changes: 2 additions & 0 deletions bomboni_prost/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub struct ApiConfig {
pub oneof_utility: bool,
pub domain: Option<String>,
pub serde: bool,
pub helpers_mod: Option<String>,
}

impl Default for CompileConfig {
Expand All @@ -43,6 +44,7 @@ impl Default for ApiConfig {
oneof_utility: true,
domain: None,
serde: true,
helpers_mod: None,
}
}
}
23 changes: 16 additions & 7 deletions bomboni_prost/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::utility::str_to_case;
use convert_case::Case;
use itertools::Itertools;
use prost_types::{DescriptorProto, FileDescriptorSet, OneofDescriptorProto};
use syn::ExprPath;
use syn::{ExprPath, PathSegment};

pub struct Context<'a> {
pub config: &'a CompileConfig,
Expand All @@ -13,14 +13,23 @@ pub struct Context<'a> {
}

impl<'a> Context<'a> {
pub fn get_type_ident(&self, name: &str) -> ExprPath {
let mut ident = String::new();
pub fn get_type_expr_path(&self, name: &str) -> ExprPath {
let mut path = String::new();
for parent in &self.path {
ident.push_str(&str_to_case(parent, Case::Snake));
ident.push_str("::");
path.push_str(&str_to_case(parent, Case::Snake));
path.push_str("::");
}
ident.push_str(&str_to_case(name, Case::Pascal));
syn::parse_str::<ExprPath>(&ident).unwrap()
path.push_str(&str_to_case(name, Case::Pascal));
syn::parse_str::<ExprPath>(&path).unwrap()
}

pub fn get_type_expr_relative_path(&self, name: &str, nesting: usize) -> ExprPath {
let mut path = self.get_type_expr_path(name);
let super_ident: PathSegment = syn::parse_str("super").unwrap();
for _ in 0..(nesting + self.path.len()) {
path.path.segments.insert(0, super_ident.clone());
}
path
}

pub fn get_proto_type_name(&self, name: &str) -> String {
Expand Down
37 changes: 4 additions & 33 deletions bomboni_prost/src/enums.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::utility::str_to_case;
use convert_case::Case;
use proc_macro2::{Literal, TokenStream};
use prost_types::EnumDescriptorProto;
use quote::{format_ident, quote};

use crate::context::Context;
use crate::utility::str_to_case;

pub fn write_enum(context: &Context, s: &mut TokenStream, enum_type: &EnumDescriptorProto) {
if context.config.api.names {
Expand All @@ -19,7 +19,7 @@ pub fn write_enum(context: &Context, s: &mut TokenStream, enum_type: &EnumDescri
}

fn write_name(context: &Context, s: &mut TokenStream, enum_type: &EnumDescriptorProto) {
let enum_ident = context.get_type_ident(enum_type.name());
let enum_ident = context.get_type_expr_path(enum_type.name());
let enum_proto_name = context.get_proto_type_name(enum_type.name());
let package_proto_name = Literal::string(&context.package_name);

Expand All @@ -31,7 +31,7 @@ fn write_name(context: &Context, s: &mut TokenStream, enum_type: &EnumDescriptor
}

fn write_value_names(context: &Context, s: &mut TokenStream, enum_type: &EnumDescriptorProto) {
let enum_ident = context.get_type_ident(enum_type.name());
let enum_ident = context.get_type_expr_path(enum_type.name());

let mut value_names = TokenStream::new();
let mut value_names_array = TokenStream::new();
Expand Down Expand Up @@ -62,7 +62,7 @@ fn write_value_names(context: &Context, s: &mut TokenStream, enum_type: &EnumDes
}

fn write_serde(context: &Context, s: &mut TokenStream, enum_type: &EnumDescriptorProto) {
let enum_ident = context.get_type_ident(enum_type.name());
let enum_ident = context.get_type_expr_path(enum_type.name());

// Serialize as string
s.extend(quote! {
Expand Down Expand Up @@ -128,33 +128,4 @@ fn write_serde(context: &Context, s: &mut TokenStream, enum_type: &EnumDescripto
}
}
});

let mod_ident = format_ident!("{}_serde", str_to_case(enum_type.name(), Case::Snake));
s.extend(quote! {
/// Utility for working with i32s in message fields.
/// Usable with #[serde(with = "...")]
pub mod #mod_ident {
use super::*;
use ::serde::{Serialize, Deserialize};

pub fn serialize<S>(
value: &i32,
serializer: S,
) -> Result<<S as ::serde::Serializer>::Ok, <S as ::serde::Serializer>::Error>
where
S: ::serde::Serializer,
{
let value = #enum_ident::try_from(*value).unwrap();
value.serialize(serializer)
}

pub fn deserialize<'de, D>(deserializer: D) -> Result<i32, D::Error>
where
D: ::serde::Deserializer<'de>,
{
let value = #enum_ident::deserialize(deserializer)?;
Ok(value as i32)
}
}
});
}
95 changes: 95 additions & 0 deletions bomboni_prost/src/helpers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
use convert_case::Case;
use proc_macro2::TokenStream;
use prost_types::DescriptorProto;
use prost_types::{EnumDescriptorProto, FileDescriptorProto};
use quote::{format_ident, quote};

use crate::context::Context;
use crate::utility::str_to_case;

pub fn write_helpers(context: &Context, s: &mut TokenStream, files: &[&FileDescriptorProto]) {
let mut src = quote!();
for file in files {
for message in &file.message_type {
write_message_helpers(context, &mut src, message);
}

for enum_type in &file.enum_type {
write_enum_helpers(context, &mut src, enum_type);
}
}

if !src.is_empty() {
let mod_name = if let Some(mod_name) = context.config.api.helpers_mod.as_ref() {
format_ident!("{}", mod_name)
} else {
return;
};
s.extend(quote! {
pub mod #mod_name {
#src
}
});
}
}

fn write_message_helpers(context: &Context, s: &mut TokenStream, message: &DescriptorProto) {
let mut path = context.path.clone();
path.push(message.name.clone().unwrap());
let nested_context = Context {
path: path.clone(),
package_name: context.package_name.clone(),
..*context
};

let mut src = quote!();
for nested_enum in &message.enum_type {
write_enum_helpers(&nested_context, &mut src, nested_enum);
}
for nested_message in &message.nested_type {
write_message_helpers(&nested_context, &mut src, nested_message);
}

if !src.is_empty() {
let mod_name = format_ident!("{}", str_to_case(message.name(), Case::Snake));
s.extend(quote! {
pub mod #mod_name {
#src
}
});
}
}

fn write_enum_helpers(context: &Context, s: &mut TokenStream, enum_type: &EnumDescriptorProto) {
let enum_ident = context.get_type_expr_relative_path(enum_type.name(), 2);

if context.config.api.serde {
let mod_ident = format_ident!("{}_serde", str_to_case(enum_type.name(), Case::Snake));
s.extend(quote! {
/// Utility for working with i32s in message fields.
/// Usable with #[serde(with = "...")]
pub mod #mod_ident {
use ::serde::{Serialize, Deserialize};

pub fn serialize<S>(
value: &i32,
serializer: S,
) -> Result<<S as ::serde::Serializer>::Ok, <S as ::serde::Serializer>::Error>
where
S: ::serde::Serializer,
{
let value = #enum_ident::try_from(*value).unwrap();
value.serialize(serializer)
}

pub fn deserialize<'de, D>(deserializer: D) -> Result<i32, D::Error>
where
D: ::serde::Deserializer<'de>,
{
let value = #enum_ident::deserialize(deserializer)?;
Ok(value as i32)
}
}
});
}
}
Loading

0 comments on commit 6144e15

Please sign in to comment.