Skip to content

Commit

Permalink
feat: support encode zero value in protobuf to adjust to go proto2
Browse files Browse the repository at this point in the history
  • Loading branch information
Ggiggle committed Oct 17, 2024
1 parent f899030 commit b453938
Show file tree
Hide file tree
Showing 10 changed files with 244 additions and 4 deletions.
42 changes: 41 additions & 1 deletion 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
Binary file added examples/.DS_Store
Binary file not shown.
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-zero-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"
4 changes: 4 additions & 0 deletions examples/idl/zero_value.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
message A {
map<string, string> str_map = 1;
map<string, int32> int_map = 2;
}
Binary file added examples/src/.DS_Store
Binary file not shown.
36 changes: 36 additions & 0 deletions examples/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
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 {
str_map: Default::default(),
int_map: Default::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());
}
95 changes: 95 additions & 0 deletions examples/src/zero_value.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
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 int_map: ::pilota::AHashMap<::pilota::FastStr, i32>,
}
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::hash_map::encoded_len(
::pilota::prost::encoding::faststr::encoded_len,
::pilota::prost::encoding::int32::encoded_len,
2,
&self.int_map,
)
}

#[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::hash_map::encode(
::pilota::prost::encoding::faststr::encode,
::pilota::prost::encoding::faststr::encoded_len,
::pilota::prost::encoding::int32::encode,
::pilota::prost::encoding::int32::encoded_len,
2,
&self.int_map,
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.int_map;
::pilota::prost::encoding::hash_map::merge(
::pilota::prost::encoding::faststr::merge,
::pilota::prost::encoding::int32::merge,
&mut _inner_pilota_value,
buf,
ctx,
)
.map_err(|mut error| {
error.push(STRUCT_NAME, stringify!(int_map));
error
})
}
_ => ::pilota::prost::encoding::skip_field(wire_type, tag, buf, ctx),
}
}
}
}
1 change: 1 addition & 0 deletions pilota/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ rand = "0.8"

[features]
unstable = []
pb-encode-zero-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

value assigned to `skip_key` is never read

warning: value assigned to `skip_key` is never read --> pilota/src/prost/encoding.rs:1582:25 | 1582 | let mut skip_key = key == &K::default(); | ^^^^^^^^ ... 1687 | map!(BTreeMap); | -------------- in this macro invocation | = help: maybe it is overwritten before being read? = 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

value assigned to `skip_key` is never read

warning: value assigned to `skip_key` is never read --> pilota/src/prost/encoding.rs:1582:25 | 1582 | let mut skip_key = key == &K::default(); | ^^^^^^^^ ... 1683 | map!(AHashMap); | -------------- in this macro invocation | = help: maybe it is overwritten before being read? = note: `#[warn(unused_assignments)]` 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

value assigned to `skip_val` is never read

warning: value assigned to `skip_val` is never read --> pilota/src/prost/encoding.rs:1583:25 | 1583 | let mut skip_val = val == val_default; | ^^^^^^^^ ... 1687 | map!(BTreeMap); | -------------- in this macro invocation | = help: maybe it is overwritten before being read? = 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

value assigned to `skip_val` is never read

warning: value assigned to `skip_val` is never read --> pilota/src/prost/encoding.rs:1583:25 | 1583 | let mut skip_val = val == val_default; | ^^^^^^^^ ... 1683 | map!(AHashMap); | -------------- in this macro invocation | = help: maybe it is overwritten before being read? = 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")]
{
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 b453938

Please sign in to comment.