use super::*;
impl RoleParam {
pub fn validate(&self) -> RoleValidationResult<()> {
match self {
RoleParam::Static(count) => {
if *count > MAX_ROLE_COUNT {
return Err(RoleValidationError::CountOverflow {
count: *count,
max: MAX_ROLE_COUNT,
});
}
Ok(())
}
RoleParam::Symbolic(_) => Ok(()),
RoleParam::Runtime => Ok(()),
}
}
pub fn validate_with_index(&self, index: &RoleIndex) -> RoleValidationResult<()> {
match (self, index) {
(RoleParam::Static(count), RoleIndex::Concrete(idx)) => {
if *idx >= *count {
return Err(RoleValidationError::IndexOverflow {
index: *idx,
max: *count - 1,
});
}
Ok(())
}
(RoleParam::Static(count), RoleIndex::Range(range)) => {
if let (RangeExpr::Concrete(_), RangeExpr::Concrete(end)) =
(&range.start, &range.end)
{
if *end > *count {
return Err(RoleValidationError::IndexOverflow {
index: *end,
max: *count,
});
}
}
Ok(())
}
_ => Ok(()),
}
}
pub fn safe_static(count: u32) -> RoleValidationResult<Self> {
if count > MAX_ROLE_COUNT {
return Err(RoleValidationError::CountOverflow {
count,
max: MAX_ROLE_COUNT,
});
}
Ok(RoleParam::Static(count))
}
}
impl RoleIndex {
pub fn validate(&self) -> RoleValidationResult<()> {
match self {
RoleIndex::Concrete(index) => {
if *index > MAX_ROLE_INDEX {
return Err(RoleValidationError::IndexOverflow {
index: *index,
max: MAX_ROLE_INDEX,
});
}
Ok(())
}
RoleIndex::Symbolic(_) | RoleIndex::Wildcard => Ok(()),
RoleIndex::Range(range) => range.validate(),
}
}
pub fn safe_concrete(index: u32) -> RoleValidationResult<Self> {
if index > MAX_ROLE_INDEX {
return Err(RoleValidationError::IndexOverflow {
index,
max: MAX_ROLE_INDEX,
});
}
Ok(RoleIndex::Concrete(index))
}
}
impl RoleRange {
pub fn validate(&self) -> RoleValidationResult<()> {
self.start.validate()?;
self.end.validate()?;
if let (RangeExpr::Concrete(start), RangeExpr::Concrete(end)) = (&self.start, &self.end) {
if start >= end {
return Err(RoleValidationError::InvalidRange {
start: *start,
end: *end,
});
}
let range_size = end - start;
if range_size > MAX_RANGE_COUNT {
return Err(RoleValidationError::RangeSizeOverflow {
size: range_size,
max: MAX_RANGE_COUNT,
});
}
}
Ok(())
}
pub fn safe_concrete(start: u32, end: u32) -> RoleValidationResult<Self> {
let range = RoleRange {
start: RangeExpr::Concrete(start),
end: RangeExpr::Concrete(end),
};
range.validate()?;
Ok(range)
}
}
impl RangeExpr {
pub fn validate(&self) -> RoleValidationResult<()> {
match self {
RangeExpr::Concrete(value) => {
if *value > MAX_ROLE_INDEX {
return Err(RoleValidationError::IndexOverflow {
index: *value,
max: MAX_ROLE_INDEX,
});
}
Ok(())
}
RangeExpr::Symbolic(_) => Ok(()),
}
}
}
pub struct RoleBoundsChecker {
max_count: u32,
max_index: u32,
}
impl Default for RoleBoundsChecker {
fn default() -> Self {
Self {
max_count: MAX_ROLE_COUNT,
max_index: MAX_ROLE_INDEX,
}
}
}
impl RoleBoundsChecker {
pub fn new(max_count: u32, max_index: u32) -> Self {
Self {
max_count,
max_index,
}
}
pub fn check_count(&self, count: u32) -> RoleValidationResult<()> {
if count > self.max_count {
return Err(RoleValidationError::CountOverflow {
count,
max: self.max_count,
});
}
Ok(())
}
pub fn check_index(&self, index: u32) -> RoleValidationResult<()> {
if index > self.max_index {
return Err(RoleValidationError::IndexOverflow {
index,
max: self.max_index,
});
}
Ok(())
}
pub fn check_range(&self, start: u32, end: u32) -> RoleValidationResult<()> {
if start >= end {
return Err(RoleValidationError::InvalidRange { start, end });
}
if end > self.max_index {
return Err(RoleValidationError::IndexOverflow {
index: end,
max: self.max_index,
});
}
let range_size = end - start;
if range_size > MAX_RANGE_COUNT {
return Err(RoleValidationError::RangeSizeOverflow {
size: range_size,
max: MAX_RANGE_COUNT,
});
}
Ok(())
}
}
impl std::fmt::Display for RoleIndex {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
RoleIndex::Concrete(index) => write!(f, "{}", index),
RoleIndex::Symbolic(name) => write!(f, "{}", name),
RoleIndex::Wildcard => write!(f, "*"),
RoleIndex::Range(range) => write!(f, "{}", range),
}
}
}
impl std::fmt::Display for RoleRange {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}..{}", self.start, self.end)
}
}
impl std::fmt::Display for RangeExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
RangeExpr::Concrete(value) => write!(f, "{}", value),
RangeExpr::Symbolic(name) => write!(f, "{}", name),
}
}
}
impl std::fmt::Display for RoleParam {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
RoleParam::Static(count) => write!(f, "{}", count),
RoleParam::Symbolic(name) => write!(f, "{}", name),
RoleParam::Runtime => write!(f, "*"),
}
}
}