Add 'specific' traits for common gencode message operations.

This also changes MessageView and MessageMut to be subtraits of the ViewProxy and MutProxy (which also requires them to have lifetimes now, and a weird extra bounds on ViewProxy)

PiperOrigin-RevId: 654788207
pull/17497/head
Protobuf Team Bot 4 months ago committed by Copybara-Service
parent 84af72713d
commit 6d25846f47
  1. 52
      conformance/conformance_rust.rs
  2. 80
      rust/codegen_traits.rs
  3. 7
      rust/shared.rs
  4. 44
      src/google/protobuf/compiler/rust/message.cc

@ -13,6 +13,7 @@ use protobuf_cpp as kernel;
use protobuf_upb as kernel;
use kernel::Optional::{Set, Unset};
use kernel::{Message, ParseError};
use std::io::{self, ErrorKind, Read, Write};
use test_messages_edition2023_rust_proto::TestAllTypesEdition2023;
@ -73,52 +74,39 @@ fn do_test(req: &ConformanceRequest) -> ConformanceResponse {
Set(bytes) => bytes,
};
fn roundtrip<T: Message>(bytes: &[u8]) -> Result<Vec<u8>, ParseError> {
T::parse(bytes).map(|msg| msg.serialize().unwrap())
}
let serialized = match message_type.as_bytes() {
b"protobuf_test_messages.proto2.TestAllTypesProto2" => {
if let Ok(msg) = TestAllTypesProto2::parse(bytes) {
msg.serialize().unwrap()
} else {
resp.set_parse_error("failed to parse bytes");
return resp;
}
roundtrip::<TestAllTypesProto2>(bytes)
}
b"protobuf_test_messages.proto3.TestAllTypesProto3" => {
if let Ok(msg) = TestAllTypesProto3::parse(bytes) {
msg.serialize().unwrap()
} else {
resp.set_parse_error("failed to parse bytes");
return resp;
}
roundtrip::<TestAllTypesProto3>(bytes)
}
b"protobuf_test_messages.editions.TestAllTypesEdition2023" => {
if let Ok(msg) = TestAllTypesEdition2023::parse(bytes) {
msg.serialize().unwrap()
} else {
resp.set_parse_error("failed to parse bytes");
return resp;
}
roundtrip::<TestAllTypesEdition2023>(bytes)
}
b"protobuf_test_messages.editions.proto2.TestAllTypesProto2" => {
if let Ok(msg) = EditionsTestAllTypesProto2::parse(bytes) {
msg.serialize().unwrap()
} else {
resp.set_parse_error("failed to parse bytes");
return resp;
}
roundtrip::<EditionsTestAllTypesProto2>(bytes)
}
b"protobuf_test_messages.editions.proto3.TestAllTypesProto3" => {
if let Ok(msg) = EditionsTestAllTypesProto3::parse(bytes) {
msg.serialize().unwrap()
} else {
resp.set_parse_error("failed to parse bytes");
return resp;
}
roundtrip::<EditionsTestAllTypesProto3>(bytes)
}
_ => panic!("unexpected msg type {message_type}"),
};
resp.set_protobuf_payload(serialized);
return resp;
match serialized {
Ok(serialized) => {
resp.set_protobuf_payload(serialized);
}
Err(_) => {
resp.set_parse_error("failed to parse bytes");
}
}
resp
}
fn main() {

@ -7,11 +7,83 @@
//! Traits that are implemeted by codegen types.
use crate::Proxied;
use crate::{MutProxied, MutProxy, ViewProxy};
use create::Parse;
use read::Serialize;
use std::fmt::Debug;
use write::ClearAndParse;
pub trait Message: Default + Debug + Proxied + Send + Sync {}
/// A trait that all generated owned message types implement.
pub trait Message: MutProxied
// Create traits:
+ create::Parse + Default
// Read traits:
+ Debug + Serialize
// Write traits:
// TODO: Msg should impl Clear.
+ ClearAndParse
// Thread safety:
+ Send + Sync
// Copy/Clone:
+ Clone
{}
pub trait MessageView: Debug + Send + Sync {}
/// A trait that all generated message views implement.
pub trait MessageView<'msg>: ViewProxy<'msg, Proxied = Self::Message>
// Read traits:
+ Debug + Serialize
// Thread safety:
+ Send + Sync
// Copy/Clone:
+ Copy + Clone
{
#[doc(hidden)]
type Message: Message;
}
pub trait MessageMut: Debug + Sync {}
/// A trait that all generated message muts implement.
pub trait MessageMut<'msg>:
MutProxy<'msg, Proxied = Self::Message>
// Read traits:
+ Debug + Serialize
// Write traits:
// TODO: MsgMut should impl Clear and ClearAndParse.
// Thread safety:
+ Sync
// Copy/Clone: (Neither)
{
#[doc(hidden)]
type Message: Message;
}
/// Operations related to constructing a message. Only owned messages implement
/// these traits.
pub(crate) mod create {
pub trait Parse: Sized {
fn parse(serialized: &[u8]) -> Result<Self, crate::ParseError>;
}
}
/// Operations related to reading some aspect of a message (methods that would
/// have a `&self` receiver on an owned message). Owned messages, views, and
/// muts all implement these traits.
pub(crate) mod read {
pub trait Serialize {
fn serialize(&self) -> Result<Vec<u8>, crate::SerializeError>;
}
}
/// Operations related to mutating a message (methods that would have a `&mut
/// self` receiver on an owned message). Owned messages and muts implement these
/// traits.
pub(crate) mod write {
pub trait Clear {
fn clear(&mut self);
}
pub trait ClearAndParse {
fn clear_and_parse(&mut self, data: &[u8]) -> Result<(), crate::ParseError>;
}
}

@ -22,7 +22,12 @@ use std::fmt;
/// These are the items protobuf users can access directly.
#[doc(hidden)]
pub mod __public {
pub use crate::codegen_traits::{Message, MessageMut, MessageView};
pub use crate::codegen_traits::{
create::Parse,
read::Serialize,
write::{Clear, ClearAndParse},
Message, MessageMut, MessageView,
};
pub use crate::r#enum::{Enum, UnknownEnumValue};
pub use crate::map::{Map, MapIter, MapMut, MapView, ProxiedInMapValue};
pub use crate::optional::Optional;

@ -953,15 +953,33 @@ void GenerateRs(Context& ctx, const Descriptor& msg) {
impl $pb$::Message for $Msg$ {}
impl std::default::Default for $Msg$ {
fn default() -> Self {
Self::new()
}
}
impl $pb$::Parse for $Msg$ {
fn parse(serialized: &[u8]) -> Result<Self, $pb$::ParseError> {
Self::parse(serialized)
}
}
impl std::fmt::Debug for $Msg$ {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
$Msg::debug$
}
}
impl std::default::Default for $Msg$ {
fn default() -> Self {
Self::new()
impl $pb$::Serialize for $Msg$ {
fn serialize(&self) -> Result<Vec<u8>, $pb$::SerializeError> {
self.serialize()
}
}
impl $pb$::ClearAndParse for $Msg$ {
fn clear_and_parse(&mut self, data: &[u8]) -> Result<(), $pb$::ParseError> {
self.clear_and_parse(data)
}
}
@ -990,7 +1008,9 @@ void GenerateRs(Context& ctx, const Descriptor& msg) {
_phantom: $Phantom$<&'msg ()>,
}
impl $pb$::MessageView for $Msg$View<'_> {}
impl<'msg> $pb$::MessageView<'msg> for $Msg$View<'msg> {
type Message = $Msg$;
}
impl std::fmt::Debug for $Msg$View<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@ -998,6 +1018,12 @@ void GenerateRs(Context& ctx, const Descriptor& msg) {
}
}
impl $pb$::Serialize for $Msg$View<'_> {
fn serialize(&self) -> Result<Vec<u8>, $pb$::SerializeError> {
self.serialize()
}
}
#[allow(dead_code)]
impl<'msg> $Msg$View<'msg> {
#[doc(hidden)]
@ -1053,7 +1079,9 @@ void GenerateRs(Context& ctx, const Descriptor& msg) {
inner: $pbr$::MutatorMessageRef<'msg>,
}
impl $pb$::MessageMut for $Msg$Mut<'_> {}
impl<'msg> $pb$::MessageMut<'msg> for $Msg$Mut<'msg> {
type Message = $Msg$;
}
impl std::fmt::Debug for $Msg$Mut<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@ -1061,6 +1089,12 @@ void GenerateRs(Context& ctx, const Descriptor& msg) {
}
}
impl $pb$::Serialize for $Msg$Mut<'_> {
fn serialize(&self) -> Result<Vec<u8>, $pb$::SerializeError> {
self.serialize()
}
}
#[allow(dead_code)]
impl<'msg> $Msg$Mut<'msg> {
#[doc(hidden)]

Loading…
Cancel
Save