cartel-sqlite 0.24.0

SQLite driver for the dope runtime
Documentation
use crate::limits;
use std::{cell, mem};

pub(crate) struct Meter {
    primary: cell::Cell<u64>,
    mode: cell::Cell<Mode>,
    permission: cell::Cell<Permission>,
}

#[derive(Clone, Copy)]
pub(super) enum Permission {
    Denied,
    Granted,
}

#[derive(Clone, Copy, Eq, PartialEq)]
#[repr(u8)]
enum Mode {
    Idle = 0,
    Primary = 2,
    Cleanup = 3,
}

pub(super) enum Tick {
    Continue,
    Stop,
}

pub(crate) enum Quota {
    Available,
    Exhausted,
}

impl Meter {
    pub(super) const fn new() -> Self {
        Self {
            primary: cell::Cell::new(0),
            mode: cell::Cell::new(Mode::Idle),
            permission: cell::Cell::new(Permission::Denied),
        }
    }

    pub(super) fn reset(&self) {
        self.mode.set(Mode::Idle);
        self.permission.set(Permission::Denied);
    }

    pub(super) fn begin_call(&self, primary: limits::Progress) -> Result<(), crate::Error> {
        self.begin(Mode::Primary, primary)
    }

    pub(super) fn cleanup(&self, quota: limits::Progress) -> Result<(), crate::Error> {
        match self.mode.get() {
            Mode::Cleanup => Ok(()),
            Mode::Idle => self.begin(Mode::Cleanup, quota),
            Mode::Primary => Err(crate::Error::ReentrantQuery),
        }
    }

    pub(super) fn tick(&self) -> Tick {
        match self.mode.get() {
            Mode::Idle => return Tick::Continue,
            Mode::Primary | Mode::Cleanup => {}
        }
        let left = self.primary.get();
        if left == 0 {
            return Tick::Stop;
        }
        let left = left - 1;
        self.primary.set(left);
        match left {
            0 => Tick::Stop,
            _ => Tick::Continue,
        }
    }

    pub(super) fn call_quota(&self) -> Quota {
        match self.primary.get() {
            0 => Quota::Exhausted,
            _ => Quota::Available,
        }
    }

    pub(super) fn finish(&self) {
        self.mode.set(Mode::Idle);
    }

    pub(crate) fn run<T>(
        &self,
        op: impl FnOnce() -> Result<T, crate::Error>,
    ) -> Result<T, crate::Error> {
        self.permission.set(Permission::Granted);
        let result = op();
        self.permission.set(Permission::Denied);
        result
    }

    pub(super) fn permission(&self) -> Permission {
        self.permission.get()
    }

    fn begin(&self, mode: Mode, primary: limits::Progress) -> Result<(), crate::Error> {
        if self.mode.get() != Mode::Idle {
            return Err(crate::Error::ReentrantQuery);
        }
        self.primary.set(primary.get());
        self.mode.set(mode);
        Ok(())
    }
}

const _: () = assert!(mem::size_of::<Meter>() <= 3 * mem::size_of::<u64>());