use vstd::prelude::*;
verus! {
pub open spec fn carries<T>(
complete: Seq<T>,
accumulated: Seq<T>,
pending: Seq<T>,
) -> bool {
complete == accumulated.add(pending)
}
pub proof fn mismatched_partition_rejected<T>(
complete: Seq<T>,
accumulated: Seq<T>,
pending: Seq<T>,
)
requires complete != accumulated.add(pending),
ensures !carries(complete, accumulated, pending),
{
}
pub open spec fn append<T>(before: Seq<T>, after: Seq<T>, value: T) -> bool {
after == before.push(value)
}
pub open spec fn stutter<T>(before: Seq<T>, after: Seq<T>) -> bool {
after == before
}
pub proof fn append_pending<T>(prefix: Seq<T>, pending: Seq<T>, value: T)
ensures
prefix.add(pending).push(value) == prefix.add(pending.push(value)),
{
Seq::push_distributes_over_add(prefix, pending, value);
}
pub proof fn consume_pending_head<T>(accumulated: Seq<T>, pending: Seq<T>)
requires pending.len() > 0,
ensures
accumulated.add(pending)
== accumulated.push(pending[0]).add(pending.skip(1)),
{
assert(pending =~= seq![pending[0]].add(pending.skip(1)));
assert(accumulated.push(pending[0]) =~= accumulated.add(seq![pending[0]]));
assert(accumulated.add(pending)
=~= accumulated.push(pending[0]).add(pending.skip(1)));
}
pub proof fn move_pending_head<T>(
prefix: Seq<T>,
destination: Seq<T>,
source: Seq<T>,
)
requires source.len() > 0,
ensures
prefix.add(destination).add(source)
== prefix.add(destination.push(source[0])).add(source.skip(1)),
{
assert(source =~= seq![source[0]].add(source.skip(1)));
assert(destination.push(source[0]) =~= destination.add(seq![source[0]]));
assert(prefix.add(destination).add(source)
=~= prefix.add(destination.push(source[0])).add(source.skip(1)));
}
pub proof fn move_pending_head_with_suffix<T>(
prefix: Seq<T>,
destination: Seq<T>,
source: Seq<T>,
suffix: Seq<T>,
)
requires source.len() > 0,
ensures
prefix.add(destination).add(source).add(suffix)
== prefix
.add(destination.push(source[0]))
.add(source.skip(1))
.add(suffix),
{
move_pending_head(prefix, destination, source);
}
pub proof fn consume_pending_head_with_suffix<T>(
accumulated: Seq<T>,
source: Seq<T>,
suffix: Seq<T>,
)
requires source.len() > 0,
ensures
accumulated.add(source.add(suffix))
== accumulated.push(source[0]).add(source.skip(1).add(suffix)),
{
consume_pending_head(accumulated, source);
assert(accumulated.add(source.add(suffix))
=~= accumulated.add(source).add(suffix));
assert(accumulated.push(source[0]).add(source.skip(1).add(suffix))
=~= accumulated.push(source[0]).add(source.skip(1)).add(suffix));
}
pub proof fn skip_pending_head_with_suffix<T>(source: Seq<T>, suffix: Seq<T>)
requires source.len() > 0,
ensures
source.add(suffix).skip(1) == source.skip(1).add(suffix),
{
assert(source.add(suffix).skip(1) =~= source.skip(1).add(suffix));
}
}