pub struct Validated<T>(T);
impl<T> Validated<T> {
pub(crate) fn new(value: T) -> Self {
Self(value)
}
pub fn unbrand(self) -> T {
self.0
}
pub fn inner(&self) -> &T {
&self.0
}
}
pub struct Untrusted<T>(T);
impl<T> Untrusted<T> {
pub fn new(value: T) -> Self {
Self(value)
}
pub fn validate<F: FnOnce(&T) -> bool>(self, predicate: F) -> Option<Validated<T>> {
if predicate(&self.0) {
Some(Validated::new(self.0))
} else {
None
}
}
pub fn try_validate<E, F: FnOnce(&T) -> Result<(), E>>(
self,
validator: F,
) -> Result<Validated<T>, E> {
validator(&self.0)?;
Ok(Validated::new(self.0))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_validated_unbrand() {
let validated = Validated::new(42);
assert_eq!(validated.unbrand(), 42);
}
#[test]
fn test_untrusted_validate() {
let untrusted = Untrusted::new("hello");
let validated = untrusted.validate(|s| !s.is_empty());
assert!(validated.is_some());
}
#[test]
fn test_untrusted_validate_fails() {
let untrusted = Untrusted::new("");
let validated = untrusted.validate(|s| !s.is_empty());
assert!(validated.is_none());
}
}