Skip to content

Commit

Permalink
feat: support encode zero value in protobuf to adjust to go proto2 (#274
Browse files Browse the repository at this point in the history
)

* feat: support encode zero value in protobuf to adjust to go proto2

* remove unused file

* chore: add test for more type and use a better feature name
  • Loading branch information
Ggiggle authored Oct 17, 2024
1 parent f899030 commit cc9b6c8
Show file tree
Hide file tree
Showing 8 changed files with 251 additions and 6 deletions.
44 changes: 42 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = ["pilota", "pilota-build", "pilota-thrift-parser"]
members = ["pilota", "pilota-build", "pilota-thrift-parser", "examples"]
resolver = "2"

[profile.bench]
Expand Down
58 changes: 58 additions & 0 deletions examples/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
[package]
name = "examples"
version = "0.1.0"
edition = "2021"
description = "Compile thrift and protobuf idl into rust code at compile-time."
homepage = "https://cloudwego.io/docs/pilota/"
repository = "https://github.com/cloudwego/pilota"
license = "MIT OR Apache-2.0"
authors = ["Pilota Team <[email protected]>"]
keywords = ["serialization", "thrift", "protobuf", "volo"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[badges]
maintenance = { status = "actively-developed" }

[dependencies]
pilota = { path = "../pilota", features = ["pb-encode-default-value"] }
pilota-build = { path = "../pilota-build" }
pilota-thrift-parser = { path = "../pilota-thrift-parser", version = "0.11" }

ahash = "0.8"
anyhow = "1"
dashmap = "5"
heck = "0.5"
itertools = "0.13"
normpath = "1"
paste = "1"
petgraph = "0.6"
phf = { version = "0.11", features = ["macros"] }
proc-macro2 = "1"
quote = "1"
rayon = "1"
rustc-hash = "1"
salsa = { version = "0.17.0-pre.2" }
scoped-tls = "1"
serde = { version = "1", features = ["derive"] }
serde_yaml = "0.9"
syn = "2"
toml = "0.8"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }

# The official rust-protobuf parser currently has some bug.
# We will switch to the official one when https://github.com/stepancheg/rust-protobuf/pull/646 is fixed.
protobuf-parse = { package = "protobuf-parse2", version = "4.0.0-alpha.4" }
protobuf = { package = "protobuf2", version = "4.0.0-alpha.2" }
faststr = "0.2"

[dev-dependencies]

tokio = { version = "1", features = ["io-util"] }
derivative = "2"
tempfile = "3"
diffy = "0.4"
criterion = { version = "0.5", features = ["html_reports"] }
rand = "0.8"
linkedbytes = "0.1"
5 changes: 5 additions & 0 deletions examples/idl/zero_value.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
message A {
map<string, string> str_map = 1;
required string s1 = 2;
optional string s2 = 3;
}
33 changes: 33 additions & 0 deletions examples/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use pilota::prost::Message as _;

Check warning on line 1 in examples/src/lib.rs

View workflow job for this annotation

GitHub Actions / clippy

unused import: `pilota::prost::Message as _`

warning: unused import: `pilota::prost::Message as _` --> examples/src/lib.rs:1:5 | 1 | use pilota::prost::Message as _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default

mod zero_value;

