blob: 92ac377d5bda6c4d1b6131d61abccb0af971385d [file]
// Protocol Buffers - Google's data interchange format
// Copyright 2024 Google LLC. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
use super::sys::text::text::{text_encode_options, upb_DebugString};
use super::{AssociatedMiniTable, MessagePtr};
/// Options for upb's text encoders.
/// This is only used for `text_encode` for now, but it might be used for `debug_string` in the
/// future. That's why it must be in the non-reflection crate.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct TextEncodeOptions {
/// Print everything on a single line.
pub single_line: bool,
/// Do not print unknown fields.
pub skip_unknown: bool,
}
impl TextEncodeOptions {
/// The bitmask that upb's text encoders expect.
pub fn to_bits(self) -> i32 {
let mut bits = 0;
if self.single_line {
bits |= text_encode_options::SINGLE_LINE;
}
if self.skip_unknown {
bits |= text_encode_options::SKIP_UNKNOWN;
}
bits
}
}
/// Returns a string of field number to value entries of a message.
///
/// # Safety
/// - `msg` must be legally dereferenceable.
pub unsafe fn debug_string<T: AssociatedMiniTable>(msg: MessagePtr<T>) -> String {
let mt = T::mini_table();
let msg = msg.raw();
// Only find out the length first to then allocate a buffer of the minimum size
// needed.
// SAFETY:
// - `msg` is a legally dereferencable upb_Message whose associated minitable is `mt`
// - `buf` is nullptr and `buf_len` is 0
let len = unsafe { upb_DebugString(msg, mt, 0, core::ptr::null_mut(), 0) };
assert!(len < isize::MAX as usize);
// +1 for the trailing NULL
let mut buf = vec![0u8; len + 1];
// SAFETY:
// - `msg` is a legally dereferencable upb_Message whose associated minitable is `mt`
// - `buf` is legally writable for 'buf_len' bytes
let written_len = unsafe { upb_DebugString(msg, mt, 0, buf.as_mut_ptr(), buf.len()) };
assert_eq!(len, written_len);
String::from_utf8_lossy(&buf[..len]).into_owned()
}