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

WIP: Add json (serde) support #1081

Draft
wants to merge 30 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
4674b34
feat: add serde support
cynecx Jun 2, 2024
b726394
Move built-in serialization impls to main prost to avoid orphan check…
cynecx Jun 15, 2024
73c4b38
Don't encode empty message in new any repr
cynecx Jun 15, 2024
70160a9
Cover old len/buffer checks in new roundtrip checker
cynecx Jun 15, 2024
962ea03
Cleanup roundtrip testing
cynecx Jun 15, 2024
5413e05
clippy
cynecx Jun 15, 2024
5d9e663
Cleanup cargo features
cynecx Jun 15, 2024
0a3c569
Fix import typo
cynecx Jun 15, 2024
2e977f0
Bump to min required itertools
cynecx Jun 18, 2024
5400096
Address warning with MSRV toolchain
cynecx Jun 18, 2024
976e3b2
Format Cargo.tomls
cynecx Jun 18, 2024
23a4b3a
Don't include serde in default features + enable serde impls in tests
cynecx Jun 18, 2024
ffd5be3
Format Cargo.tomls
cynecx Jun 18, 2024
c3f9672
Fix tests failures
cynecx Jun 18, 2024
8778f3e
Keep previous Any impl exposed
cynecx Aug 22, 2024
a52d4fc
codegen: fix additional indent
cynecx Aug 22, 2024
a544538
more conformance fixes to oneof handling and nan/inf serialization
cynecx Nov 22, 2024
f297fb8
support protobuf's json_name override option in prost-build
cynecx Nov 24, 2024
25fcc10
Add documentation for camelcase json name conversion
cynecx Nov 24, 2024
e19ec2f
fix comment in conformance failing tests
cynecx Nov 24, 2024
5cf3c06
properly parse and convert json fieldmasks + parse NullValue's string…
cynecx Nov 26, 2024
1ee2567
support for ignoring unknown enum values
cynecx Dec 6, 2024
35786dd
address some clippy lints
cynecx Dec 7, 2024
f062b3c
small fixes related to cfg and imports
cynecx Dec 7, 2024
e5b5ea8
enable serde for tests
cynecx Dec 7, 2024
b3f6b79
address doc failures
cynecx Dec 7, 2024
0c87530
make serde module more no_std aware
cynecx Dec 7, 2024
d34a05f
address more clippy lints
cynecx Dec 7, 2024
1b072d9
make prost-types no-std aware
cynecx Dec 7, 2024
167f6c7
make tests more no_std aware
cynecx Dec 8, 2024
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
3 changes: 2 additions & 1 deletion conformance/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ authors.workspace = true
[dependencies]
bytes = "1"
env_logger = { version = "0.11", default-features = false }
prost = { path = "../prost" }
prost = { path = "../prost", features = ["serde", "serde-json"] }
prost-types = { path = "../prost-types", features = ["serde", "any-v2"] }
protobuf = { path = "../protobuf" }
tests = { path = "../tests" }
3 changes: 3 additions & 0 deletions conformance/failing_tests.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# TODO(tokio-rs/prost#2): prost doesn't preserve unknown fields.
Required.Proto2.ProtobufInput.UnknownVarint.ProtobufOutput
Required.Proto3.ProtobufInput.UnknownVarint.ProtobufOutput

# Unsupported right now
Recommended.Proto2.JsonInput.FieldNameExtension.Validator
59 changes: 39 additions & 20 deletions conformance/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,29 @@ use bytes::{Buf, BufMut};
use prost::Message;

use protobuf::conformance::{
conformance_request, conformance_response, ConformanceRequest, ConformanceResponse, WireFormat,
conformance_request, conformance_response, ConformanceRequest, ConformanceResponse,
TestCategory, WireFormat,
};
use protobuf::test_messages::proto2::TestAllTypesProto2;
use protobuf::test_messages::proto3::TestAllTypesProto3;
use tests::{roundtrip, RoundtripResult};
use tests::{roundtrip, RoundtripInput, RoundtripOutputType, RoundtripResult};

fn main() -> io::Result<()> {
env_logger::init();

let mut registry = prost_types::any_v2::TypeRegistry::new_with_well_known_types();
registry.insert_msg_type_for_type_url::<TestAllTypesProto2>(
"type.googleapis.com/protobuf_test_messages.proto2.TestAllTypesProto2",
);
registry.insert_msg_type_for_type_url::<TestAllTypesProto3>(
"type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3",
);

let type_resolver = registry.into_type_resolver();
prost_types::any_v2::with_type_resolver(Some(type_resolver), entrypoint)
}

