| use super::*; | |
| /// Returns a static empty MapView. | |
| pub fn empty_map<K, V>() -> MapView<'static, K, V> | |
| where | |
| K: MapKey, | |
| V: MapValue, | |
| { | |
| // TODO: Consider creating a static empty map in C. | |
| // Use `<bool, bool>` 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<bool, bool> 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<Map<bool, bool>> = 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<MessageType> MapValue for MessageType | |
| where | |
| Self: Proxied + EntityType + UpbTypeConversions<<Self as EntityType>::Tag>, | |
| { | |
| fn map_new<K: MapKey>(_private: Private) -> Map<K, Self> { | |
| 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<K: MapKey>(_private: Private, _map: &mut Map<K, Self>) { | |
| // No-op: the memory will be dropped by the arena. | |
| } | |
| fn map_clear<K: MapKey>(_private: Private, mut map: MapMut<K, Self>) { | |
| unsafe { | |
| upb_Map_Clear(map.as_raw(Private)); | |
| } | |
| } | |
| fn map_len<K: MapKey>(_private: Private, map: MapView<K, Self>) -> usize { | |
| unsafe { upb_Map_Size(map.as_raw(Private)) } | |
| } | |
| fn map_insert<K: MapKey>( | |
| _private: Private, | |
| mut map: MapMut<K, Self>, | |
| key: View<'_, K>, | |
| value: impl IntoProxied<Self>, | |
| ) -> 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<View<'a, Self>> { | |
| 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<Mut<'a, Self>> | |
| 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<K: MapKey>( | |
| _private: Private, | |
| mut map: MapMut<K, Self>, | |
| key: View<'_, K>, | |
| ) -> bool { | |
| unsafe { upb_Map_Delete(map.as_raw(Private), K::to_message_value(key), ptr::null_mut()) } | |
| } | |
| fn map_iter<K: MapKey>(_private: Private, map: MapView<K, Self>) -> MapIter<K, Self> { | |
| // 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<K, V> 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)) }) | |
| } | |
| } |