Skip to content

Commit ff751dd

Browse files
runzwcopybara-github
authored andcommitted
Internal change
PiperOrigin-RevId: 952911533
1 parent 4bd1598 commit ff751dd

10 files changed

Lines changed: 171 additions & 1 deletion

File tree

rust/upb/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ rust_library(
1717
"lib.rs",
1818
"message.rs",
1919
"owned_arena_box.rs",
20+
"reflection.rs",
2021
"text.rs",
2122
"wire.rs",
2223
],

rust/upb/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ pub use arena::Arena;
1313
mod associated_mini_table;
1414
pub use associated_mini_table::{AssociatedMiniTable, AssociatedMiniTableEnum};
1515

16+
mod reflection;
17+
pub use reflection::{DefPool, MessageDef};
18+
1619
mod text;
1720
pub use text::debug_string;
1821

rust/upb/reflection.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
use std::marker::PhantomData;
2+
use std::ptr::NonNull;
3+
4+
pub use super::sys::reflection::def_pool::upb_DefPool;
5+
use super::sys::reflection::def_pool::{upb_DefPool_Free, upb_DefPool_New};
6+
pub use super::sys::reflection::message_def::upb_MessageDef;
7+
8+
/// A wrapper over a `upb_DefPool`.
9+
///
10+
/// This is an owning type and will automatically free the pool when
11+
/// dropped.
12+
pub struct DefPool {
13+
raw: NonNull<upb_DefPool>,
14+
}
15+
16+
impl Default for DefPool {
17+
fn default() -> Self {
18+
Self::new()
19+
}
20+
}
21+
22+
impl DefPool {
23+
/// Allocates a fresh pool.
24+
#[inline]
25+
pub fn new() -> Self {
26+
// SAFETY: upb_DefPool_New is guaranteed to return a valid pointer or crash.
27+
let ptr = unsafe { upb_DefPool_New() };
28+
Self { raw: NonNull::new(ptr).unwrap() }
29+
}
30+
31+
/// Returns the raw, UPB-managed pointer to the pool.
32+
#[inline]
33+
#[doc(hidden)]
34+
pub fn as_mut_ptr(&self) -> *mut upb_DefPool {
35+
self.raw.as_ptr()
36+
}
37+
}
38+
39+
impl Drop for DefPool {
40+
fn drop(&mut self) {
41+
// SAFETY: The pointer was generated by upb_DefPool_New and hasn't been freed.
42+
unsafe { upb_DefPool_Free(self.raw.as_ptr()) }
43+
}
44+
}
45+
46+
/// A borrowed message descriptor tied to the lifetime of a DefPool. No drop implementation is
47+
/// provided because this is not an owning type and cannot be individually freed.
48+
pub struct MessageDef<'pool> {
49+
raw: NonNull<upb_MessageDef>,
50+
_marker: PhantomData<&'pool DefPool>,
51+
}
52+
53+
impl<'pool> MessageDef<'pool> {
54+
/// # Safety
55+
/// The caller must guarantee `ptr` was allocated by the pool providing the `'pool` lifetime.
56+
pub unsafe fn from_raw(ptr: *const upb_MessageDef) -> Self {
57+
Self {
58+
raw: NonNull::new(ptr as *mut _).expect("Descriptor ptr cannot be null"),
59+
_marker: PhantomData,
60+
}
61+
}
62+
63+
/// Returns the raw, UPB-managed pointer to the descriptor.
64+
#[inline]
65+
#[doc(hidden)]
66+
pub fn as_ptr(&self) -> *const upb_MessageDef {
67+
self.raw.as_ptr()
68+
}
69+
}

