use super::*; /// Returns a static empty MapView. pub fn empty_map() -> MapView<'static, K, V> where K: MapKey, V: MapValue, { // TODO: Consider creating a static empty map in C. // Use `` for a shared empty map for all map types. // // This relies on an implicit contract with UPB that it is OK to use an empty // Map as an empty map of all other types. The only const // function on `upb_Map` that will care about the size of key or value is // `get()` where it will hash the appropriate number of bytes of the // provided `upb_MessageValue`, and that bool being the smallest type in the // union means it will happen to work for all possible key types. // // If we used a larger key, then UPB would hash more bytes of the key than Rust // initialized. static EMPTY_MAP_VIEW: OnceLock> = OnceLock::new(); // SAFETY: // - The map is empty and never mutated. // - The value type is never used. // - The size of the key type is used when `get()` computes the hash of the key. // The map is empty, therefore it doesn't matter what hash is computed, but we // have to use `bool` type as the smallest key possible (otherwise UPB would // read more bytes than Rust allocated). unsafe { MapView::from_raw(Private, EMPTY_MAP_VIEW.get_or_init(Map::new).as_view().as_raw(Private)) } } impl<'msg, K: ?Sized, V: ?Sized> MapMut<'msg, K, V> { // Returns a `RawArena` which is live for at least `'msg` #[doc(hidden)] pub fn raw_arena(&mut self, _private: Private) -> RawArena { self.inner.arena.raw() } // Returns an `Arena` which is live for at least `'msg` #[doc(hidden)] pub fn arena(&self, _private: Private) -> &'msg Arena { self.inner.arena } } #[derive(Debug)] #[doc(hidden)] pub struct InnerMap { pub(crate) raw: RawMap, arena: Arena, } impl InnerMap { pub fn new(raw: RawMap, arena: Arena) -> Self { Self { raw, arena } } pub fn as_mut(&mut self) -> InnerMapMut<'_> { InnerMapMut { raw: self.raw, arena: &self.arena } } } #[derive(Clone, Copy, Debug)] #[doc(hidden)] pub struct InnerMapMut<'msg> { pub(crate) raw: RawMap, arena: &'msg Arena, } #[doc(hidden)] impl<'msg> InnerMapMut<'msg> { pub fn new(raw: RawMap, arena: &'msg Arena) -> Self { InnerMapMut { raw, arena } } #[doc(hidden)] pub fn as_raw(&self) -> RawMap { self.raw } pub fn arena(&mut self) -> &Arena { self.arena } #[doc(hidden)] pub fn raw_arena(&mut self) -> RawArena { self.arena.raw() } } #[doc(hidden)] pub struct RawMapIter { // TODO: Replace this `RawMap` with the const type. map: RawMap, iter: usize, } impl RawMapIter { pub fn new(map: RawMap) -> Self { RawMapIter { map, iter: UPB_MAP_BEGIN } } /// # Safety /// - `self.map` must be valid, and remain valid while the return value is /// in use. pub unsafe fn next_unchecked(&mut self) -> Option<(upb_MessageValue, upb_MessageValue)> { let mut key = MaybeUninit::uninit(); let mut value = MaybeUninit::uninit(); // SAFETY: the `map` is valid as promised by the caller unsafe { upb_Map_Next(self.map, key.as_mut_ptr(), value.as_mut_ptr(), &mut self.iter) } // SAFETY: if upb_Map_Next returns true, then key and value have been populated. .then(|| unsafe { (key.assume_init(), value.assume_init()) }) } } impl MapValue for MessageType where Self: Proxied + EntityType + UpbTypeConversions<::Tag>, { fn map_new(_private: Private) -> Map { let arena = Arena::new(); let raw = unsafe { upb_Map_New(arena.raw(), K::upb_type(), Self::upb_type()) }; Map::from_inner(Private, InnerMap::new(raw, arena)) } unsafe fn map_free(_private: Private, _map: &mut Map) { // No-op: the memory will be dropped by the arena. } fn map_clear(_private: Private, mut map: MapMut) { unsafe { upb_Map_Clear(map.as_raw(Private)); } } fn map_len(_private: Private, map: MapView) -> usize { unsafe { upb_Map_Size(map.as_raw(Private)) } } fn map_insert( _private: Private, mut map: MapMut, key: View<'_, K>, value: impl IntoProxied, ) -> bool { let arena = map.inner(Private).raw_arena(); let insert_status = unsafe { upb_Map_Insert( map.as_raw(Private), K::to_message_value(key), Self::into_message_value_fuse_if_required(arena, value.into_proxied(Private)), arena, ) }; match insert_status { upb::MapInsertStatus::Inserted => true, upb::MapInsertStatus::Replaced => false, upb::MapInsertStatus::OutOfMemory => { panic!("map insert failed (alloc should be infallible)") } } } fn map_get<'a, K: MapKey>( _private: Private, map: MapView<'a, K, Self>, key: View<'_, K>, ) -> Option> { let mut val = MaybeUninit::uninit(); let found = unsafe { upb_Map_Get(map.as_raw(Private), K::to_message_value(key), val.as_mut_ptr()) }; if !found { return None; } Some(unsafe { Self::from_message_value(val.assume_init()) }) } fn map_get_mut<'a, K: MapKey>( _private: Private, mut map: MapMut<'a, K, Self>, key: View<'_, K>, ) -> Option> where Self: Message, { // SAFETY: The map is valid as promised by the caller. let val = unsafe { upb_Map_GetMutable(map.as_raw(Private), K::to_message_value(key)) }; // SAFETY: The lifetime of the MapMut is guaranteed to outlive the returned Mut. NonNull::new(val).map(|msg| unsafe { Self::from_message_mut(msg, map.arena(Private)) }) } fn map_remove( _private: Private, mut map: MapMut, key: View<'_, K>, ) -> bool { unsafe { upb_Map_Delete(map.as_raw(Private), K::to_message_value(key), ptr::null_mut()) } } fn map_iter(_private: Private, map: MapView) -> MapIter { // SAFETY: MapView<'_,..>> guarantees its RawMap outlives '_. unsafe { MapIter::from_raw(Private, RawMapIter::new(map.as_raw(Private))) } } fn map_iter_next<'a, K: MapKey>( _private: Private, iter: &mut MapIter<'a, K, Self>, ) -> Option<(View<'a, K>, View<'a, Self>)> { // SAFETY: MapIter<'a, ..> guarantees its RawMapIter outlives 'a. unsafe { iter.as_raw_mut(Private).next_unchecked() } // SAFETY: MapIter returns key and values message values // with the variants for K and V active. .map(|(k, v)| unsafe { (K::from_message_value(k), Self::from_message_value(v)) }) } }