A lightweight crate for defining and validating capacity constraints.
This crate is no_std compatible and contains no unsafe code.
Capacity: Validates iterator compatibility against a capacity constraint.StaticCap: Declares a compile-time capacity constraint.VariableCap: Declares a runtime capacity constraint.
Implementations are provided for Array by default. See the features section for more conditional enabled implementations.
Types that have a compile-time capacity constraint (like arrays) can implement StaticCap. And select a static Capacity implementation to use. This is most useful for pre-validating collection type operations.
use collection_cap::StaticCap;
use collection_cap::cap::StaticMaxCap;
struct MyStaticCollection;
impl StaticCap for MyStaticCollection {
type Cap = StaticMaxCap<10>;
const CAP: Self::Cap = StaticMaxCap::<10>;
}Types that have a capacity constraint that can change or is determined at runtime (like ArrayVec) can implement VariableCap. And return a Capacity implementation that reflects the current capacity constraint. This is most useful for pre-validating extension operations.
use collection_cap::VariableCap;
use collection_cap::cap::MaxCapVal;
struct MyDynamicCollection { remaining: usize }
impl VariableCap for MyDynamicCollection {
type Cap = MaxCapVal;
fn capacity(&self) -> Self::Cap { MaxCapVal(self.remaining) }
}While the Capacity trait can be used directly, it is most useful when combined with the IterCapExt extension trait. This trait provides a number of methods for checking iterator compatibility and fit.
use collection_cap::IterCapExt;
use arrayvec::ArrayVec;
(0..10).ensure_compatible::<[i32; 10]>().expect("Exact match");
(0..11).ensure_compatible::<ArrayVec<i32, 10>>().expect_err("Overflow");
let mut vec: ArrayVec<i32, 10> = (0..5).collect();
(0..3).ensure_compatible_with(&vec).expect("Fits remaining");
(0..6).ensure_compatible_with(&vec).expect_err("Too many");The following Capacity implementations are provided.
| Represents | Variable | Static | Range equivalent |
|---|---|---|---|
| Minimum | MinCapVal |
StaticMinCap |
min.. |
| Maximum | MaxCapVal |
StaticMaxCap |
..=max |
| Min & Max | MinMaxCapVal |
StaticMinMaxCap |
min..=max |
| Exact | ExactCapVal |
StaticExactCap |
size..=size |
| Unbounded | UnboundedCap |
UnboundedCap |
.. |
These types can be used either directly, or as a return type parameter for StaticCap or VariableCap. VariableCap is also implemented for std range types, as indicated.
use collection_cap::IterCapExt;
use collection_cap::cap::StaticExactCap;
(0..5).ensure_compatible_with(..=5).expect("should be compatible");
(0..6).ensure_compatible_with(..=5).expect_err("should not be compatible");
(0..5).ensure_compatible::<StaticExactCap<5>>().expect("should be compatible");
(0..6).ensure_compatible::<StaticExactCap<5>>().expect_err("should not be compatible");Note that for non-ExactSizeIterator, these checks only guarantee that an iterator's size_hint is compatible with the given capacity. They do not guarantee that an iterator will actually fit the capacity during iteration, as the size_hint only reports the minimum and maximum number of elements an iterator might produce. An error is only returned if the iterator's size_hint indicates that it cannot fit the capacity constraint.
For a stronger guarantee, IterCapExt::ensure_fit and IterCapExt::ensure_fits_into can be used. These methods check if the entire range reported by an iterator's size_hint fits within the capacity constraints. If any possible count of elements could violate the constraint, these methods will return an error.
Put another way, ensure_compatible has the possibility of a false positive, while ensure_fit has the possibility of a false negative.
use collection_cap::IterCapExt;
let max_5_elements = ..=4;
let produces_10 = (0..10).filter(|_| true);
assert_eq!(produces_10.size_hint(), (0, Some(10)), "Can produce 0 to 10 elements");
produces_10.ensure_compatible_with(max_5_elements)
.expect("Compatibility only requires that it MIGHT fit");
let produces_3 = (0..10).filter(|x| *x < 3);
assert_eq!(produces_3.size_hint(), (0, Some(10)), "Can produce 0 to 10 elements");
produces_3.ensure_fits_into(max_5_elements)
.expect_err("Fit requires that it MUST fit");See the Capacity#note-on-fit documentation for more details.
It's on crates.io: collection_cap
arrayvec: ImplementsStaticCapandVariableCapforArrayVec.alloc: Adds theSpareCapacityExtextension trait forVec,String, andVecDequeto allow querying their remaining capacity as aMaxCapVal.