Implement Msg::parse(&mut self) for V0 API.

PiperOrigin-RevId: 523665442
pull/12402/head
Marcel Hlopko 2 years ago committed by Copybara-Service
parent 1abe2ead1c
commit 390b7f3e6f
  1. 6
      rust/cpp_kernel/cpp.rs
  2. 12
      rust/shared.rs
  3. 28
      rust/test/cpp/interop/main.rs
  4. 10
      rust/test/cpp/interop/test_utils.cc
  5. 16
      src/google/protobuf/compiler/rust/generator.cc

@ -73,6 +73,12 @@ pub struct SerializedData {
// LINT.ThenChange(//depot/google3/third_party/protobuf/rust/cpp_kernel/cpp_api.
// h) copybara:strip_end
impl SerializedData {
pub unsafe fn from_raw_parts(data: NonNull<u8>, len: usize) -> Self {
Self { data, len }
}
}
impl Deref for SerializedData {
type Target = [u8];
fn deref(&self) -> &Self::Target {

@ -40,3 +40,15 @@ pub extern crate upb as __runtime;
pub use __runtime::Arena;
pub use __runtime::SerializedData;
use std::fmt;
/// Represents error during deserialization.
#[derive(Debug, Clone)]
pub struct ParseError;
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Couldn't deserialize given bytes into a proto")
}
}

@ -30,18 +30,36 @@
use std::ptr::NonNull;
macro_rules! assert_serializes_equally {
($msg:ident) => {{
let mut msg = $msg;
let serialized_cpp =
unsafe { Serialize(msg.__unstable_cpp_repr_grant_permission_to_break()) };
let serialized_rs = msg.serialize();
assert_eq!(*serialized_rs, *serialized_cpp);
}};
}
#[test]
fn mutate_message_in_cpp() {
let mut msg = unittest_proto::TestAllTypes::new();
unsafe { MutateInt32Field(msg.__unstable_cpp_repr_grant_permission_to_break()) };
let serialized_msg_from_cpp =
unsafe { Serialize(msg.__unstable_cpp_repr_grant_permission_to_break()) };
assert_eq!(*msg.serialize(), *serialized_msg_from_cpp);
unsafe { MutateInt64Field(msg.__unstable_cpp_repr_grant_permission_to_break()) };
assert_serializes_equally!(msg);
}
#[test]
fn deserialize_message_in_rust() {
let serialized = unsafe { SerializeMutatedInstance() };
let mut msg = unittest_proto::TestAllTypes::new();
msg.deserialize(&serialized).unwrap();
assert_serializes_equally!(msg);
}
// Helper functions invoking C++ Protobuf APIs directly in C++. Defined in
// `//third_party/protobuf/rust/test/cpp/interop:test_utils`.
extern "C" {
fn MutateInt32Field(msg: NonNull<u8>);
fn SerializeMutatedInstance() -> protobuf_cpp::SerializedData;
fn MutateInt64Field(msg: NonNull<u8>);
fn Serialize(msg: NonNull<u8>) -> protobuf_cpp::SerializedData;
}

@ -33,11 +33,17 @@
#include "google/protobuf/rust/cpp_kernel/cpp_api.h"
#include "google/protobuf/unittest.pb.h"
extern "C" void MutateInt32Field(protobuf_unittest::TestAllTypes* msg) {
msg->set_optional_int32(42);
extern "C" void MutateInt64Field(protobuf_unittest::TestAllTypes* msg) {
msg->set_optional_int64(42);
}
extern "C" google::protobuf::rust_internal::SerializedData Serialize(
const protobuf_unittest::TestAllTypes* msg) {
return google::protobuf::rust_internal::SerializeMsg(msg);
}
extern "C" google::protobuf::rust_internal::SerializedData SerializeMutatedInstance() {
protobuf_unittest::TestAllTypes* inst = new protobuf_unittest::TestAllTypes();
MutateInt64Field(inst);
return Serialize(inst);
}

@ -132,11 +132,21 @@ void GenerateForCpp(const FileDescriptor* file, google::protobuf::io::Printer& p
pub fn __unstable_cpp_repr_grant_permission_to_break(&mut self) -> ::__std::ptr::NonNull<u8> {
self.msg
}
pub fn deserialize(&mut self, data: &[u8]) -> Result<(), ::__pb::ParseError> {
let success = unsafe { __rust_proto_thunk__$pkg_Msg$__deserialize(
self.msg,
::__pb::SerializedData::from_raw_parts(
::__std::ptr::NonNull::new(data.as_ptr() as *mut _).unwrap(),
data.len()))
};
success.then_some(()).ok_or(::__pb::ParseError)
}
}
extern "C" {
fn __rust_proto_thunk__$pkg_Msg$__new() -> ::__std::ptr::NonNull<u8>;
fn __rust_proto_thunk__$pkg_Msg$__serialize(raw_msg: ::__std::ptr::NonNull<u8>) -> ::__pb::SerializedData;
fn __rust_proto_thunk__$pkg_Msg$__deserialize(raw_msg: ::__std::ptr::NonNull<u8>, data: ::__pb::SerializedData) -> bool;
}
)rs");
}
@ -159,6 +169,12 @@ void GenerateThunksForCpp(const FileDescriptor* file, google::protobuf::io::Prin
__rust_proto_thunk__$pkg_Msg$__serialize($namespace$::$Msg$* msg) {
return google::protobuf::rust_internal::SerializeMsg(msg);
}
bool __rust_proto_thunk__$pkg_Msg$__deserialize(
$namespace$::$Msg$* msg,
google::protobuf::rust_internal::SerializedData data) {
return msg->ParseFromArray(data.data, data.len);
}
}
)cc");
}

Loading…
Cancel
Save