// 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 use super::*; use crate::__internal::entity_tag::*; use crate::__internal::runtime::_opaque_pointees::RawRepeatedFieldData; use crate::__internal::{EntityType, Enum, MatcherEq, Private, Singular}; use crate::extension::{ExtAccess, ExtClear, ExtGetMut, ExtHas}; use crate::{ExtensionId, IntoMut, IntoView, MessageViewInterop, Proxied}; unsafe extern "C" { pub fn proto2_rust_Message_clear_extension(m: RawMessage, number: i32); pub fn proto2_rust_Message_has_extension(m: RawMessage, number: i32) -> bool; pub fn proto2_rust_Message_set_extension_bool( m: RawMessage, number: i32, field_type: i32, value: bool, ); pub fn proto2_rust_Message_get_extension_bool( m: RawMessage, number: i32, default_value: bool, ) -> bool; pub fn proto2_rust_Message_set_extension_float( m: RawMessage, number: i32, field_type: i32, value: f32, ); pub fn proto2_rust_Message_get_extension_float( m: RawMessage, number: i32, default_value: f32, ) -> f32; pub fn proto2_rust_Message_set_extension_double( m: RawMessage, number: i32, field_type: i32, value: f64, ); pub fn proto2_rust_Message_get_extension_double( m: RawMessage, number: i32, default_value: f64, ) -> f64; pub fn proto2_rust_Message_set_extension_int32( m: RawMessage, number: i32, field_type: i32, value: i32, ); pub fn proto2_rust_Message_get_extension_int32( m: RawMessage, number: i32, default_value: i32, ) -> i32; pub fn proto2_rust_Message_set_extension_int64( m: RawMessage, number: i32, field_type: i32, value: i64, ); pub fn proto2_rust_Message_get_extension_int64( m: RawMessage, number: i32, default_value: i64, ) -> i64; pub fn proto2_rust_Message_set_extension_uint32( m: RawMessage, number: i32, field_type: i32, value: u32, ); pub fn proto2_rust_Message_get_extension_uint32( m: RawMessage, number: i32, default_value: u32, ) -> u32; pub fn proto2_rust_Message_set_extension_uint64( m: RawMessage, number: i32, field_type: i32, value: u64, ); pub fn proto2_rust_Message_get_extension_uint64( m: RawMessage, number: i32, default_value: u64, ) -> u64; pub fn proto2_rust_Message_set_extension_string( m: RawMessage, number: i32, field_type: i32, value: CppStdString, ); pub fn proto2_rust_Message_get_extension_string( m: RawMessage, number: i32, default_value: PtrAndLen, ) -> PtrAndLen; pub fn proto2_rust_Message_get_extension_message( m: RawMessage, number: i32, default_instance: RawMessage, ) -> RawMessage; pub fn proto2_rust_Message_mutable_extension_message( m: RawMessage, number: i32, field_type: i32, default_instance: RawMessage, ) -> RawMessage; } fn pin_extension(extension: &ExtensionId) { unsafe { std::ptr::read_volatile(extension.inner.cpp_extension_id_thunk() as *const u8); // We could try to optimize this to the following at some point, but it's less portable. // std::arch::asm!("/* {0} */", in(reg) ($ptr as *const ())); } } #[doc(hidden)] pub struct InnerExtensionId { field_type: i32, cpp_extension_id_thunk: unsafe extern "C" fn() -> *const c_void, cpp_get_extension_thunk: Option *const c_void>, cpp_mutable_extension_thunk: Option *mut c_void>, } impl InnerExtensionId { pub const fn new( field_type: i32, cpp_extension_id_thunk: unsafe extern "C" fn() -> *const c_void, ) -> Self { Self { field_type, cpp_extension_id_thunk, cpp_get_extension_thunk: None, cpp_mutable_extension_thunk: None, } } pub const fn new_repeated( field_type: i32, cpp_extension_id_thunk: unsafe extern "C" fn() -> *const c_void, cpp_get_extension_thunk: unsafe extern "C" fn(*const c_void) -> *const c_void, cpp_mutable_extension_thunk: unsafe extern "C" fn(*mut c_void) -> *mut c_void, ) -> Self { Self { field_type, cpp_extension_id_thunk, cpp_get_extension_thunk: Some(cpp_get_extension_thunk), cpp_mutable_extension_thunk: Some(cpp_mutable_extension_thunk), } } pub fn cpp_extension_id_thunk(&self) -> unsafe extern "C" fn() -> *const c_void { self.cpp_extension_id_thunk } pub fn cpp_get_extension_thunk( &self, ) -> Option *const c_void> { self.cpp_get_extension_thunk } pub fn cpp_mutable_extension_thunk( &self, ) -> Option *mut c_void> { self.cpp_mutable_extension_thunk } } impl ExtHas for ExtensionId { fn has(&self, _private: Private, msg: impl AsView) -> bool { pin_extension(self); unsafe { proto2_rust_Message_has_extension( msg.as_view().get_raw_message(Private), self.number() as i32, ) } } } macro_rules! impl_scalar_extension { ($($t:ty => [$get:ident, $set:ident]),* $(,)?) => { $( impl ExtAccess for ExtensionId { fn get<'msg>(&self, _private: Private, msg: impl IntoView<'msg, Proxied = Extendee>) -> View<'msg, $t> { let msg = msg.into_view(); pin_extension(self); unsafe { $get( msg.get_raw_message(Private), self.number() as i32, self.default.expect("scalar extensions must have a default value"), ) } } fn set(&self, _private: Private, mut msg: impl AsMut, value: impl IntoProxied<$t>) { pin_extension(self); unsafe { $set( msg.as_mut().get_raw_message_mut(Private), self.number() as i32, self.inner.field_type, value.into_proxied(Private), ); } } } )* }; } impl_scalar_extension!( bool => [proto2_rust_Message_get_extension_bool, proto2_rust_Message_set_extension_bool], f32 => [proto2_rust_Message_get_extension_float, proto2_rust_Message_set_extension_float], f64 => [proto2_rust_Message_get_extension_double, proto2_rust_Message_set_extension_double], i32 => [proto2_rust_Message_get_extension_int32, proto2_rust_Message_set_extension_int32], i64 => [proto2_rust_Message_get_extension_int64, proto2_rust_Message_set_extension_int64], u32 => [proto2_rust_Message_get_extension_uint32, proto2_rust_Message_set_extension_uint32], u64 => [proto2_rust_Message_get_extension_uint64, proto2_rust_Message_set_extension_uint64], ); impl ExtAccess for ExtensionId { fn get<'msg>( &self, _private: Private, msg: impl IntoView<'msg, Proxied = Extendee>, ) -> View<'msg, ProtoString> { let msg = msg.into_view(); pin_extension(self); let ptr_len = unsafe { proto2_rust_Message_get_extension_string( msg.get_raw_message(Private), self.number() as i32, self.default.expect("string extensions must have a default value").into(), ) }; unsafe { ProtoStr::from_utf8_unchecked(ptr_len.as_ref()) } } fn set( &self, _private: Private, mut msg: impl AsMut, value: impl IntoProxied, ) { pin_extension(self); unsafe { proto2_rust_Message_set_extension_string( msg.as_mut().get_raw_message_mut(Private), self.number() as i32, self.inner.field_type, ::into_insertelem(value.into_proxied(Private)), ); } } } impl ExtAccess for ExtensionId { fn get<'msg>( &self, _private: Private, msg: impl IntoView<'msg, Proxied = Extendee>, ) -> View<'msg, ProtoBytes> { let msg = msg.into_view(); pin_extension(self); let ptr_len = unsafe { proto2_rust_Message_get_extension_string( msg.get_raw_message(Private), self.number() as i32, self.default.expect("bytes extensions must have a default value").into(), ) }; unsafe { ptr_len.as_ref() } } fn set( &self, _private: Private, mut msg: impl AsMut, value: impl IntoProxied, ) { pin_extension(self); unsafe { proto2_rust_Message_set_extension_string( msg.as_mut().get_raw_message_mut(Private), self.number() as i32, self.inner.field_type, ::into_insertelem(value.into_proxied(Private)), ); } } } impl ExtAccess for ExtensionId { fn get<'msg>( &self, _private: Private, msg: impl IntoView<'msg, Proxied = Extendee>, ) -> View<'msg, V> { let msg = msg.into_view(); pin_extension(self); let default_instance = ::View::default(); let raw_msg = unsafe { proto2_rust_Message_get_extension_message( msg.get_raw_message(Private), self.number() as i32, default_instance.get_raw_message(Private), ) }; unsafe { >::__unstable_wrap_raw_message_unchecked_lifetime( raw_msg.as_ptr() as *const std::ffi::c_void ) } } fn set( &self, _private: Private, mut msg: impl AsMut, value: impl IntoProxied, ) { let value = value.into_proxied(Private); let mut ext_mut = self.get_mut(msg.as_mut()); ext_mut.take_from(value); } } impl ExtGetMut for ExtensionId { fn get_mut<'msg>( &self, _private: Private, msg: impl IntoMut<'msg, MutProxied = Extendee>, ) -> Mut<'msg, V> { let mut msg = msg.into_mut(); pin_extension(self); let default_instance = ::View::default(); let raw_msg = unsafe { proto2_rust_Message_mutable_extension_message( msg.get_raw_message_mut(Private), self.number() as i32, self.inner.field_type, default_instance.get_raw_message(Private), ) }; unsafe { >::__unstable_wrap_raw_message_mut_unchecked_lifetime( raw_msg.as_ptr() as *mut std::ffi::c_void ) } } } impl ExtClear for ExtensionId { fn clear(&self, _private: Private, mut msg: impl AsMut) { pin_extension(self); unsafe { proto2_rust_Message_clear_extension( msg.as_mut().get_raw_message_mut(Private), self.number() as i32, ) } } } impl ExtAccess, RepeatedTag> for ExtensionId> { fn get<'msg>( &self, _private: Private, msg: impl IntoView<'msg, Proxied = Msg>, ) -> View<'msg, Repeated> { let msg = msg.into_view(); let raw = unsafe { let thunk = self.inner.cpp_get_extension_thunk().unwrap(); thunk(msg.get_raw_message(Private).as_ptr() as *const std::ffi::c_void) as *mut RawRepeatedFieldData }; unsafe { IntoView::into_view(RepeatedView::from_raw( Private, RawRepeatedField::new(raw).unwrap(), )) } } fn set( &self, _private: Private, mut msg: impl AsMut, value: impl IntoProxied>, ) { let value = value.into_proxied(Private); let mut ext_mut = self.get_mut(msg.as_mut()); ext_mut.clear(); ext_mut.copy_from(unsafe { RepeatedView::from_raw(Private, value.inner(Private).raw()) }); } } impl ExtGetMut, RepeatedTag> for ExtensionId> { fn get_mut<'msg>( &self, _private: Private, msg: impl IntoMut<'msg, MutProxied = Msg>, ) -> Mut<'msg, Repeated> { let mut msg = msg.into_mut(); let raw = unsafe { let thunk = self.inner.cpp_mutable_extension_thunk().unwrap(); thunk(msg.get_raw_message_mut(Private).as_ptr() as *mut std::ffi::c_void) as *mut RawRepeatedFieldData }; unsafe { RepeatedMut::from_inner( Private, InnerRepeatedMut::new(RawRepeatedField::new(raw).unwrap()), ) .into_mut() } } } impl ExtAccess for ExtensionId where E: Enum + Proxied + EntityType + Copy, for<'a> E: Proxied = E>, for<'a> Extendee::MessageView<'a>: CppGetRawMessage, i32: From, { fn get<'msg>( &self, _private: Private, msg: impl IntoView<'msg, Proxied = Extendee>, ) -> View<'msg, E> { let msg = msg.into_view(); pin_extension(self); let default = self.default.expect("enum extensions must have a default value"); let val = unsafe { proto2_rust_Message_get_extension_int32( msg.get_raw_message(Private), self.number() as i32, i32::from(default), ) }; E::try_from(val).unwrap_or(default) } fn set( &self, _private: Private, mut msg: impl AsMut, value: impl IntoProxied, ) { pin_extension(self); unsafe { proto2_rust_Message_set_extension_int32( msg.as_mut().get_raw_message_mut(Private), self.number() as i32, self.inner.field_type, value.into_proxied(Private).into(), ); } } }