use alloc::{collections::TryReserveError, vec::Vec};
use super::SecondaryIndex;
use crate::storage::warp_table::IndexKey;
use crate::storage::warp_table::dense_key_index::{DenseKeyIndex, DenseKeyIndexCreationError};
#[derive(Debug)]
pub enum SecondaryIndexCreationError {
SecondaryKeyStorageUnavailable { source: TryReserveError },
SlotSetStorageUnavailable { source: TryReserveError },
SecondaryKeyIndexCapacityOverflow { maximum_distinct_keys: usize },
SecondaryKeyIndexStorageUnavailable { source: TryReserveError },
}
impl<SecondaryKey: IndexKey> SecondaryIndex<SecondaryKey> {
pub fn try_new(maximum_distinct_keys: usize) -> Result<Self, SecondaryIndexCreationError> {
let mut secondary_keys = Vec::new();
secondary_keys
.try_reserve_exact(maximum_distinct_keys)
.map_err(
|source| SecondaryIndexCreationError::SecondaryKeyStorageUnavailable { source },
)?;
let mut slot_sets = Vec::new();
slot_sets
.try_reserve_exact(maximum_distinct_keys)
.map_err(|source| SecondaryIndexCreationError::SlotSetStorageUnavailable { source })?;
let secondary_key_index = DenseKeyIndex::try_new(maximum_distinct_keys)
.map_err(SecondaryIndexCreationError::from)?;
Ok(Self {
maximum_distinct_keys,
secondary_keys,
slot_sets,
secondary_key_index,
})
}
}
impl From<DenseKeyIndexCreationError> for SecondaryIndexCreationError {
fn from(reason: DenseKeyIndexCreationError) -> Self {
match reason {
DenseKeyIndexCreationError::CapacityOverflow { maximum_rows } => {
Self::SecondaryKeyIndexCapacityOverflow {
maximum_distinct_keys: maximum_rows,
}
}
DenseKeyIndexCreationError::StorageUnavailable { source } => {
Self::SecondaryKeyIndexStorageUnavailable { source }
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn secondary_creation_refusals_preserve_the_bound_or_allocator_cause()
-> Result<(), &'static str> {
use alloc::string::ToString;
let mapped =
SecondaryIndexCreationError::from(DenseKeyIndexCreationError::CapacityOverflow {
maximum_rows: 23,
});
assert!(matches!(
mapped,
SecondaryIndexCreationError::SecondaryKeyIndexCapacityOverflow {
maximum_distinct_keys: 23
}
));
let source = Vec::<u8>::new()
.try_reserve_exact(usize::MAX)
.err()
.ok_or("impossible allocation succeeded")?;
let message = source.to_string();
let mapped =
SecondaryIndexCreationError::from(DenseKeyIndexCreationError::StorageUnavailable {
source,
});
let SecondaryIndexCreationError::SecondaryKeyIndexStorageUnavailable { source } = mapped
else {
return Err("failure stage changed");
};
assert_eq!(source.to_string(), message);
Ok(())
}
}