// Protocol Buffers - Google's data interchange format // Copyright 2025 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::{ message::array as sys_array, message::map as sys_map, message::message as sys_msg, mini_table::mini_table as sys_mt, }; use super::StringView; use super::{Arena, AssociatedMiniTable}; use core::marker::PhantomData; use paste::paste; pub type RawMessage = sys_msg::RawMessage; #[derive(Debug)] pub struct MessagePtr { raw: RawMessage, _phantom: PhantomData, } impl Copy for MessagePtr {} impl Clone for MessagePtr { fn clone(&self) -> Self { *self } } impl MessagePtr { pub fn raw(&self) -> RawMessage { self.raw } } macro_rules! scalar_accessors { ( $ty:ty, $rust_ty_name:ident, $upb_ty_name:ident) => { paste! { impl MessagePtr { /// # Safety /// - `self` must be legally dereferenceable. /// - The field at `index` must be a $ty field. pub unsafe fn [< get_ $rust_ty_name _at_index >] (self, index: u32, default_value: $ty) -> $ty { let f = unsafe { sys_mt::upb_MiniTable_GetFieldByIndex(T::mini_table(), index) }; unsafe { sys_msg::[< upb_Message_Get $upb_ty_name >](self.raw, f, default_value) } } /// # Safety /// - `self` must be legally dereferenceable to a mutable message. /// - The field at `index` must be a $ty field. pub unsafe fn [< set_base_field_ $rust_ty_name _at_index >] (self, index: u32, value: $ty) { let f = unsafe { sys_mt::upb_MiniTable_GetFieldByIndex(T::mini_table(), index) }; unsafe { sys_msg::[< upb_Message_SetBaseField $upb_ty_name >](self.raw, f, value) } } } } }; } scalar_accessors!(bool, bool, Bool); scalar_accessors!(i32, i32, Int32); scalar_accessors!(i64, i64, Int64); scalar_accessors!(u32, u32, UInt32); scalar_accessors!(u64, u64, UInt64); scalar_accessors!(f32, f32, Float); scalar_accessors!(f64, f64, Double); scalar_accessors!(StringView, string, String); impl MessagePtr { /// Constructs a new mutable message pointer. /// Will only return None if arena allocation fails. pub fn new(arena: &Arena) -> Option> { let raw = unsafe { sys_msg::upb_Message_New(T::mini_table(), arena.raw()) }; raw.map(|raw| MessagePtr { raw, _phantom: PhantomData }) } /// # Safety /// - `raw` must be a dereferenceable message pointer of message associated with `T::mini_table()`. pub unsafe fn wrap(raw: RawMessage) -> MessagePtr { MessagePtr { raw, _phantom: PhantomData } } /// # Safety /// - `self` must be legally dereferenceable to a mutable message. pub unsafe fn clear(self) { unsafe { sys_msg::upb_Message_Clear(self.raw, T::mini_table()) } } /// Copies the contents of `src` to `self`, using `arena` for allocations. /// `arena` should be the one associated with `self`. /// # Safety /// - `self` must be legally dereferenceable to a mutable message. pub unsafe fn deep_copy(self, src: Self, arena: &Arena) -> bool { unsafe { sys_msg::upb_Message_DeepCopy(self.raw, src.raw, T::mini_table(), arena.raw()) } } /// Returns a pointer to a mutable message which is a clone of `self` on `arena`. /// # Safety /// - `self` must be legally dereferenceable. pub unsafe fn deep_clone(self, arena: &Arena) -> Option> { let raw = unsafe { sys_msg::upb_Message_DeepClone(self.raw, T::mini_table(), arena.raw()) }; raw.map(|raw| MessagePtr { raw, _phantom: PhantomData }) } /// # Safety /// - `self` must be legally dereferenceable. /// - `index` must be within bounds of `T::mini_table()`. pub unsafe fn clear_field_at_index(self, index: u32) { let f = unsafe { sys_mt::upb_MiniTable_GetFieldByIndex(T::mini_table(), index) }; unsafe { sys_msg::upb_Message_ClearBaseField(self.raw, f) } } /// # Safety /// - `self` must be legally dereferenceable. /// - `index` must be within bounds of `T::mini_table()`. pub unsafe fn has_field_at_index(self, index: u32) -> bool { let f = unsafe { sys_mt::upb_MiniTable_GetFieldByIndex(T::mini_table(), index) }; unsafe { sys_msg::upb_Message_HasBaseField(self.raw, f) } } /// Returns a constant message pointer, or None if the field is not present. /// /// # Safety /// - `self` must be legally dereferenceable. /// - The field at `index` must be a message field of type `ChildT`. pub unsafe fn get_message_at_index(self, index: u32) -> Option> { let f = unsafe { sys_mt::upb_MiniTable_GetFieldByIndex(T::mini_table(), index) }; let raw = unsafe { sys_msg::upb_Message_GetMessage(self.raw, f) }; raw.map(|raw| MessagePtr { raw, _phantom: PhantomData }) } /// # Safety /// - `self` must be legally dereferenceable. /// - The field at `index` must be a message field of type `ChildT`. /// - Caller must ensure that `value` outlives `self` (typically by being on the same arena). pub unsafe fn set_base_field_message_at_index( self, index: u32, value: MessagePtr, ) { let f = unsafe { sys_mt::upb_MiniTable_GetFieldByIndex(T::mini_table(), index) }; unsafe { sys_msg::upb_Message_SetBaseFieldMessage(self.raw, f, value.raw) } } /// Returns a mutable message pointer, creating the field if it is not present. /// /// # Safety /// - `self` must be legally dereferenceable to a mutable message. /// - The field at `index` must be a message field of type `ChildT`. pub unsafe fn get_or_create_mutable_message_at_index( self, index: u32, arena: &Arena, ) -> Option> { let f = unsafe { sys_mt::upb_MiniTable_GetFieldByIndex(T::mini_table(), index) }; let raw = unsafe { sys_msg::upb_Message_GetOrCreateMutableMessage(self.raw, f, arena.raw()) }; raw.map(|raw| MessagePtr { raw, _phantom: PhantomData }) } /// Returns a constant pointer to an array. May return None if the repeated field is empty. /// /// # Safety /// - `self` must be legally dereferenceable. /// - The field at `index` must be a repeated field. pub unsafe fn get_array_at_index(self, index: u32) -> Option { let f = unsafe { sys_mt::upb_MiniTable_GetFieldByIndex(T::mini_table(), index) }; let raw = unsafe { sys_msg::upb_Message_GetArray(self.raw, f) }; raw } /// # Safety /// - `self` must be legally dereferenceable. /// - The field at `index` must be a repeated field. /// - Caller must ensure that `value` outlives `self` (typically by being on the same arena). pub unsafe fn set_array_at_index(self, index: u32, value: sys_array::RawArray) { let f = unsafe { sys_mt::upb_MiniTable_GetFieldByIndex(T::mini_table(), index) }; let value_ptr: *const *const core::ffi::c_void = &(value.as_ptr() as *const core::ffi::c_void); unsafe { sys_msg::upb_Message_SetBaseField(self.raw, f, value_ptr as *const core::ffi::c_void) } } /// Returns a mutable pointer to an array. Will only return None if arena allocation fails. /// /// # Safety /// - `self` must be legally dereferenceable to a mutable message. /// - The field at `index` must be a repeated field. pub unsafe fn get_or_create_mutable_array_at_index( self, index: u32, arena: &Arena, ) -> Option { let f = unsafe { sys_mt::upb_MiniTable_GetFieldByIndex(T::mini_table(), index) }; let raw = unsafe { sys_msg::upb_Message_GetOrCreateMutableArray(self.raw, f, arena.raw()) }; raw } /// Returns a constant pointer to a map. May return None if the map is empty. /// /// # Safety /// - `self` must be legally dereferenceable. /// - The field at `index` must be a map. pub unsafe fn get_map_at_index(self, index: u32) -> Option { let f = unsafe { sys_mt::upb_MiniTable_GetFieldByIndex(T::mini_table(), index) }; unsafe { sys_msg::upb_Message_GetMap(self.raw, f) } } /// # Safety /// - `self` must be legally dereferenceable. /// - The field at `index` must be a map field. /// - Caller must ensure that `value` outlives `self` (typically by being on the same arena). pub unsafe fn set_map_at_index(self, index: u32, value: sys_map::RawMap) { let f = unsafe { sys_mt::upb_MiniTable_GetFieldByIndex(T::mini_table(), index) }; let value_ptr: *const *const core::ffi::c_void = &(value.as_ptr() as *const core::ffi::c_void); unsafe { sys_msg::upb_Message_SetBaseField(self.raw, f, value_ptr as *const core::ffi::c_void) } } /// Returns a mutable pointer to a map. Will only return None if arena allocation fails. /// /// # Safety /// - `self` must be legally dereferenceable to a mutable message. /// - The field at `index` must be a map. pub unsafe fn get_or_create_mutable_map_at_index( self, index: u32, arena: &Arena, ) -> Option { unsafe { let f = sys_mt::upb_MiniTable_GetFieldByIndex(T::mini_table(), index); let map_entry_mini_table = sys_mt::upb_MiniTable_SubMessage(f); sys_msg::upb_Message_GetOrCreateMutableMap( self.raw, map_entry_mini_table, f, arena.raw(), ) } } /// Returns the number associated with the active field in a oneof, or 0 if the oneof is unset. /// `index` can be the field number of any field in the oneof. /// /// # Safety /// - `self` must be legally dereferenceable. /// - The field at `index` must be part of a oneof. pub unsafe fn which_oneof_field_number_by_index(self, index: u32) -> u32 { let f = unsafe { sys_mt::upb_MiniTable_GetFieldByIndex(T::mini_table(), index) }; unsafe { sys_msg::upb_Message_WhichOneofFieldNumber(self.raw, f) } } }