///|
/// Validates invariants before using state loaded from external storage.
pub fn validate_state(state : LeaseState) -> Array[StateIssue] {
let issues : Array[StateIssue] = []
if state.resource == "" {
issues.push({
code: "empty_resource",
message: "resource must not be empty",
})
}
if state.next_token <= 0 {
issues.push({
code: "invalid_next_token",
message: "next token must be positive",
})
}
if state.revision < 0 {
issues.push({
code: "invalid_revision",
message: "revision must not be negative",
})
}
match state.lease {
Some(lease) => {
if lease.resource != state.resource {
issues.push({
code: "resource_mismatch",
message: "nested lease resource differs from state resource",
})
}
if lease.holder == "" {
issues.push({
code: "empty_holder",
message: "lease holder must not be empty",
})
}
if lease.token <= 0 {
issues.push({
code: "invalid_token",
message: "lease token must be positive",
})
}
if lease.token >= state.next_token {
issues.push({
code: "token_cursor_regression",
message: "next token must be greater than issued token",
})
}
if lease.revision <= 0 || lease.revision > state.revision {
issues.push({
code: "lease_revision_mismatch",
message: "lease revision must be positive and not exceed state revision",
})
}
if lease.issued_at < 0 || lease.expires_at <= lease.issued_at {
issues.push({
code: "invalid_interval",
message: "lease interval must be positive and non-negative",
})
}
}
None => ()
}
issues
}
///|
/// Returns whether restored state is safe to apply.
pub fn state_is_valid(state : LeaseState) -> Bool {
validate_state(state).length() == 0
}