extern crate attr; use attr::*; struct User { data: Data, } struct DataAttribute; impl<'a> Attr<&'a User> for DataAttribute { type Output = &'a Data; fn name(&self) -> &'static str { "data" } fn get(&self, u: &'a User) -> &'a Data { &u.data } } struct Data { email: String } struct EmailAttribute; impl<'a> Attr<&'a Data> for EmailAttribute { type Output = &'a str; fn name(&self) -> &'static str { "email" } fn get(&self, d: &'a Data) -> &'a str { &d.email } } struct PrefixValidator
{ pattern: String, path: P } impl
PrefixValidator
{ fn validate<'a, 'b: 'a, T: 'b>(&'a self, t: T) -> std::result::Result<(), String> where P: Traverse<'a, 'b, T, &'b str> { match self.path.traverse(t) { Ok(s) => { if s.starts_with(&self.pattern) { Ok(()) } else { Err(format!("Does not start with {}", self.pattern)) } } Err(reason) => Err(reason) } } } fn main() { let user = User { data: Data { email: "flo@andersground.net".into() }}; assert!(validate(&user).is_ok()); } fn validate(u: &User) -> std::result::Result<(), String> { let path = retrieve(EmailAttribute).from(DataAttribute); let validator = PrefixValidator { pattern: "flo".into(), path: path }; validator.validate(u) }