use hopper_runtime::error::ProgramError;
#[inline(always)]
pub fn check_invariant(condition: bool, invariant_code: u32) -> Result<(), ProgramError> {
if !condition {
return Err(ProgramError::Custom(invariant_code));
}
Ok(())
}
#[inline(always)]
pub fn check_invariant_fn<F: FnOnce() -> bool>(
f: F,
invariant_code: u32,
) -> Result<(), ProgramError> {
if !f() {
return Err(ProgramError::Custom(invariant_code));
}
Ok(())
}
pub struct InvariantSet {
first_failure: Option<u32>,
checked: u16,
passed: u16,
}
impl InvariantSet {
#[inline(always)]
pub const fn new() -> Self {
Self {
first_failure: None,
checked: 0,
passed: 0,
}
}
#[inline(always)]
pub fn check(&mut self, condition: bool, code: u32) {
self.checked += 1;
if condition {
self.passed += 1;
} else if self.first_failure.is_none() {
self.first_failure = Some(code);
}
}
#[inline(always)]
pub fn check_fn<F: FnOnce() -> bool>(&mut self, f: F, code: u32) {
self.check(f(), code);
}
#[inline(always)]
pub fn checked_count(&self) -> u16 {
self.checked
}
#[inline(always)]
pub fn passed_count(&self) -> u16 {
self.passed
}
#[inline(always)]
pub fn all_passed(&self) -> bool {
self.first_failure.is_none()
}
#[inline(always)]
pub fn finalize(self) -> Result<(), ProgramError> {
match self.first_failure {
None => Ok(()),
Some(code) => Err(ProgramError::Custom(code)),
}
}
}
impl Default for InvariantSet {
fn default() -> Self {
Self::new()
}
}
#[derive(Clone, Copy)]
pub struct InvariantDescriptor {
pub name: &'static str,
pub code: u32,
pub description: &'static str,
}