• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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