use vstd::prelude::*;
verus! {
pub assume_specification<T, const N: usize>[ <[T]>::first_chunk::<N> ](slice: &[T]) -> (chunk:
Option<&[T; N]>)
ensures
chunk.is_some() <==> slice@.len() >= N,
chunk.is_some() ==> chunk.unwrap()@ == slice@.subrange(0, N as int),
;
pub assume_specification<T, const N: usize>[ <[T]>::last_chunk::<N> ](slice: &[T]) -> (chunk:
Option<&[T; N]>)
ensures
chunk.is_some() <==> slice@.len() >= N,
chunk.is_some() ==> chunk.unwrap()@ == slice@.subrange(
slice@.len() - N,
slice@.len() as int,
),
;
pub assume_specification[ u64::checked_shl ](word: u64, shift: u32) -> (shifted: Option<u64>)
ensures
shifted.is_some() <==> shift < 64,
shifted.is_some() ==> shifted.unwrap() == word << shift,
;
pub(super) struct BigEndian;
impl BigEndian {
#[verusfmt::skip]
pub(super) open spec fn spec_u64(bytes: Seq<u8>) -> u64 {
(bytes[0] as u64) << 56 | (bytes[1] as u64) << 48 | (bytes[2] as u64) << 40
| (bytes[3] as u64) << 32 | (bytes[4] as u64) << 24 | (bytes[5] as u64) << 16
| (bytes[6] as u64) << 8 | bytes[7] as u64
}
pub(super) open spec fn spec_u32(bytes: Seq<u8>) -> u32 {
(bytes[0] as u32) << 24 | (bytes[1] as u32) << 16 | (bytes[2] as u32) << 8 | bytes[3] as u32
}
pub(super) open spec fn spec_u16(bytes: Seq<u8>) -> u16 {
(bytes[0] as u16) << 8 | bytes[1] as u16
}
#[verifier::external_body]
#[inline(always)]
pub(super) fn u64_of(bytes: [u8; 8]) -> (word: u64)
ensures
word == Self::spec_u64(bytes@),
{
u64::from_be_bytes(bytes)
}
#[verifier::external_body]
#[inline(always)]
pub(super) fn u32_of(bytes: [u8; 4]) -> (word: u32)
ensures
word == Self::spec_u32(bytes@),
{
u32::from_be_bytes(bytes)
}
#[verifier::external_body]
#[inline(always)]
pub(super) fn u16_of(bytes: [u8; 2]) -> (word: u16)
ensures
word == Self::spec_u16(bytes@),
{
u16::from_be_bytes(bytes)
}
}
}