use crate::contrib::exec_spec::*;
use crate::prelude::*;
use std::collections::{HashMap, HashSet};
verus! {
broadcast use {
crate::group_vstd_default,
crate::std_specs::hash::group_hash_axioms,
crate::std_specs::hash::lemma_hashmap_deepview_dom,
};
impl<
'a,
K: DeepView + DeepViewClone + std::hash::Hash + std::cmp::Eq,
V: DeepView + DeepViewClone,
> ToRef<&'a HashMap<K, V>> for &'a HashMap<K, V> {
#[inline(always)]
fn get_ref(self) -> &'a HashMap<K, V> {
&self
}
}
impl<
'a,
K: DeepView + DeepViewClone + std::hash::Hash + std::cmp::Eq,
V: DeepView + DeepViewClone,
> ToOwned<HashMap<K, V>> for &'a HashMap<K, V> {
#[verifier::external_body]
#[inline(always)]
fn get_owned(self) -> HashMap<K, V> {
let mut new_map = HashMap::new();
for (k, v) in self.iter() {
new_map.insert(k.deep_clone(), v.deep_clone());
}
new_map
}
}
impl<
K: DeepView + DeepViewClone + std::hash::Hash + std::cmp::Eq,
V: DeepView + DeepViewClone,
> DeepViewClone for HashMap<K, V> {
#[verifier::external_body]
#[inline(always)]
fn deep_clone(&self) -> Self {
let mut new_map = HashMap::new();
for (k, v) in self.iter() {
new_map.insert(k.deep_clone(), v.deep_clone());
}
new_map
}
}
impl<
'a,
K: DeepView + DeepViewClone + std::hash::Hash + std::cmp::Eq,
V: DeepView + DeepViewClone,
> ExecSpecEq<'a> for &'a HashMap<K, V> where
&'a K: ExecSpecEq<'a, Other = &'a K>,
&'a V: ExecSpecEq<'a, Other = &'a V>,
{
type Other = &'a HashMap<K, V>;
#[verifier::external_body]
#[inline(always)]
fn exec_eq(this: Self, other: Self::Other) -> bool {
if this.len() != other.len() {
return false;
}
for (k, v) in this.iter() {
match other.get(k) {
Some(ov) => {
if !<&'a V>::exec_eq(v, ov) {
return false;
}
},
None => return false,
}
}
true
}
}
impl<
'a,
K: DeepView + DeepViewClone + std::hash::Hash + std::cmp::Eq,
V: DeepView + DeepViewClone,
> ExecSpecLen for &'a HashMap<K, V> {
#[inline(always)]
#[verifier::external_body]
fn exec_len(self) -> (res: usize)
ensures
res == self.deep_view().len(),
{
self.len()
}
}
pub trait ExecSpecMapEmpty: Sized {
fn exec_empty() -> Self;
}
pub trait ExecSpecMapIndex<'a>: Sized + DeepView<
V = Map<<Self::Key as DeepView>::V, <Self::Value as DeepView>::V>,
> {
type Key: DeepView;
type Value: DeepView;
fn exec_index(self, key: Self::Key) -> Self::Value
requires
self.deep_view().dom().contains(key.deep_view()),
;
}
pub trait ExecSpecMapInsert<'a, Out: Sized + DeepView>: Sized + DeepView + ToOwned<Out> {
type Key: DeepView + DeepViewClone;
type Value: DeepView + DeepViewClone;
fn exec_insert(self, key: Self::Key, value: Self::Value) -> Out;
}
pub trait ExecSpecMapRemove<'a, Out: Sized + DeepView>: Sized + DeepView + ToOwned<Out> {
type Key: DeepView + DeepViewClone;
fn exec_remove(self, key: Self::Key) -> Out;
}
pub trait ExecSpecMapDom<'a>: Sized + DeepView {
type Key: DeepView + DeepViewClone;
fn exec_dom(self) -> HashSet<Self::Key>;
}
pub trait ExecSpecMapGet<'a>: Sized + DeepView {
type Key: DeepView + DeepViewClone;
type Value: DeepView + DeepViewClone;
fn exec_get(self, k: Self::Key) -> Option<Self::Value>;
}
impl<K: DeepView + std::hash::Hash + std::cmp::Eq, V: DeepView> ExecSpecMapEmpty for HashMap<K, V> {
#[inline(always)]
fn exec_empty() -> (res: Self)
ensures
res.deep_view() =~= Map::empty(),
{
HashMap::new()
}
}
impl<'a, K: DeepView + std::hash::Hash + std::cmp::Eq, V: DeepView> ExecSpecMapIndex<
'a,
> for &'a HashMap<K, V> {
type Key = K;
type Value = &'a V;
#[verifier::external_body]
#[inline(always)]
fn exec_index(self, index: Self::Key) -> (res: Self::Value)
ensures
res.deep_view() == self.deep_view()[index.deep_view()],
{
self.get(&index).unwrap()
}
}
impl<'a, K, V> ExecSpecMapInsert<'a, HashMap<K, V>> for &'a HashMap<K, V> where
K: DeepView + DeepViewClone + std::hash::Hash + std::cmp::Eq,
V: DeepView + DeepViewClone,
{
type Key = K;
type Value = V;
#[verifier::external_body]
#[inline(always)]
fn exec_insert(self, key: Self::Key, value: Self::Value) -> (res: HashMap<K, V>)
ensures
res.deep_view() =~= self.deep_view().insert(key.deep_view(), value.deep_view()),
{
let mut m = self.deep_clone();
let _ = m.insert(key.deep_clone(), value.deep_clone());
m
}
}
impl<'a, K, V> ExecSpecMapRemove<'a, HashMap<K, V>> for &'a HashMap<K, V> where
K: DeepView + DeepViewClone + std::hash::Hash + std::cmp::Eq,
V: DeepView + DeepViewClone,
{
type Key = K;
#[verifier::external_body]
#[inline(always)]
fn exec_remove(self, key: Self::Key) -> (res: HashMap<K, V>)
ensures
res.deep_view() =~= self.deep_view().remove(key.deep_view()),
{
let mut m = self.deep_clone();
let _ = m.remove(&key);
m
}
}
impl<'a, K, V> ExecSpecMapDom<'a> for &'a HashMap<K, V> where
K: DeepView + DeepViewClone + std::hash::Hash + std::cmp::Eq,
V: DeepView + DeepViewClone,
{
type Key = K;
#[verifier::external_body]
#[inline(always)]
fn exec_dom(self) -> (res: HashSet<K>)
ensures
res.deep_view() =~= self.deep_view().dom(),
{
let mut m = HashSet::new();
for key in self.keys() {
m.insert(key.deep_clone());
}
m
}
}
impl<'a, K, V> ExecSpecMapGet<'a> for &'a HashMap<K, V> where
K: DeepView + DeepViewClone + std::hash::Hash + std::cmp::Eq,
V: DeepView + DeepViewClone,
{
type Key = K;
type Value = V;
#[verifier::external_body]
#[inline(always)]
fn exec_get(self, k: Self::Key) -> (res: Option<Self::Value>)
ensures
match (res, self.deep_view().get(k.deep_view())) {
(Some(v1), Some(v2)) => v1.deep_view() == v2,
(None, None) => true,
(_, _) => false,
},
{
self.get(&k).map(|v| v.deep_clone())
}
}
}