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 10 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] { fn as_mut_ptr(&mut self) -> *mut [u8] {
ptr::slice_from_raw_parts_mut(self.data.as_ptr(), self.len) 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 { impl Deref for SerializedData {

@ -61,7 +61,7 @@ macro_rules! generate_parameterized_serialization_test {
msg.set_optional_bool(true); msg.set_optional_bool(true);
let mut msg2 = [< $type >]::new(); let mut msg2 = [< $type >]::new();
msg2.set_optional_bytes(msg.serialize().unwrap()); 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] #[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; use std::ptr::NonNull;
// LINT.IfChange(encode_status) // LINT.IfChange(encode_status)
@ -37,12 +37,12 @@ enum DecodeOption {
/// If Err, then EncodeStatus != Ok. /// If Err, then EncodeStatus != Ok.
/// ///
/// SAFETY: /// # Safety
/// - `msg` must be associated with `mini_table`. /// - `msg` must be associated with `mini_table`.
pub unsafe fn encode( pub unsafe fn encode(
msg: RawMessage, msg: RawMessage,
mini_table: *const upb_MiniTable, mini_table: *const upb_MiniTable,
) -> Result<OwnedArenaBox<[u8]>, EncodeStatus> { ) -> Result<Vec<u8>, EncodeStatus> {
let arena = Arena::new(); let arena = Arena::new();
let mut buf: *mut u8 = std::ptr::null_mut(); let mut buf: *mut u8 = std::ptr::null_mut();
let mut len = 0usize; let mut len = 0usize;
@ -55,8 +55,7 @@ pub unsafe fn encode(
if status == EncodeStatus::Ok { if status == EncodeStatus::Ok {
assert!(!buf.is_null()); // EncodeStatus Ok should never return NULL data, even for len=0. 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`. // 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((*std::ptr::slice_from_raw_parts(buf, len)).to_vec())
Ok(OwnedArenaBox::new(slice, arena))
} else { } else {
Err(status) Err(status)
} }
@ -65,7 +64,7 @@ pub unsafe fn encode(
/// Decodes into the provided message (merge semantics). If Err, then /// Decodes into the provided message (merge semantics). If Err, then
/// DecodeStatus != Ok. /// DecodeStatus != Ok.
/// ///
/// SAFETY: /// # Safety
/// - `msg` must be mutable. /// - `msg` must be mutable.
/// - `msg` must be associated with `mini_table`. /// - `msg` must be associated with `mini_table`.
pub unsafe fn decode( pub unsafe fn decode(

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

Loading…
Cancel
Save