blob: c48b9fc0469afbcb19f949e3cfb6ab5ab0a59151 [file]
// Protocol Buffers - Google's data interchange format
// Copyright 2026 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
//! Reflection support for the C++ kernel.
//!
//! The descriptor itself is fetched through a per-message thunk emitted into
//! that message's generated C++ code, so that only protos which actually need
//! reflection pull in the full C++ runtime.
use super::*;
pub trait KernelWithReflection: MessageDescriptorInterop {
fn kernel_full_name(_private: Private) -> &'static str {
let desc = Self::__unstable_get_descriptor();
// SAFETY:
// - This function is only called via `WithReflection::full_name`. Gencode only implements
// `WithReflection` for messages with reflection, so `desc` is a real descriptor.
unsafe { std::str::from_utf8_unchecked(proto2_rust_Descriptor_full_name(desc).as_ref()) }
}
}
impl<T: MessageDescriptorInterop> KernelWithReflection for T {}
#[cfg(not(lite_runtime))]
unsafe extern "C" {
/// From reflection.cc
///
/// # Safety
/// - `desc` points to a valid `proto2::Descriptor`.
fn proto2_rust_Descriptor_full_name(desc: *const std::ffi::c_void) -> PtrAndLen;
/// From reflection.cc
///
/// # Safety
/// - `m` is a legally dereferenceable MessageLite* that supports reflection.
fn proto2_rust_Message_print_to_text_format(
m: RawMessage,
single_line: bool,
hide_unknown_fields: bool,
) -> RustStringRawParts;
/// From reflection.cc
///
/// # Safety
/// - `m` is a legally dereferenceable and mutable MessageLite* that supports reflection.
/// - `input` is a valid `PtrAndLen` pointing to readable memory for its length.
fn proto2_rust_Message_parse_from_text_format(m: RawMessage, input: PtrAndLen) -> bool;
}
/// Returns the protobuf TextFormat representation of `msg` with custom options.
#[cfg(not(lite_runtime))]
pub fn print_to_text_format<T: crate::WithReflection>(
msg: &T,
single_line: bool,
hide_unknown_fields: bool,
) -> String {
let raw = msg.as_view().get_raw_message(Private);
// SAFETY: `raw` points to a live message, and `WithReflection` guarantees it
// supports reflection.
unsafe { proto2_rust_Message_print_to_text_format(raw, single_line, hide_unknown_fields) }
.into()
}
/// Parses a message from its protobuf TextFormat representation.
#[cfg(not(lite_runtime))]
pub fn parse_from_text_format<T: crate::WithReflection>(input: &str) -> Result<T, ParseError> {
let mut msg = T::default();
let raw = msg.get_raw_message_mut(Private);
// SAFETY:
// - `raw` points to a live, mutable message, and `WithReflection` guarantees it supports
// reflection.
// - `input` is converted from a valid `&str` slice.
unsafe { proto2_rust_Message_parse_from_text_format(raw, input.as_bytes().into()) }
.then_some(msg)
.ok_or(ParseError)
}