#[test]
fn test_pb_encode_zero_value() {
let test_data = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("idl")
.join("zero_value.proto");

let out_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("src")
.join("zero_value.rs");

pilota_build::Builder::protobuf()
.ignore_unused(false)
.include_dirs(vec![test_data.parent().unwrap().to_path_buf()])
.compile_with_config(
vec![pilota_build::IdlService::from_path(test_data.to_path_buf())],
pilota_build::Output::File(out_path.into()),
);

let mut a = zero_value::zero_value::A::default();

a.str_map.insert("key1".into(), "value".into());
a.str_map.insert("key2".into(), "".into());

let mut buf = pilota::BytesMut::new();
a.encode(&mut buf).unwrap();

println!("{:?}", buf);
println!("{:?}", buf.freeze().as_ref());
}
102 changes: 102 additions & 0 deletions examples/src/zero_value.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
pub mod zero_value {
#![allow(warnings, clippy::all)]
#[derive(Debug, Default, Clone, PartialEq)]
pub struct A {
pub str_map: ::pilota::AHashMap<::pilota::FastStr, ::pilota::FastStr>,

pub s1: ::pilota::FastStr,

pub s2: ::std::option::Option<::pilota::FastStr>,
}
impl ::pilota::prost::Message for A {
#[inline]
fn encoded_len(&self) -> usize {
0 + ::pilota::prost::encoding::hash_map::encoded_len(
::pilota::prost::encoding::faststr::encoded_len,
::pilota::prost::encoding::faststr::encoded_len,
1,
&self.str_map,
) + ::pilota::prost::encoding::faststr::encoded_len(2, &self.s1)
+ self.s2.as_ref().map_or(0, |value| {
::pilota::prost::encoding::faststr::encoded_len(3, value)
})
}

#[allow(unused_variables)]
fn encode_raw<B>(&self, buf: &mut B)
where
B: ::pilota::prost::bytes::BufMut,
{
::pilota::prost::encoding::hash_map::encode(
::pilota::prost::encoding::faststr::encode,
::pilota::prost::encoding::faststr::encoded_len,
::pilota::prost::encoding::faststr::encode,
::pilota::prost::encoding::faststr::encoded_len,
1,
&self.str_map,
buf,
);
::pilota::prost::encoding::faststr::encode(2, &self.s1, buf);
if let Some(_pilota_inner_value) = self.s2.as_ref() {
::pilota::prost::encoding::faststr::encode(3, _pilota_inner_value, buf);
};
}

#[allow(unused_variables)]
fn merge_field<B>(
&mut self,
tag: u32,
wire_type: ::pilota::prost::encoding::WireType,
buf: &mut B,
ctx: ::pilota::prost::encoding::DecodeContext,
) -> ::core::result::Result<(), ::pilota::prost::DecodeError>
where
B: ::pilota::prost::bytes::Buf,
{
const STRUCT_NAME: &'static str = stringify!(A);
match tag {
1 => {
let mut _inner_pilota_value = &mut self.str_map;
::pilota::prost::encoding::hash_map::merge(
::pilota::prost::encoding::faststr::merge,
::pilota::prost::encoding::faststr::merge,
&mut _inner_pilota_value,
buf,
ctx,
)
.map_err(|mut error| {
error.push(STRUCT_NAME, stringify!(str_map));
error
})
}
2 => {
let mut _inner_pilota_value = &mut self.s1;
::pilota::prost::encoding::faststr::merge(
wire_type,
_inner_pilota_value,
buf,
ctx,
)
.map_err(|mut error| {
error.push(STRUCT_NAME, stringify!(s1));
error
})
}
3 => {
let mut _inner_pilota_value = &mut self.s2;
::pilota::prost::encoding::faststr::merge(
wire_type,
_inner_pilota_value.get_or_insert_with(::core::default::Default::default),
buf,
ctx,
)
.map_err(|mut error| {
error.push(STRUCT_NAME, stringify!(s2));
error
})
}
_ => ::pilota::prost::encoding::skip_field(wire_type, tag, buf, ctx),
}
}
}
}
3 changes: 2 additions & 1 deletion pilota/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "pilota"
version = "0.11.3"
version = "0.11.4"
edition = "2021"
description = "Pilota is a thrift and protobuf implementation in pure rust with high performance and extensibility."
documentation = "https://docs.rs/pilota"
Expand Down Expand Up @@ -41,6 +41,7 @@ rand = "0.8"

[features]
unstable = []
pb-encode-default-value = []