rust/upb/sys/BUILD

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ rust_library(
2828
"mini_table/mini_table.rs",
2929
"mini_table/mod.rs",
3030
"opaque_pointee.rs",
31+
"reflection/def_pool.rs",
32+
"reflection/message_def.rs",
33+
"reflection/mod.rs",
3134
"test_helpers.rs",
3235
"text/mod.rs",
3336
"text/text.rs",
@@ -59,6 +62,8 @@ cc_library(
5962
"//upb/message:copy",
6063
"//upb/mini_descriptor",
6164
"//upb/mini_table",
65+
"//upb/reflection",
66+
"//upb/text",
6267
"//upb/text:debug",
6368
"//upb/wire:byte_size",
6469
],

rust/upb/sys/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ pub mod mem;
33
pub mod message;
44
pub mod mini_table;
55
pub mod opaque_pointee;
6+
pub mod reflection;
67
pub mod text;
78
pub mod wire;
89

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
use super::super::opaque_pointee::opaque_pointee;
2+
3+
opaque_pointee!(upb_DefPool);
4+
5+
unsafe extern "C" {
6+
/// Creates a new upb_DefPool.
7+
///
8+
/// The caller takes ownership of the returned pointer and is responsible for calling
9+
/// `upb_DefPool_Free` on it, or leaking memory.
10+
pub fn upb_DefPool_New() -> *mut upb_DefPool;
11+
12+
/// Frees a upb_DefPool and all message definitions allocated within it.
13+
///
14+
/// # Safety
15+
/// - `s` must be a valid pointer to a `upb_DefPool` created by `upb_DefPool_New`. This fn is
16+
/// only called during Drop so it is safe to assume that the pointer is not null. It is
17+
/// technically identical to taking a NonNull pointer.
18+
pub fn upb_DefPool_Free(s: *mut upb_DefPool);
19+
}
20+
21+
#[cfg(test)]
22+
mod tests {
23+
use googletest::gtest;
24+
25+
#[gtest]
26+
fn assert_def_pool_linked() {
27+
use crate::assert_linked;
28+
assert_linked!(super::upb_DefPool_New);
29+
assert_linked!(super::upb_DefPool_Free);
30+
}
31+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
use super::super::opaque_pointee::opaque_pointee;
2+
3+
opaque_pointee!(upb_MessageDef);

rust/upb/sys/reflection/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pub mod def_pool;
2+
pub mod message_def;

rust/upb/sys/text/text.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ mod sys {
1111

1212
use sys::message::message::RawMessage;
1313
use sys::mini_table::mini_table::RawMiniTable;
14+
use sys::reflection::def_pool::upb_DefPool;
15+
use sys::reflection::message_def::upb_MessageDef;
1416

1517
unsafe extern "C" {
1618
/// Returns the minimum needed length (excluding NULL) that `buf` has to be
@@ -28,6 +30,27 @@ unsafe extern "C" {
2830
buf: *mut u8,
2931
size: usize,
3032
) -> usize;
33+
34+
/// Encodes a message to text format.
35+
///
36+
/// Returns the exact number of bytes required to store the resulting text (excluding
37+
/// the null terminator). If `size` is greater than 0, the text is written into `buf`
38+
/// up to `size - 1` bytes and null-terminated.
39+
///
40+
/// # Safety
41+
/// - `msg` must point to a valid `upb_Message` whose shape perfectly aligns with the
42+
/// supplied descriptor `m`.
43+
/// - `m` must point to a legally allocated `upb_MessageDef`.
44+
/// - `ext_pool` may be null, but if provided, it must point to a valid `upb_DefPool`.
45+
/// - `buf` must be legally writable for at least `size` bytes (or may be null if `size` is 0).
46+
pub fn upb_TextEncode(
47+
msg: RawMessage,
48+
m: *const upb_MessageDef,
49+
ext_pool: *const upb_DefPool,
50+
options: i32, // bitmask of `text_encode_options` values
51+
buf: *mut u8,
52+
size: usize,
53+
) -> usize;
3154
}
3255

3356
/// Encoding options.
@@ -52,5 +75,6 @@ mod tests {
5275
fn assert_text_linked() {
5376
use crate::assert_linked;
5477
assert_linked!(upb_DebugString);
78+
assert_linked!(upb_TextEncode);
5579
}
5680
}

rust/upb/text.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// license that can be found in the LICENSE file or at
66
// https://developers.google.com/open-source/licenses/bsd
77

8-
use super::sys::text::text::upb_DebugString;
8+
use super::sys::text::text::{upb_DebugString, upb_TextEncode};
99
use super::{AssociatedMiniTable, MessagePtr};
1010

1111
/// Returns a string of field number to value entries of a message.
@@ -34,3 +34,34 @@ pub unsafe fn debug_string<T: AssociatedMiniTable>(msg: MessagePtr<T>) -> String
3434
assert_eq!(len, written_len);
3535
String::from_utf8_lossy(buf.as_slice()).to_string()
3636
}
37+
38+
/// Encodes a message as text format.
39+
///
40+
/// # Safety
41+
/// - `msg` must be legally dereferenceable.
42+
pub unsafe fn text_encode<'pool, T>(
43+
msg: super::MessagePtr<T>,
44+
def: &super::MessageDef<'pool>,
45+
_pool: &'pool super::DefPool,
46+
) -> String {
47+
let msg = msg.raw();
48+
49+
// SAFETY: buf is legally writable if size > 0 (size is 0 here)
50+
let len = unsafe {
51+
upb_TextEncode(msg, def.as_ptr(), core::ptr::null(), 0, core::ptr::null_mut(), 0)
52+
};
53+
54+
let mut buf = vec![0u8; len + 1];
55+
56+
// SAFETY: buf is writable for its len
57+
let written_len = unsafe {
58+
upb_TextEncode(msg, def.as_ptr(), core::ptr::null(), 0, buf.as_mut_ptr(), buf.len())
59+
};
60+
61+
// upb_TextEncode returns the length excluding NULL, same as len
62+
assert_eq!(len, written_len);
63+
64+
// Truncate to written length (ignoring NULL)
65+
buf.truncate(len);
66+
String::from_utf8_lossy(buf.as_slice()).to_string()
67+
}

0 commit comments

Comments
 (0)