| // Protocol Buffers - Google's data interchange format | |
| // Copyright 2023 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 crate::{ | |
| __internal::runtime::{InnerMap, InnerMapMut, RawMap, RawMapIter}, | |
| __internal::{Private, SealedInternal}, | |
| AsMut, AsView, IntoMut, IntoProxied, IntoView, Message, Mut, MutProxied, Proxied, Singular, | |
| View, | |
| }; | |
| use std::marker::PhantomData; | |
| /// A trait implemented by types which are allowed as keys in maps. | |
| /// This is all types for fields except for repeated, maps, bytes, messages, enums and floating point types. | |
| #[doc(inline)] | |
| pub use crate::__internal::runtime::MapKey; | |
| /// A trait implemented by types which are allowed as values in maps, which is all Singular types. | |
| /// This trait is distinct from `Singular` only because of the generic `K: MapKey`. | |
| pub trait MapValue: Singular + SealedInternal { | |
| #[doc(hidden)] | |
| fn map_new<K: MapKey>(_: Private) -> Map<K, Self>; | |
| /// # Safety | |
| /// - After `map_free`, no other methods on the input are safe to call. | |
| #[doc(hidden)] | |
| unsafe fn map_free<K: MapKey>(_: Private, map: &mut Map<K, Self>); | |
| #[doc(hidden)] | |
| fn map_clear<K: MapKey>(_: Private, map: MapMut<K, Self>); | |
| #[doc(hidden)] | |
| fn map_len<K: MapKey>(_: Private, map: MapView<K, Self>) -> usize; | |
| #[doc(hidden)] | |
| fn map_insert<K: MapKey>( | |
| _: Private, | |
| map: MapMut<K, Self>, | |
| key: View<'_, K>, | |
| value: impl IntoProxied<Self>, | |
| ) -> bool; | |
| #[doc(hidden)] | |
| fn map_get<'a, K: MapKey>( | |
| _: Private, | |
| map: MapView<'a, K, Self>, | |
| key: View<'_, K>, | |
| ) -> Option<View<'a, Self>>; | |
| #[doc(hidden)] | |
| fn map_get_mut<'a, K: MapKey>( | |
| _: Private, | |
| map: MapMut<'a, K, Self>, | |
| key: View<'_, K>, | |
| ) -> Option<Mut<'a, Self>> | |
| where | |
| Self: Message; | |
| #[doc(hidden)] | |
| fn map_remove<K: MapKey>(_: Private, map: MapMut<K, Self>, key: View<'_, K>) -> bool; | |
| #[doc(hidden)] | |
| fn map_iter<K: MapKey>(_: Private, map: MapView<K, Self>) -> MapIter<K, Self>; | |
| #[doc(hidden)] | |
| fn map_iter_next<'a, K: MapKey>( | |
| _: Private, | |
| iter: &mut MapIter<'a, K, Self>, | |
| ) -> Option<(View<'a, K>, View<'a, Self>)>; | |
| } | |
| pub struct Map<K: MapKey, V: MapValue> { | |
| inner: InnerMap, | |
| _phantom: PhantomData<(PhantomData<K>, PhantomData<V>)>, | |
| } | |
| // SAFETY: `Map` is Sync because it does not implement interior mutability. | |
| unsafe impl<K: MapKey, V: MapValue> Sync for Map<K, V> {} | |
| // SAFETY: `Map` is Send because it's not bound to a specific thread e.g. | |
| // it does not use thread-local data or similar. | |
| unsafe impl<K: MapKey, V: MapValue> Send for Map<K, V> {} | |
| impl<K: MapKey, V: MapValue> SealedInternal for Map<K, V> {} | |
| impl<K: MapKey, V: MapValue> Map<K, V> { | |
| #[inline] | |
| pub fn new() -> Self { | |
| V::map_new(Private) | |
| } | |
| #[inline] | |
| pub fn as_mut(&mut self) -> MapMut<'_, K, V> { | |
| MapMut { inner: self.inner.as_mut(), _phantom: PhantomData } | |
| } | |
| #[inline] | |
| pub fn as_view(&self) -> MapView<'_, K, V> { | |
| MapView { raw: self.inner.raw, _phantom: PhantomData } | |
| } | |
| #[doc(hidden)] | |
| #[inline] | |
| pub fn from_inner(_: Private, inner: InnerMap) -> Self { | |
| Self { inner, _phantom: PhantomData } | |
| } | |
| #[doc(hidden)] | |
| #[inline] | |
| pub fn as_raw(&self, _: Private) -> RawMap { | |
| self.inner.raw | |
| } | |
| } | |
| impl<K: MapKey, V: MapValue> Default for Map<K, V> { | |
| fn default() -> Self { | |
| Map::new() | |
| } | |
| } | |
| impl<K: MapKey, V: MapValue> Drop for Map<K, V> { | |
| fn drop(&mut self) { | |
| // SAFETY: | |
| // - `drop` is only called once. | |
| // - 'map_free` is only called here. | |
| unsafe { V::map_free(Private, self) } | |
| } | |
| } | |
| impl<K: MapKey, V: MapValue> Proxied for Map<K, V> { | |
| type View<'msg> = MapView<'msg, K, V>; | |
| } | |
| impl<K: MapKey, V: MapValue> AsView for Map<K, V> { | |
| type Proxied = Self; | |
| fn as_view(&self) -> MapView<'_, K, V> { | |
| self.as_view() | |
| } | |
| } | |
| impl<K: MapKey, V: MapValue> MutProxied for Map<K, V> { | |
| type Mut<'msg> = MapMut<'msg, K, V>; | |
| } | |
| impl<K: MapKey, V: MapValue> AsMut for Map<K, V> { | |
| type MutProxied = Self; | |
| fn as_mut(&mut self) -> MapMut<'_, K, V> { | |
| self.as_mut() | |
| } | |
| } | |
| impl<'msg, K, KView, V, VView, I> IntoProxied<Map<K, V>> for I | |
| where | |
| I: Iterator<Item = (KView, VView)>, | |
| K: MapKey, | |
| V: MapValue, | |
| KView: Into<View<'msg, K>>, | |
| VView: IntoProxied<V>, | |
| { | |
| fn into_proxied(self, _: Private) -> Map<K, V> { | |
| let mut m = Map::<K, V>::new(); | |
| m.as_mut().extend(self); | |
| m | |
| } | |
| } | |
| /// A view of a map field. | |
| /// | |
| /// This is a proxy type that is conceptually similar to a `&Map<K, V>` | |
| #[repr(transparent)] | |
| pub struct MapView<'msg, K: ?Sized, V: ?Sized> { | |
| raw: RawMap, | |
| _phantom: PhantomData<(&'msg K, &'msg V)>, | |
| } | |
| impl<'msg, K: ?Sized, V: ?Sized> Copy for MapView<'msg, K, V> {} | |
| impl<'msg, K: ?Sized, V: ?Sized> Clone for MapView<'msg, K, V> { | |
| fn clone(&self) -> Self { | |
| *self | |
| } | |
| } | |
| unsafe impl<'msg, K: ?Sized, V: ?Sized> Sync for MapView<'msg, K, V> {} | |
| unsafe impl<'msg, K: ?Sized, V: ?Sized> Send for MapView<'msg, K, V> {} | |
| impl<'msg, K: ?Sized, V: ?Sized> std::fmt::Debug for MapView<'msg, K, V> { | |
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | |
| f.debug_tuple("MapView") | |
| .field(&std::any::type_name::<K>()) | |
| .field(&std::any::type_name::<V>()) | |
| .finish() | |
| } | |
| } | |
| impl<'msg, K: MapKey, V: MapValue> SealedInternal for MapView<'msg, K, V> {} | |
| #[doc(hidden)] | |
| impl<'msg, K: ?Sized, V: ?Sized> MapView<'msg, K, V> { | |
| #[doc(hidden)] | |
| pub fn as_raw(&self, _: Private) -> RawMap { | |
| self.raw | |
| } | |
| /// # Safety | |
| /// - `raw` must be valid to read from for `'msg`. | |
| #[doc(hidden)] | |
| pub unsafe fn from_raw(_: Private, raw: RawMap) -> Self { | |
| Self { raw, _phantom: PhantomData } | |
| } | |
| } | |
| impl<'msg, K: MapKey, V: MapValue> MapView<'msg, K, V> { | |
| #[inline] | |
| pub fn get<'a>(self, key: impl Into<View<'a, K>>) -> Option<View<'msg, V>> | |
| where | |
| K: 'a, | |
| { | |
| V::map_get(Private, self, key.into()) | |
| } | |
| #[inline] | |
| pub fn len(self) -> usize { | |
| V::map_len(Private, self) | |
| } | |
| #[inline] | |
| pub fn is_empty(self) -> bool { | |
| self.len() == 0 | |
| } | |
| #[inline] | |
| pub fn contains_key<'a>(self, key: impl Into<View<'a, K>>) -> bool | |
| where | |
| K: 'a, | |
| { | |
| self.get(key).is_some() | |
| } | |
| /// Returns an iterator visiting all key-value pairs in arbitrary order. | |
| /// | |
| /// The iterator element type is `(View<K>, View<V>)`. | |
| /// This is an alias for `<Self as IntoIterator>::into_iter`. | |
| pub fn iter(self) -> MapIter<'msg, K, V> { | |
| self.into_iter() | |
| } | |
| /// Returns an iterator visiting all keys in arbitrary order. | |
| /// | |
| /// The iterator element type is `View<K>`. | |
| pub fn keys(self) -> impl Iterator<Item = View<'msg, K>> + 'msg { | |
| self.into_iter().map(|(k, _)| k) | |
| } | |
| /// Returns an iterator visiting all values in arbitrary order. | |
| /// | |
| /// The iterator element type is `View<V>`. | |
| pub fn values(self) -> impl Iterator<Item = View<'msg, V>> + 'msg { | |
| self.into_iter().map(|(_, v)| v) | |
| } | |
| } | |
| impl<'msg, K: MapKey, V: MapValue> AsView for MapView<'msg, K, V> { | |
| type Proxied = Map<K, V>; | |
| fn as_view(&self) -> MapView<'_, K, V> { | |
| *self | |
| } | |
| } | |
| impl<'msg, K: MapKey, V: MapValue> IntoView<'msg> for MapView<'msg, K, V> { | |
| fn into_view<'shorter>(self) -> MapView<'shorter, K, V> | |
| where | |
| 'msg: 'shorter, | |
| { | |
| MapView { raw: self.raw, _phantom: PhantomData } | |
| } | |
| } | |
| impl<'msg, K: MapKey, V: MapValue> IntoProxied<Map<K, V>> for MapView<'msg, K, V> | |
| where | |
| View<'msg, V>: IntoProxied<V>, | |
| { | |
| fn into_proxied(self, _: Private) -> Map<K, V> { | |
| let mut m = Map::<K, V>::new(); | |
| m.as_mut().copy_from(self); | |
| m | |
| } | |
| } | |
| /// A mutable proxy of a map field. | |
| /// | |
| /// This is a proxy type that is conceptually similar to a `&mut Map<K, V>` | |
| pub struct MapMut<'msg, K: ?Sized, V: ?Sized> { | |
| pub(crate) inner: InnerMapMut<'msg>, | |
| _phantom: PhantomData<(&'msg mut K, &'msg mut V)>, | |
| } | |
| impl<'msg, K: ?Sized, V: ?Sized> MapMut<'msg, K, V> { | |
| #[doc(hidden)] | |
| pub fn inner(&self, _: Private) -> InnerMapMut<'_> { | |
| self.inner | |
| } | |
| } | |
| unsafe impl<'msg, K: ?Sized, V: ?Sized> Sync for MapMut<'msg, K, V> {} | |
| impl<'msg, K: ?Sized, V: ?Sized> std::fmt::Debug for MapMut<'msg, K, V> { | |
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | |
| f.debug_tuple("MapMut") | |
| .field(&std::any::type_name::<K>()) | |
| .field(&std::any::type_name::<V>()) | |
| .finish() | |
| } | |
| } | |
| impl<'msg, K: MapKey, V: MapValue> SealedInternal for MapMut<'msg, K, V> {} | |
| impl<'msg, K: MapKey, V: MapValue> AsView for MapMut<'msg, K, V> { | |
| type Proxied = Map<K, V>; | |
| fn as_view(&self) -> MapView<'_, K, V> { | |
| MapView { raw: self.inner.raw, _phantom: PhantomData } | |
| } | |
| } | |
| impl<'msg, K: MapKey, V: MapValue> IntoView<'msg> for MapMut<'msg, K, V> { | |
| fn into_view<'shorter>(self) -> MapView<'shorter, K, V> | |
| where | |
| 'msg: 'shorter, | |
| { | |
| MapView { raw: self.inner.raw, _phantom: PhantomData } | |
| } | |
| } | |
| impl<'msg, K: MapKey, V: MapValue> AsMut for MapMut<'msg, K, V> { | |
| type MutProxied = Map<K, V>; | |
| fn as_mut(&mut self) -> MapMut<'_, K, V> { | |
| MapMut { inner: self.inner, _phantom: PhantomData } | |
| } | |
| } | |
| impl<'msg, K: MapKey, V: MapValue> IntoMut<'msg> for MapMut<'msg, K, V> { | |
| fn into_mut<'shorter>(self) -> MapMut<'shorter, K, V> | |
| where | |
| 'msg: 'shorter, | |
| { | |
| MapMut { inner: self.inner, _phantom: PhantomData } | |
| } | |
| } | |
| #[doc(hidden)] | |
| impl<'msg, K: ?Sized, V: ?Sized> MapMut<'msg, K, V> { | |
| /// # Safety | |
| /// - `inner` must be valid to read and write from for `'msg`. | |
| #[doc(hidden)] | |
| pub unsafe fn from_inner(_: Private, inner: InnerMapMut<'msg>) -> Self { | |
| Self { inner, _phantom: PhantomData } | |
| } | |
| #[doc(hidden)] | |
| pub fn as_raw(&mut self, _: Private) -> RawMap { | |
| self.inner.raw | |
| } | |
| } | |
| impl<'msg, K: MapKey, V: MapValue> MapMut<'msg, K, V> { | |
| #[inline] | |
| pub fn len(&self) -> usize { | |
| self.as_view().len() | |
| } | |
| #[inline] | |
| pub fn is_empty(&self) -> bool { | |
| self.len() == 0 | |
| } | |
| #[inline] | |
| pub fn contains_key<'a>(&self, key: impl Into<View<'a, K>>) -> bool | |
| where | |
| K: 'a, | |
| { | |
| self.as_view().contains_key(key) | |
| } | |
| /// Adds a key-value pair to the map. | |
| /// | |
| /// Returns `true` if the entry was newly inserted. | |
| #[inline] | |
| pub fn insert<'a>(&mut self, key: impl Into<View<'a, K>>, value: impl IntoProxied<V>) -> bool { | |
| V::map_insert(Private, self.as_mut(), key.into(), value) | |
| } | |
| #[inline] | |
| pub fn remove<'a>(&mut self, key: impl Into<View<'a, K>>) -> bool { | |
| V::map_remove(Private, self.as_mut(), key.into()) | |
| } | |
| #[inline] | |
| pub fn clear(&mut self) { | |
| V::map_clear(Private, self.as_mut()) | |
| } | |
| #[inline] | |
| pub fn get<'a>(&self, key: impl Into<View<'a, K>>) -> Option<View<'_, V>> { | |
| V::map_get(Private, self.as_view(), key.into()) | |
| } | |
| #[inline] | |
| pub fn get_mut<'a>(&mut self, key: impl Into<View<'a, K>>) -> Option<Mut<'_, V>> | |
| where | |
| V: Message, | |
| { | |
| V::map_get_mut(Private, self.as_mut(), key.into()) | |
| } | |
| pub fn copy_from<'a>( | |
| &mut self, | |
| src: impl IntoIterator<Item = (impl Into<View<'a, K>>, impl IntoProxied<V>)>, | |
| ) { | |
| //TODO | |
| self.clear(); | |
| for (k, v) in src.into_iter() { | |
| self.insert(k, v); | |
| } | |
| } | |
| /// Returns an iterator visiting all key-value pairs in arbitrary order. | |
| /// | |
| /// The iterator element type is `(View<K>, View<V>)`. | |
| #[inline] | |
| pub fn iter(&self) -> MapIter<'_, K, V> { | |
| self.into_iter() | |
| } | |
| /// Returns an iterator visiting all keys in arbitrary order. | |
| /// | |
| /// The iterator element type is `View<K>`. | |
| #[inline] | |
| pub fn keys(&self) -> impl Iterator<Item = View<'_, K>> + '_ { | |
| self.as_view().keys() | |
| } | |
| /// Returns an iterator visiting all values in arbitrary order. | |
| /// | |
| /// The iterator element type is `View<V>`. | |
| #[inline] | |
| pub fn values(&self) -> impl Iterator<Item = View<'_, V>> + '_ { | |
| self.as_view().values() | |
| } | |
| } | |
| impl<'msg, K: MapKey, V: MapValue> IntoProxied<Map<K, V>> for MapMut<'msg, K, V> | |
| where | |
| View<'msg, V>: IntoProxied<V>, | |
| { | |
| fn into_proxied(self, _: Private) -> Map<K, V> { | |
| self.into_view().into_proxied(Private) | |
| } | |
| } | |
| impl<'msg, 'k, KView, VView, K, V> Extend<(KView, VView)> for MapMut<'msg, K, V> | |
| where | |
| K: MapKey, | |
| V: MapValue, | |
| KView: Into<View<'k, K>>, | |
| VView: IntoProxied<V>, | |
| { | |
| fn extend<T: IntoIterator<Item = (KView, VView)>>(&mut self, iter: T) { | |
| for (k, v) in iter.into_iter() { | |
| self.insert(k, v); | |
| } | |
| } | |
| } | |
| /// An iterator visiting all key-value pairs in arbitrary order. | |
| /// | |
| /// The iterator element type is `(View<Key>, View<Value>)`. | |
| pub struct MapIter<'msg, K: ?Sized, V: ?Sized> { | |
| raw: RawMapIter, | |
| _phantom: PhantomData<(&'msg K, &'msg V)>, | |
| } | |
| impl<'msg, K: ?Sized, V: ?Sized> MapIter<'msg, K, V> { | |
| /// # Safety | |
| /// - `raw` must be a valid instance of the raw iterator for `'msg`. | |
| /// - The untyped `raw` iterator must be for a map of `K,V`. | |
| /// - The backing map must be live and unmodified for `'msg`. | |
| #[doc(hidden)] | |
| pub unsafe fn from_raw(_: Private, raw: RawMapIter) -> Self { | |
| Self { raw, _phantom: PhantomData } | |
| } | |
| #[doc(hidden)] | |
| pub fn as_raw_mut(&mut self, _: Private) -> &mut RawMapIter { | |
| &mut self.raw | |
| } | |
| } | |
| impl<'msg, K: MapKey, V: MapValue> Iterator for MapIter<'msg, K, V> { | |
| type Item = (View<'msg, K>, View<'msg, V>); | |
| fn next(&mut self) -> Option<Self::Item> { | |
| V::map_iter_next(Private, self) | |
| } | |
| } | |
| impl<'msg, K: MapKey, V: MapValue> IntoIterator for MapView<'msg, K, V> { | |
| type IntoIter = MapIter<'msg, K, V>; | |
| type Item = (View<'msg, K>, View<'msg, V>); | |
| fn into_iter(self) -> MapIter<'msg, K, V> { | |
| V::map_iter(Private, self) | |
| } | |
| } | |
| impl<'msg, K: MapKey, V: MapValue> IntoIterator for &'msg Map<K, V> { | |
| type IntoIter = MapIter<'msg, K, V>; | |
| type Item = (View<'msg, K>, View<'msg, V>); | |
| fn into_iter(self) -> MapIter<'msg, K, V> { | |
| self.as_view().into_iter() | |
| } | |
| } | |
| impl<'a, 'msg, K: MapKey, V: MapValue> IntoIterator for &'a MapView<'msg, K, V> | |
| where | |
| 'msg: 'a, | |
| { | |
| type IntoIter = MapIter<'msg, K, V>; | |
| type Item = (View<'msg, K>, View<'msg, V>); | |
| fn into_iter(self) -> MapIter<'msg, K, V> { | |
| (*self).into_iter() | |
| } | |
| } | |
| impl<'a, 'msg, K: MapKey, V: MapValue> IntoIterator for &'a MapMut<'msg, K, V> | |
| where | |
| 'msg: 'a, | |
| { | |
| type IntoIter = MapIter<'a, K, V>; | |
| // The View's are valid for 'a instead of 'msg. | |
| // This is because the mutator may mutate past 'a but before 'msg expires. | |
| type Item = (View<'a, K>, View<'a, V>); | |
| fn into_iter(self) -> MapIter<'a, K, V> { | |
| self.as_view().into_iter() | |
| } | |
| } | |
| #[cfg(test)] | |
| mod tests { | |
| use super::*; | |
| use crate::{ProtoBytes, ProtoStr, ProtoString}; | |
| use googletest::prelude::*; | |
| #[gtest] | |
| fn test_proxied_scalar() { | |
| let mut map: Map<i32, i64> = Map::new(); | |
| let mut map_mut = map.as_mut(); | |
| map_mut.insert(1, 2); | |
| assert_that!(map_mut.get(1), eq(Some(2))); | |
| let map_view_1 = map_mut.as_view(); | |
| assert_that!(map_view_1.len(), eq(1)); | |
| assert_that!(map_view_1.get(1), eq(Some(2))); | |
| map_mut.insert(3, 4); | |
| let map_view_2 = map_mut.into_view(); | |
| assert_that!(map_view_2.len(), eq(2)); | |
| assert_that!(map_view_2.get(3), eq(Some(4))); | |
| { | |
| let map_view_3 = map_view_2.as_view(); | |
| assert_that!(map_view_3.is_empty(), eq(false)); | |
| } | |
| let map_view_4 = map_view_2.into_view(); | |
| assert_that!(map_view_4.is_empty(), eq(false)); | |
| } | |
| #[gtest] | |
| fn test_proxied_str() { | |
| let mut map: Map<ProtoString, ProtoString> = Map::new(); | |
| let mut map_mut = map.as_mut(); | |
| map_mut.insert("a", "b"); | |
| let map_view_1 = map_mut.as_view(); | |
| assert_that!(map_view_1.len(), eq(1)); | |
| assert_that!(map_view_1.get("a").unwrap(), eq("b")); | |
| map_mut.insert("c", "d"); | |
| let map_view_2 = map_mut.into_view(); | |
| assert_that!(map_view_2.len(), eq(2)); | |
| assert_that!(map_view_2.get("c").unwrap(), eq("d")); | |
| { | |
| let map_view_3 = map_view_2.as_view(); | |
| assert_that!(map_view_3.is_empty(), eq(false)); | |
| } | |
| let map_view_4 = map_view_2.into_view(); | |
| assert_that!(map_view_4.is_empty(), eq(false)); | |
| } | |
| #[gtest] | |
| fn test_proxied_iter() { | |
| let mut map: Map<i32, ProtoString> = Map::new(); | |
| let mut map_mut = map.as_mut(); | |
| map_mut.insert(15, "fizzbuzz"); | |
| map_mut.insert(5, "buzz"); | |
| map_mut.insert(3, "fizz"); | |
| // ProtoStr::from_str is necessary below because | |
| // https://doc.rust-lang.org/std/primitive.tuple.html#impl-PartialEq-for-(T,) | |
| // only compares where the types are the same, even when the tuple types can | |
| // compare with each other. | |
| // googletest-rust matchers also do not currently implement Clone. | |
| assert_that!( | |
| map.as_view().iter().collect::<Vec<_>>(), | |
| unordered_elements_are![ | |
| eq(&(3, ProtoStr::from_str("fizz"))), | |
| eq(&(5, ProtoStr::from_str("buzz"))), | |
| eq(&(15, ProtoStr::from_str("fizzbuzz"))) | |
| ] | |
| ); | |
| assert_that!( | |
| map.as_view(), | |
| unordered_elements_are![ | |
| eq((3, ProtoStr::from_str("fizz"))), | |
| eq((5, ProtoStr::from_str("buzz"))), | |
| eq((15, ProtoStr::from_str("fizzbuzz"))) | |
| ] | |
| ); | |
| assert_that!( | |
| map.as_mut().iter().collect::<Vec<_>>(), | |
| unordered_elements_are![ | |
| eq(&(3, ProtoStr::from_str("fizz"))), | |
| eq(&(5, ProtoStr::from_str("buzz"))), | |
| eq(&(15, ProtoStr::from_str("fizzbuzz"))) | |
| ] | |
| ); | |
| assert_that!( | |
| map.as_mut(), | |
| unordered_elements_are![ | |
| eq((3, ProtoStr::from_str("fizz"))), | |
| eq((5, ProtoStr::from_str("buzz"))), | |
| eq((15, ProtoStr::from_str("fizzbuzz"))) | |
| ] | |
| ); | |
| } | |
| #[gtest] | |
| fn test_overwrite_insert() { | |
| let mut map: Map<i32, ProtoString> = Map::new(); | |
| let mut map_mut = map.as_mut(); | |
| assert!(map_mut.insert(0, "fizz")); | |
| // insert should return false when the key is already present | |
| assert!(!map_mut.insert(0, "buzz")); | |
| assert_that!(map.as_mut(), unordered_elements_are![eq((0, ProtoStr::from_str("buzz"))),]); | |
| } | |
| #[gtest] | |
| fn test_extend() { | |
| let mut map: Map<i32, ProtoString> = Map::new(); | |
| let mut map_mut = map.as_mut(); | |
| map_mut.extend([(0, ""); 0]); | |
| assert_that!(map_mut.len(), eq(0)); | |
| map_mut.extend([(0, "fizz"), (1, "buzz"), (2, "fizzbuzz")]); | |
| assert_that!( | |
| map.as_view(), | |
| unordered_elements_are![ | |
| eq((0, ProtoStr::from_str("fizz"))), | |
| eq((1, ProtoStr::from_str("buzz"))), | |
| eq((2, ProtoStr::from_str("fizzbuzz"))) | |
| ] | |
| ); | |
| let mut map_2: Map<i32, ProtoString> = Map::new(); | |
| let mut map_2_mut = map_2.as_mut(); | |
| map_2_mut.extend([(2, "bing"), (3, "bong")]); | |
| let mut map_mut = map.as_mut(); | |
| map_mut.extend(&map_2); | |
| assert_that!( | |
| map.as_view(), | |
| unordered_elements_are![ | |
| eq((0, ProtoStr::from_str("fizz"))), | |
| eq((1, ProtoStr::from_str("buzz"))), | |
| eq((2, ProtoStr::from_str("bing"))), | |
| eq((3, ProtoStr::from_str("bong"))) | |
| ] | |
| ); | |
| } | |
| #[gtest] | |
| fn test_copy_from() { | |
| let mut map: Map<i32, ProtoString> = Map::new(); | |
| let mut map_mut = map.as_mut(); | |
| map_mut.copy_from([(0, "fizz"), (1, "buzz"), (2, "fizzbuzz")]); | |
| assert_that!( | |
| map.as_view(), | |
| unordered_elements_are![ | |
| eq((0, ProtoStr::from_str("fizz"))), | |
| eq((1, ProtoStr::from_str("buzz"))), | |
| eq((2, ProtoStr::from_str("fizzbuzz"))) | |
| ] | |
| ); | |
| let mut map_2: Map<i32, ProtoString> = Map::new(); | |
| let mut map_2_mut = map_2.as_mut(); | |
| map_2_mut.copy_from([(2, "bing"), (3, "bong")]); | |
| let mut map_mut = map.as_mut(); | |
| map_mut.copy_from(&map_2); | |
| assert_that!( | |
| map.as_view(), | |
| unordered_elements_are![ | |
| eq((2, ProtoStr::from_str("bing"))), | |
| eq((3, ProtoStr::from_str("bong"))) | |
| ] | |
| ); | |
| } | |
| #[gtest] | |
| fn test_all_maps_can_be_constructed() { | |
| macro_rules! gen_proto_values { | |
| ($key_t:ty, $($value_t:ty),*) => { | |
| $( | |
| let map = Map::<$key_t, $value_t>::new(); | |
| assert_that!(map.as_view().len(), eq(0)); | |
| )* | |
| } | |
| } | |
| macro_rules! gen_proto_keys { | |
| ($($key_t:ty),*) => { | |
| $( | |
| gen_proto_values!($key_t, f32, f64, i32, u32, i64, bool, ProtoString, ProtoBytes); | |
| )* | |
| } | |
| } | |
| gen_proto_keys!(i32, u32, i64, u64, bool, ProtoString); | |
| } | |
| #[gtest] | |
| fn test_dbg() { | |
| let mut map = Map::<i32, f64>::new(); | |
| assert_that!(format!("{:?}", map.as_view()), eq("MapView(\"i32\", \"f64\")")); | |
| assert_that!(format!("{:?}", map.as_mut()), eq("MapMut(\"i32\", \"f64\")")); | |
| } | |
| #[gtest] | |
| fn test_contains_key() { | |
| let mut map = Map::<i32, f64>::new(); | |
| let mut map_mut = map.as_mut(); | |
| assert!(!map_mut.contains_key(42)); | |
| assert!(!map_mut.as_view().contains_key(42)); | |
| map_mut.insert(42, 1.0); | |
| assert!(map_mut.contains_key(42)); | |
| assert!(map_mut.as_view().contains_key(42)); | |
| } | |
| } |