[[bench]]
name = "faststr"
Expand Down
10 changes: 8 additions & 2 deletions pilota/src/prost/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1579,8 +1579,14 @@ macro_rules! map {
VL: Fn(u32, &V) -> usize,
{
for (key, val) in values.iter() {
let skip_key = key == &K::default();
let skip_val = val == val_default;
let mut skip_key = key == &K::default();

Check warning on line 1582 in pilota/src/prost/encoding.rs

View workflow job for this annotation

GitHub Actions / clippy

variable does not need to be mutable

warning: variable does not need to be mutable --> pilota/src/prost/encoding.rs:1582:21 | 1582 | let mut skip_key = key == &K::default(); | ----^^^^^^^^ | | | help: remove this `mut` ... 1687 | map!(BTreeMap); | -------------- in this macro invocation | = note: this warning originates in the macro `map` (in Nightly builds, run with -Z macro-backtrace for more info)

Check warning on line 1582 in pilota/src/prost/encoding.rs

View workflow job for this annotation

GitHub Actions / clippy

variable does not need to be mutable

warning: variable does not need to be mutable --> pilota/src/prost/encoding.rs:1582:21 | 1582 | let mut skip_key = key == &K::default(); | ----^^^^^^^^ | | | help: remove this `mut` ... 1683 | map!(AHashMap); | -------------- in this macro invocation | = note: `#[warn(unused_mut)]` on by default = note: this warning originates in the macro `map` (in Nightly builds, run with -Z macro-backtrace for more info)
let mut skip_val = val == val_default;

Check warning on line 1583 in pilota/src/prost/encoding.rs

View workflow job for this annotation

GitHub Actions / clippy

variable does not need to be mutable

warning: variable does not need to be mutable --> pilota/src/prost/encoding.rs:1583:21 | 1583 | let mut skip_val = val == val_default; | ----^^^^^^^^ | | | help: remove this `mut` ... 1687 | map!(BTreeMap); | -------------- in this macro invocation | = note: this warning originates in the macro `map` (in Nightly builds, run with -Z macro-backtrace for more info)

Check warning on line 1583 in pilota/src/prost/encoding.rs

View workflow job for this annotation

GitHub Actions / clippy

variable does not need to be mutable

warning: variable does not need to be mutable --> pilota/src/prost/encoding.rs:1583:21 | 1583 | let mut skip_val = val == val_default; | ----^^^^^^^^ | | | help: remove this `mut` ... 1683 | map!(AHashMap); | -------------- in this macro invocation | = note: this warning originates in the macro `map` (in Nightly builds, run with -Z macro-backtrace for more info)

#[cfg(feature = "pb-encode-zero-value")]

Check warning on line 1585 in pilota/src/prost/encoding.rs

View workflow job for this annotation

GitHub Actions / clippy

unexpected `cfg` condition value: `pb-encode-zero-value`

warning: unexpected `cfg` condition value: `pb-encode-zero-value` --> pilota/src/prost/encoding.rs:1585:23 | 1585 | #[cfg(feature = "pb-encode-zero-value")] | ^^^^^^^^^^---------------------- | | | help: there is a expected value with a similar name: `"pb-encode-default-value"` ... 1687 | map!(BTreeMap); | -------------- in this macro invocation | = note: expected values for `feature` are: `pb-encode-default-value` and `unstable` = help: consider adding `pb-encode-zero-value` as a feature in `Cargo.toml` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration = note: this warning originates in the macro `map` (in Nightly builds, run with -Z macro-backtrace for more info)

Check warning on line 1585 in pilota/src/prost/encoding.rs

View workflow job for this annotation

GitHub Actions / clippy

unexpected `cfg` condition value: `pb-encode-zero-value`

warning: unexpected `cfg` condition value: `pb-encode-zero-value` --> pilota/src/prost/encoding.rs:1585:23 | 1585 | #[cfg(feature = "pb-encode-zero-value")] | ^^^^^^^^^^---------------------- | | | help: there is a expected value with a similar name: `"pb-encode-default-value"` ... 1683 | map!(AHashMap); | -------------- in this macro invocation | = note: expected values for `feature` are: `pb-encode-default-value` and `unstable` = help: consider adding `pb-encode-zero-value` as a feature in `Cargo.toml` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration = note: this warning originates in the macro `map` (in Nightly builds, run with -Z macro-backtrace for more info)
{
skip_key = false;
skip_val = false;
}

let len = (if skip_key { 0 } else { key_encoded_len(1, key) })
+ (if skip_val { 0 } else { val_encoded_len(2, val) });
Expand Down

0 comments on commit cc9b6c8

Please sign in to comment.