| Crates.io | vts |
| lib.rs | vts |
| version | 1.1.2 |
| created_at | 2023-02-01 13:16:02.290441+00 |
| updated_at | 2023-02-03 00:41:29.123606+00 |
| description | Macro to generate boiler plate to define new types with associated constraints |
| homepage | https://github.com/input-output-hk/ce-vts#README.md |
| repository | https://github.com/input-output-hk/ce-vts |
| max_upload_size | |
| id | 773668 |
| size | 14,866 |
This started as a simple thought about implementing a new type system where we can represent a type with its underlying specification.
type NewType = BaseType
where constraint;
The NewType is defined as a wrapper around BaseType with the constraint attached to it.
For example once could define the following:
vts::vts!{
/// String that have been already validated against the constraint that
/// all the characters of the string are valid hexadecimal digits
///
/// For example:
///
/// * `00`
/// * `a`
/// * `0123456789abcdef`
///
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub type HexaString = String
where self.chars().all(|c| c.is_ascii_hexdigit());
}
So here we say that the HexaString is a String where all the characters
comply with the given constraint : all chars are ASCII hexadecimal characters.
In the context of the Rust implementation, this is only a convenient way to wrap a base type and to add some constraint to the lifting. In essence the generated code will look like the following:
struct HexaString(String);
struct HexaStringConstraintError;
impl HexaString {
pub fn new(value: String) -> Result<Self, HexaStringConstraintError> {
let value = Self(value);
if value.__constraint() {
Ok(value)
} else {
Err(HexaStringConstraintError)
}
}
fn __constraint(&self) -> bool {
self.chars().all(|c| c.is_ascii_hexdigit())
}
}
impl std::ops::Deref for HexaString {
type Target = String;
fn deref(&self) -> &Self::Target {
&self.0
}
}