| // 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, 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<Extendee: Message, T: Proxied>(extension: &ExtensionId<Extendee, T>) { | |
| 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<unsafe extern "C" fn(*const c_void) -> *const c_void>, | |
| cpp_mutable_extension_thunk: Option<unsafe extern "C" fn(*mut c_void) -> *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<unsafe extern "C" fn(*const c_void) -> *const c_void> { | |
| self.cpp_get_extension_thunk | |
| } | |
| pub fn cpp_mutable_extension_thunk( | |
| &self, | |
| ) -> Option<unsafe extern "C" fn(*mut c_void) -> *mut c_void> { | |
| self.cpp_mutable_extension_thunk | |
| } | |
| } | |
| impl<Msg: Message, T: Singular> ExtHas<Msg> for ExtensionId<Msg, T> { | |
| fn has(&self, _private: Private, msg: impl AsView<Proxied = Msg>) -> 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<Extendee: Message> ExtAccess<Extendee, $t, PrimitiveTag> | |
| for ExtensionId<Extendee, $t> | |
| { | |
| 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<MutProxied = Extendee>, 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<Extendee: Message> ExtAccess<Extendee, ProtoString, PrimitiveTag> | |
| for ExtensionId<Extendee, ProtoString> | |
| { | |
| 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<MutProxied = Extendee>, | |
| value: impl IntoProxied<ProtoString>, | |
| ) { | |
| 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, | |
| <ProtoString as CppTypeConversions>::into_insertelem(value.into_proxied(Private)), | |
| ); | |
| } | |
| } | |
| } | |
| impl<Extendee: Message> ExtAccess<Extendee, ProtoBytes, PrimitiveTag> | |
| for ExtensionId<Extendee, ProtoBytes> | |
| { | |
| 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<MutProxied = Extendee>, | |
| value: impl IntoProxied<ProtoBytes>, | |
| ) { | |
| 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, | |
| <ProtoBytes as CppTypeConversions>::into_insertelem(value.into_proxied(Private)), | |
| ); | |
| } | |
| } | |
| } | |
| impl<Extendee: Message, V: Message> ExtAccess<Extendee, V, MessageTag> | |
| for ExtensionId<Extendee, V> | |
| { | |
| 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 = <V as Proxied>::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 { | |
| <View<'msg, V>>::__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<MutProxied = Extendee>, | |
| value: impl IntoProxied<V>, | |
| ) { | |
| let value = value.into_proxied(Private); | |
| let mut ext_mut = self.get_mut(msg.as_mut()); | |
| ext_mut.take_from(value); | |
| } | |
| } | |
| impl<Extendee: Message, V: Message> ExtGetMut<Extendee, V, MessageTag> | |
| for ExtensionId<Extendee, V> | |
| { | |
| 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 = <V as Proxied>::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 { | |
| <Mut<'msg, V>>::__unstable_wrap_raw_message_mut_unchecked_lifetime( | |
| raw_msg.as_ptr() as *mut std::ffi::c_void | |
| ) | |
| } | |
| } | |
| } | |
| impl<Msg: Message, T: Proxied> ExtClear<Msg> for ExtensionId<Msg, T> { | |
| fn clear(&self, _private: Private, mut msg: impl AsMut<MutProxied = Msg>) { | |
| pin_extension(self); | |
| unsafe { | |
| proto2_rust_Message_clear_extension( | |
| msg.as_mut().get_raw_message_mut(Private), | |
| self.number() as i32, | |
| ) | |
| } | |
| } | |
| } | |
| impl<Msg: Message, V: Singular> ExtAccess<Msg, Repeated<V>, RepeatedTag> | |
| for ExtensionId<Msg, Repeated<V>> | |
| { | |
| fn get<'msg>( | |
| &self, | |
| _private: Private, | |
| msg: impl IntoView<'msg, Proxied = Msg>, | |
| ) -> View<'msg, Repeated<V>> { | |
| 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<MutProxied = Msg>, | |
| value: impl IntoProxied<Repeated<V>>, | |
| ) { | |
| 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<Msg: Message, V: Singular> ExtGetMut<Msg, Repeated<V>, RepeatedTag> | |
| for ExtensionId<Msg, Repeated<V>> | |
| { | |
| fn get_mut<'msg>( | |
| &self, | |
| _private: Private, | |
| msg: impl IntoMut<'msg, MutProxied = Msg>, | |
| ) -> Mut<'msg, Repeated<V>> { | |
| 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<Extendee: Message, E> ExtAccess<Extendee, E, EnumTag> for ExtensionId<Extendee, E> | |
| where | |
| E: Enum + Proxied + EntityType<Tag = EnumTag> + Copy, | |
| for<'a> E: Proxied<View<'a> = E>, | |
| for<'a> Extendee::MessageView<'a>: CppGetRawMessage, | |
| i32: From<E>, | |
| { | |
| 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<MutProxied = Extendee>, | |
| value: impl IntoProxied<E>, | |
| ) { | |
| 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(), | |
| ); | |
| } | |
| } | |
| } |