use super::error::ZerokitMerkleTreeError;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OverrideRangeValidation {
pub indices: Vec<usize>,
pub max_index: Option<usize>,
pub min_index: Option<usize>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EmptyIndicesPolicy {
Allow,
Reject,
}
pub fn validate_override_range_inputs(
start: usize,
leaves_len: usize,
mut indices: Vec<usize>,
capacity: usize,
empty_indices_policy: EmptyIndicesPolicy,
) -> Result<OverrideRangeValidation, ZerokitMerkleTreeError> {
if matches!(empty_indices_policy, EmptyIndicesPolicy::Reject) && indices.is_empty() {
return Err(ZerokitMerkleTreeError::InvalidIndices);
}
if indices.iter().any(|&i| i >= capacity) {
return Err(ZerokitMerkleTreeError::InvalidIndices);
}
indices.sort_unstable();
indices.dedup();
let min_index = indices.first().copied();
let max_index = if leaves_len == 0 {
None
} else {
let end = start
.checked_add(leaves_len)
.ok_or(ZerokitMerkleTreeError::TooManySet)?;
if end > capacity {
return Err(ZerokitMerkleTreeError::TooManySet);
}
Some(end)
};
if let (Some(min_idx), Some(end)) = (min_index, max_index) {
if min_idx > start || min_idx >= end {
return Err(ZerokitMerkleTreeError::InvalidIndices);
}
}
Ok(OverrideRangeValidation {
indices,
max_index,
min_index,
})
}
#[cfg(test)]
mod tests {
use super::{validate_override_range_inputs, EmptyIndicesPolicy};
use crate::merkle_tree::ZerokitMerkleTreeError;
#[test]
fn test_validate_override_range_inputs_accepts_valid_inputs() {
let validated = validate_override_range_inputs(
2,
3,
vec![1, 0],
1usize << 20,
EmptyIndicesPolicy::Allow,
)
.unwrap();
assert_eq!(validated.min_index, Some(0));
assert_eq!(validated.max_index, Some(5)); assert_eq!(validated.indices, vec![0, 1]); }
#[test]
fn test_validate_override_range_inputs_rejects_start_add_overflow() {
let err = validate_override_range_inputs(
usize::MAX,
1,
vec![0],
1usize << 20,
EmptyIndicesPolicy::Allow,
)
.unwrap_err();
assert!(matches!(err, ZerokitMerkleTreeError::TooManySet));
}
#[test]
fn test_validate_override_range_inputs_rejects_incompatible_mixed_offsets() {
let err =
validate_override_range_inputs(0, 2, vec![1], 1usize << 20, EmptyIndicesPolicy::Allow)
.unwrap_err();
assert!(matches!(err, ZerokitMerkleTreeError::InvalidIndices));
}
#[test]
fn test_validate_override_range_inputs_rejects_empty_indices_when_required() {
let err =
validate_override_range_inputs(0, 1, vec![], 1usize << 20, EmptyIndicesPolicy::Reject)
.unwrap_err();
assert!(matches!(err, ZerokitMerkleTreeError::InvalidIndices));
}
}