1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2024 Google LLC. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 use super::{upb_MiniTable, RawMessage};
9
10 extern "C" {
11 /// Returns the minimum needed length (excluding NULL) that `buf` has to be
12 /// to hold the `msg`s debug string.
13 ///
14 /// SAFETY:
15 /// - `msg` is pointing at a valid upb_Message with associated minitable
16 /// `mt`
17 /// - `buf` is legally writable for `size` bytes (`buf` may be nullptr if
18 /// `size` is 0)
upb_DebugString( msg: RawMessage, mt: *const upb_MiniTable, options: i32, buf: *mut u8, size: usize, ) -> usize19 fn upb_DebugString(
20 msg: RawMessage,
21 mt: *const upb_MiniTable,
22 options: i32,
23 buf: *mut u8,
24 size: usize,
25 ) -> usize;
26 }
27
28 #[allow(dead_code)]
29 #[repr(i32)]
30 enum Options {
31 // When set, prints everything on a single line.
32 SingleLine = 1,
33
34 // When set, unknown fields are not printed.
35 SkipUnknown = 2,
36
37 // When set, maps are *not* sorted (this avoids allocating tmp mem).
38 NoSortMaps = 4,
39 }
40
41 /// Returns a string of field number to value entries of a message.
42 ///
43 /// # Safety
44 /// - `mt` must correspond to the `msg`s minitable.
debug_string(msg: RawMessage, mt: *const upb_MiniTable) -> String45 pub unsafe fn debug_string(msg: RawMessage, mt: *const upb_MiniTable) -> String {
46 // Only find out the length first to then allocate a buffer of the minimum size
47 // needed.
48 // SAFETY:
49 // - `msg` is a legally dereferencable upb_Message whose associated minitable is
50 // `mt`
51 // - `buf` is nullptr and `buf_len` is 0
52 let len =
53 unsafe { upb_DebugString(msg, mt, Options::NoSortMaps as i32, core::ptr::null_mut(), 0) };
54 assert!(len < isize::MAX as usize);
55 // +1 for the trailing NULL
56 let mut buf = vec![0u8; len + 1];
57 // SAFETY:
58 // - `msg` is a legally dereferencable upb_Message whose associated minitable is
59 // `mt`
60 // - `buf` is legally writable for 'buf_len' bytes
61 let written_len = unsafe {
62 upb_DebugString(msg, mt, Options::NoSortMaps as i32, buf.as_mut_ptr(), buf.len())
63 };
64 assert_eq!(len, written_len);
65 String::from_utf8_lossy(buf.as_slice()).to_string()
66 }
67
68 #[cfg(test)]
69 mod tests {
70 use super::*;
71 use googletest::gtest;
72
73 #[gtest]
assert_text_linked()74 fn assert_text_linked() {
75 use crate::assert_linked;
76 assert_linked!(upb_DebugString);
77 }
78 }
79