Welcome to len_constraints
🎉
This crate implements traits and types that allows you to implement type-pinned length constraints in your API.
How often have you seen APIs like this? ```rust // BAD EXAMPLE!
fn encrypt(buf: &mut[u8], plaintext: &[u8], key: &[u8], nonce: &[u8])
-> Result
// Do sth.
unimplemented!()
} ``` As you can see, this API is pretty opaque and requires a lot of manual checks.
Of course s.o. could use array references: ```rust // MEH EXAMPLE...
fn encrypt(buf: &mut[u8], plaintext: &[u8], key: &[u8; 32], nonce: &[u8; 12])
-> Result
// Do sth.
unimplemented!()
}
``
But array references also have their disadvantages. They are not suitable for multiple valid lengths
(allow anything in
16..=32`) nor can they represent relative relationships. Also converting between
other data types and arrays can get annoying.
len_constraints
tries to solve this problem:
```rust
// GOOD EXAMPLE :D
use std::{ convert::TryInto, error::Error }; use lenconstraints::{ slicemut::RelativeMut, slice::{ Fixed, Ranged }, type_math::{ Add, _0, _12, _16, _32, _65536 } };
fn encrypt(buf: RelativeMut
// Do sth.
Ok(7)
}
fn main() -> Result<(), Box
// Call function
encrypt(buf.into(), plaintext.try_into()?, key.try_into()?, nonce.try_into()?)?;
Ok(())
} ``` As you can see, we now can describe complex relationships in the function signature – this makes the API more transparent and removes the need for manual (and error-prone) parameter validation. Also, the API is slice-friendly.