Rust protobuf: make `serialize()` method return `Vec<u8>`

`Vec<u8>` is a more idiomatic Rust type to return for serialization.

For the C++ kernel, we are able to return this type with no extra copying. We
still use `SerializedData` type for FFI, but convert the result into a
`Vec<u8>` using a new `into_vec` method.

The upb kernel serializes onto an arena, so for upb we do need to copy the data
to get it into a `Vec<u8>`.

PiperOrigin-RevId: 644444571
pull/17113/head
Adam Cozzette 9 months ago committed by Copybara-Service
parent 2088bc6e66
commit ccbed29c67
  1. 22
      rust/cpp.rs
  2. 2
      rust/test/shared/serialization_test.rs
  3. 11
      rust/upb/wire.rs
  4. 8
      src/google/protobuf/compiler/rust/message.cc

@ -164,6 +164,28 @@ impl SerializedData {
fn as_mut_ptr(&mut self) -> *mut [u8] {
ptr::slice_from_raw_parts_mut(self.data.as_ptr(), self.len)
}
/// Converts into a Vec<u8>.
pub fn into_vec(self) -> Vec<u8> {
// We need to prevent self from being dropped, because we are going to transfer
// ownership of self.data to the Vec<u8>.
let s = std::mem::ManuallyDrop::new(self);
unsafe {
// SAFETY:
// - `data` was allocated by the Rust global allocator.
// - `data` was allocated with an alignment of 1 for u8.
// - The allocated size was `len`.
// - The length and capacity are equal.
// - All `len` bytes are initialized.
// - The capacity (`len` in this case) is the size the pointer was allocated
// with.
// - The allocated size is no more than isize::MAX, because the protobuf
// serializer will refuse to serialize a message if the output would exceed
// 2^31 - 1 bytes.
Vec::<u8>::from_raw_parts(s.data.as_ptr(), s.len, s.len)
}
}
}
impl Deref for SerializedData {

@ -61,7 +61,7 @@ macro_rules! generate_parameterized_serialization_test {
msg.set_optional_bool(true);
let mut msg2 = [< $type >]::new();
msg2.set_optional_bytes(msg.serialize().unwrap());
assert_that!(msg2.optional_bytes(), eq(msg.serialize().unwrap().as_ref()));
assert_that!(msg2.optional_bytes(), eq(msg.serialize().unwrap()));
}
#[test]

@ -1,4 +1,4 @@
use crate::{upb_ExtensionRegistry, upb_MiniTable, Arena, OwnedArenaBox, RawArena, RawMessage};
use crate::{upb_ExtensionRegistry, upb_MiniTable, Arena, RawArena, RawMessage};
use std::ptr::NonNull;
// LINT.IfChange(encode_status)
@ -37,12 +37,12 @@ enum DecodeOption {
/// If Err, then EncodeStatus != Ok.
///
/// SAFETY:
/// # Safety
/// - `msg` must be associated with `mini_table`.
pub unsafe fn encode(
msg: RawMessage,
mini_table: *const upb_MiniTable,
) -> Result<OwnedArenaBox<[u8]>, EncodeStatus> {
) -> Result<Vec<u8>, EncodeStatus> {
let arena = Arena::new();
let mut buf: *mut u8 = std::ptr::null_mut();
let mut len = 0usize;
@ -55,8 +55,7 @@ pub unsafe fn encode(
if status == EncodeStatus::Ok {
assert!(!buf.is_null()); // EncodeStatus Ok should never return NULL data, even for len=0.
// SAFETY: upb guarantees that `buf` is valid to read for `len`.
let slice = NonNull::new_unchecked(std::ptr::slice_from_raw_parts_mut(buf, len));
Ok(OwnedArenaBox::new(slice, arena))
Ok((*std::ptr::slice_from_raw_parts(buf, len)).to_vec())
} else {
Err(status)
}
@ -65,7 +64,7 @@ pub unsafe fn encode(
/// Decodes into the provided message (merge semantics). If Err, then
/// DecodeStatus != Ok.
///
/// SAFETY:
/// # Safety
/// - `msg` must be mutable.
/// - `msg` must be associated with `mini_table`.
pub unsafe fn decode(

@ -66,7 +66,7 @@ void MessageSerialize(Context& ctx, const Descriptor& msg) {
$serialize_thunk$(self.raw_msg(), &mut serialized_data)
};
if success {
Ok(serialized_data)
Ok(serialized_data.into_vec())
} else {
Err($pb$::SerializeError)
}
@ -939,7 +939,7 @@ void GenerateRs(Context& ctx, const Descriptor& msg) {
self.msg
}
pub fn serialize(&self) -> Result<$pbr$::SerializedData, $pb$::SerializeError> {
pub fn serialize(&self) -> Result<Vec<u8>, $pb$::SerializeError> {
$Msg::serialize$
}
@ -1015,7 +1015,7 @@ void GenerateRs(Context& ctx, const Descriptor& msg) {
self.inner
}
pub fn serialize(&self) -> Result<$pbr$::SerializedData, $pb$::SerializeError> {
pub fn serialize(&self) -> Result<Vec<u8>, $pb$::SerializeError> {
$pb$::ViewProxy::as_view(self).serialize()
}
@ -1069,7 +1069,7 @@ void GenerateRs(Context& ctx, const Descriptor& msg) {
$raw_arena_getter_for_message$
pub fn serialize(&self) -> Result<$pbr$::SerializedData, $pb$::SerializeError> {
pub fn serialize(&self) -> Result<Vec<u8>, $pb$::SerializeError> {
self.as_view().serialize()
}
#[deprecated = "Prefer Msg::parse(), or use the new name 'clear_and_parse' to parse into a pre-existing message."]

Loading…
Cancel
Save