fn entrypoint() -> io::Result<()> {
let mut bytes = vec![0; 4];

loop {
Expand Down Expand Up @@ -49,17 +64,12 @@ fn main() -> io::Result<()> {
}

fn handle_request(request: ConformanceRequest) -> conformance_response::Result {
match request.requested_output_format() {
let output_ty = match request.requested_output_format() {
WireFormat::Unspecified => {
return conformance_response::Result::ParseError(
"output format unspecified".to_string(),
);
}
WireFormat::Json => {
return conformance_response::Result::Skipped(
"JSON output is not supported".to_string(),
);
}
WireFormat::Jspb => {
return conformance_response::Result::Skipped(
"JSPB output is not supported".to_string(),
Expand All @@ -70,16 +80,13 @@ fn handle_request(request: ConformanceRequest) -> conformance_response::Result {
"TEXT_FORMAT output is not supported".to_string(),
);
}
WireFormat::Protobuf => (),
WireFormat::Protobuf => RoundtripOutputType::Protobuf,
WireFormat::Json => RoundtripOutputType::Json,
};

let buf = match request.payload {
let input = match &request.payload {
None => return conformance_response::Result::ParseError("no payload".to_string()),
Some(conformance_request::Payload::JsonPayload(_)) => {
return conformance_response::Result::Skipped(
"JSON input is not supported".to_string(),
);
}

Some(conformance_request::Payload::JspbPayload(_)) => {
return conformance_response::Result::Skipped(
"JSON input is not supported".to_string(),
Expand All @@ -90,12 +97,20 @@ fn handle_request(request: ConformanceRequest) -> conformance_response::Result {
"JSON input is not supported".to_string(),
);
}
Some(conformance_request::Payload::ProtobufPayload(buf)) => buf,
Some(conformance_request::Payload::ProtobufPayload(buf)) => RoundtripInput::Protobuf(buf),
Some(conformance_request::Payload::JsonPayload(buf)) => RoundtripInput::Json(buf),
};

let roundtrip = match request.message_type.as_str() {
"protobuf_test_messages.proto2.TestAllTypesProto2" => roundtrip::<TestAllTypesProto2>(&buf),
"protobuf_test_messages.proto3.TestAllTypesProto3" => roundtrip::<TestAllTypesProto3>(&buf),
let ignore_unknown_fields =
request.test_category() == TestCategory::JsonIgnoreUnknownParsingTest;

let roundtrip = match &*request.message_type {
"protobuf_test_messages.proto2.TestAllTypesProto2" => {
roundtrip::<TestAllTypesProto2>(input, output_ty, ignore_unknown_fields)
}
"protobuf_test_messages.proto3.TestAllTypesProto3" => {
roundtrip::<TestAllTypesProto3>(input, output_ty, ignore_unknown_fields)
}
_ => {
return conformance_response::Result::ParseError(format!(
"unknown message type: {}",
Expand All @@ -105,7 +120,11 @@ fn handle_request(request: ConformanceRequest) -> conformance_response::Result {
};

match roundtrip {
RoundtripResult::Ok(buf) => conformance_response::Result::ProtobufPayload(buf),
RoundtripResult::Protobuf(buf) => conformance_response::Result::ProtobufPayload(buf),
RoundtripResult::Json(buf) => conformance_response::Result::JsonPayload(buf),
RoundtripResult::EncodeError(error) => {
conformance_response::Result::SerializeError(error.to_string())
}
RoundtripResult::DecodeError(error) => {
conformance_response::Result::ParseError(error.to_string())
}
Expand Down
4 changes: 2 additions & 2 deletions fuzz/afl/proto3/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use afl::fuzz;

use protobuf::test_messages::proto3::TestAllTypesProto3;
use tests::roundtrip;
use tests::roundtrip_proto;

fn main() {
fuzz!(|data: &[u8]| {
let _ = roundtrip::<TestAllTypesProto3>(data).unwrap_error();
let _ = roundtrip_proto::<TestAllTypesProto3>(data).unwrap_error();
});
}
4 changes: 2 additions & 2 deletions fuzz/afl/proto3/src/reproduce.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use protobuf::test_messages::proto3::TestAllTypesProto3;
use tests::roundtrip;
use tests::roundtrip_proto;

fn main() {
let args: Vec<String> = std::env::args().collect();
Expand All @@ -9,5 +9,5 @@ fn main() {
}

let data = std::fs::read(&args[1]).expect(&format!("Could not open file {}", args[1]));
let _ = roundtrip::<TestAllTypesProto3>(&data).unwrap_error();
let _ = roundtrip_proto::<TestAllTypesProto3>(&data).unwrap_error();
}
4 changes: 2 additions & 2 deletions fuzz/fuzzers/proto2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

use libfuzzer_sys::fuzz_target;
use protobuf::test_messages::proto2::TestAllTypesProto2;
use tests::roundtrip;
use tests::roundtrip_proto;

fuzz_target!(|data: &[u8]| {
let _ = roundtrip::<TestAllTypesProto2>(data).unwrap_error();
let _ = roundtrip_proto::<TestAllTypesProto2>(data).unwrap_error();
});
4 changes: 2 additions & 2 deletions fuzz/fuzzers/proto3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

use libfuzzer_sys::fuzz_target;
use protobuf::test_messages::proto3::TestAllTypesProto3;
use tests::roundtrip;
use tests::roundtrip_proto;

fuzz_target!(|data: &[u8]| {
let _ = roundtrip::<TestAllTypesProto3>(data).unwrap_error();
let _ = roundtrip_proto::<TestAllTypesProto3>(data).unwrap_error();
});
1 change: 1 addition & 0 deletions prost-build/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ prost-types = { version = "0.13.3", path = "../prost-types", default-features =
tempfile = "3"
once_cell = "1.17.1"
regex = { version = "1.8.1", default-features = false, features = ["std", "unicode-bool"] }
indexmap = "2.1.0"

# feature: format
prettyplease = { version = "0.2", optional = true }
Expand Down
Loading
Loading