use core::fmt;
use crate::bytes::{
PayloadByteCount, ReturnOutputByteCount, RuntimeInputByteCount, RuntimeStateByteCount,
TraceSnapshotByteCount,
};
use crate::inspect::RuleCount;
const DEFAULT_BYTE_BUDGET: usize = 16_777_216;
pub const DEFAULT_MAX_SOURCE_LEN: SourceByteLimit = SourceByteLimit::new(DEFAULT_BYTE_BUDGET);
pub const DEFAULT_MAX_CODE_LINE_LEN: CodeLineByteLimit =
CodeLineByteLimit::new(DEFAULT_BYTE_BUDGET);
pub const DEFAULT_MAX_PAYLOAD_LEN: PayloadByteLimit = PayloadByteLimit::new(DEFAULT_BYTE_BUDGET);
pub const DEFAULT_MAX_RULES: RuleLimit = RuleLimit::new(1_000_000);
pub const DEFAULT_MAX_STEPS: StepLimit = StepLimit::new(1_000_000);
pub const DEFAULT_MAX_RULE_ATTEMPTS: RuleAttemptLimit = RuleAttemptLimit::new(1_000_000);
pub const DEFAULT_MAX_STATE_LEN: RuntimeStateByteLimit =
RuntimeStateByteLimit::new(DEFAULT_BYTE_BUDGET);
pub const DEFAULT_MAX_INPUT_LEN: RuntimeInputByteLimit =
RuntimeInputByteLimit::new(DEFAULT_BYTE_BUDGET);
pub const DEFAULT_MAX_RETURN_LEN: ReturnByteLimit = ReturnByteLimit::new(DEFAULT_BYTE_BUDGET);
pub const DEFAULT_MAX_TRACE_SNAPSHOT_LEN: TraceSnapshotByteLimit =
TraceSnapshotByteLimit::new(DEFAULT_BYTE_BUDGET);
pub const DEFAULT_PARSE_LIMITS: ParseLimits = ParseLimits::new(
DEFAULT_MAX_SOURCE_LEN,
DEFAULT_MAX_CODE_LINE_LEN,
DEFAULT_MAX_PAYLOAD_LEN,
DEFAULT_MAX_RULES,
);
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SourceByteCount {
value: usize,
}
impl SourceByteCount {
#[must_use]
pub(crate) const fn new(value: usize) -> Self {
Self { value }
}
#[must_use]
pub const fn get(self) -> usize {
self.value
}
}
impl fmt::Display for SourceByteCount {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.value.fmt(f)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CodeLineByteCount {
value: usize,
}
impl CodeLineByteCount {
#[must_use]
pub(crate) const fn new(value: usize) -> Self {
Self { value }
}
#[must_use]
pub const fn get(self) -> usize {
self.value
}
}
impl fmt::Display for CodeLineByteCount {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.value.fmt(f)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SourceByteLimit {
value: usize,
}
impl SourceByteLimit {
#[must_use]
pub const fn new(value: usize) -> Self {
Self { value }
}
#[must_use]
pub const fn get(self) -> usize {
self.value
}
pub(crate) const fn accepts(self, attempted_len: SourceByteCount) -> bool {
attempted_len.get() <= self.value
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CodeLineByteLimit {
value: usize,
}
impl CodeLineByteLimit {
#[must_use]
pub const fn new(value: usize) -> Self {
Self { value }
}
#[must_use]
pub const fn get(self) -> usize {
self.value
}
pub(crate) const fn accepts(self, attempted_len: CodeLineByteCount) -> bool {
attempted_len.get() <= self.value
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PayloadByteLimit {
value: usize,
}
impl PayloadByteLimit {
#[must_use]
pub const fn new(value: usize) -> Self {
Self { value }
}
#[must_use]
pub const fn get(self) -> usize {
self.value
}
pub(crate) const fn accepts(self, attempted_len: PayloadByteCount) -> bool {
attempted_len.get() <= self.value
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RuleLimit {
value: usize,
}
impl RuleLimit {
#[must_use]
pub const fn new(value: usize) -> Self {
Self { value }
}
#[must_use]
pub const fn get(self) -> usize {
self.value
}
pub(crate) const fn accepts(self, attempted_count: RuleCount) -> bool {
attempted_count.get() <= self.value
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ParseLimits {
source_len: SourceByteLimit,
code_line_len: CodeLineByteLimit,
payload_len: PayloadByteLimit,
rules: RuleLimit,
}
impl ParseLimits {
#[must_use]
pub const fn new(
max_source_len: SourceByteLimit,
max_code_line_len: CodeLineByteLimit,
max_payload_len: PayloadByteLimit,
max_rules: RuleLimit,
) -> Self {
Self {
source_len: max_source_len,
code_line_len: max_code_line_len,
payload_len: max_payload_len,
rules: max_rules,
}
}
#[must_use]
pub const fn source_byte_limit(self) -> SourceByteLimit {
self.source_len
}
#[must_use]
pub const fn code_line_byte_limit(self) -> CodeLineByteLimit {
self.code_line_len
}
#[must_use]
pub const fn payload_byte_limit(self) -> PayloadByteLimit {
self.payload_len
}
#[must_use]
pub const fn rule_limit(self) -> RuleLimit {
self.rules
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct StepLimit {
value: usize,
}
impl StepLimit {
#[must_use]
pub const fn new(value: usize) -> Self {
Self { value }
}
#[must_use]
pub const fn get(self) -> usize {
self.value
}
pub(crate) const fn allows_next_after(self, completed_steps: StepCount) -> bool {
completed_steps.get() < self.value
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RuleAttemptLimit {
value: usize,
}
impl RuleAttemptLimit {
#[must_use]
pub const fn new(value: usize) -> Self {
Self { value }
}
#[must_use]
pub const fn get(self) -> usize {
self.value
}
pub(crate) const fn allows_next_after(self, completed_attempts: RuleAttemptCount) -> bool {
completed_attempts.get() < self.value
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RuntimeStateByteLimit {
value: usize,
}
impl RuntimeStateByteLimit {
#[must_use]
pub const fn new(value: usize) -> Self {
Self { value }
}
#[must_use]
pub const fn get(self) -> usize {
self.value
}
pub(crate) const fn accepts(self, attempted_len: RuntimeStateByteCount) -> bool {
attempted_len.get() <= self.value
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RuntimeInputByteLimit {
value: usize,
}
impl RuntimeInputByteLimit {
#[must_use]
pub const fn new(value: usize) -> Self {
Self { value }
}
#[must_use]
pub const fn get(self) -> usize {
self.value
}
pub(crate) const fn accepts(self, attempted_len: RuntimeInputByteCount) -> bool {
attempted_len.get() <= self.value
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ReturnByteLimit {
value: usize,
}
impl ReturnByteLimit {
#[must_use]
pub const fn new(value: usize) -> Self {
Self { value }
}
#[must_use]
pub const fn get(self) -> usize {
self.value
}
pub(crate) const fn accepts(self, attempted_len: ReturnOutputByteCount) -> bool {
attempted_len.get() <= self.value
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TraceSnapshotByteLimit {
value: usize,
}
impl TraceSnapshotByteLimit {
#[must_use]
pub const fn new(value: usize) -> Self {
Self { value }
}
#[must_use]
pub const fn get(self) -> usize {
self.value
}
pub(crate) const fn accepts(self, attempted_len: TraceSnapshotByteCount) -> bool {
attempted_len.get() <= self.value
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct StepCount {
value: usize,
}
impl StepCount {
pub(crate) const ZERO: Self = Self { value: 0 };
#[must_use]
pub const fn get(self) -> usize {
self.value
}
pub(crate) fn checked_next(self) -> Option<Self> {
let value = self.value.checked_add(1)?;
Some(Self { value })
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RuleAttemptCount {
value: usize,
}
impl RuleAttemptCount {
pub(crate) const ZERO: Self = Self { value: 0 };
#[must_use]
pub const fn get(self) -> usize {
self.value
}
pub(crate) fn checked_next(self) -> Option<Self> {
let value = self.value.checked_add(1)?;
Some(Self { value })
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct RuntimeInputLimits {
input_len: RuntimeInputByteLimit,
}
impl RuntimeInputLimits {
#[must_use]
pub const fn new(max_input_len: RuntimeInputByteLimit) -> Self {
Self {
input_len: max_input_len,
}
}
#[must_use]
pub const fn input_byte_limit(self) -> RuntimeInputByteLimit {
self.input_len
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ExecutionLimits {
steps: StepLimit,
state_len: RuntimeStateByteLimit,
return_len: ReturnByteLimit,
}
impl ExecutionLimits {
#[must_use]
pub const fn new(
max_steps: StepLimit,
max_state_len: RuntimeStateByteLimit,
max_return_len: ReturnByteLimit,
) -> Self {
Self {
steps: max_steps,
state_len: max_state_len,
return_len: max_return_len,
}
}
#[must_use]
pub const fn step_limit(self) -> StepLimit {
self.steps
}
#[must_use]
pub const fn state_byte_limit(self) -> RuntimeStateByteLimit {
self.state_len
}
#[must_use]
pub const fn return_byte_limit(self) -> ReturnByteLimit {
self.return_len
}
}