use std::fmt;
use ref_view::RefView;
#[derive(RefView)]
#[ref_view(name = PersonWithoutEmail, omit(email))]
struct Person {
id: u64,
name: String,
email: Option<String>,
age: u8,
}
#[test]
fn struct_views_reuse_accessors() {
let person = Person {
id: 7,
name: "Ada".to_string(),
email: Some("ada@example.com".to_string()),
age: 42,
};
assert_eq!(*person.id(), 7);
assert_eq!(person.name(), "Ada");
assert_eq!(person.email().map(String::as_str), Some("ada@example.com"));
assert_eq!(*person.age(), 42);
let full = PersonRef::from(&person);
assert_eq!(*full.id(), 7);
assert_eq!(full.name(), "Ada");
assert_eq!(full.email().map(String::as_str), Some("ada@example.com"));
assert_eq!(*full.age(), 42);
let without_email = PersonWithoutEmail::from(&person);
assert_eq!(*without_email.id(), 7);
assert_eq!(without_email.name(), "Ada");
assert_eq!(without_email.email(), None);
assert_eq!(*without_email.age(), 42);
}
#[derive(RefView)]
#[ref_view(name = NodeWithoutPivot, omit(Table.pivot, Subquery.pivot))]
enum Node {
Table {
name: String,
pivot: Option<String>,
sample: u8,
},
Subquery {
query: String,
pivot: Option<String>,
},
Other {
note: String,
},
}
#[test]
fn enum_views_can_omit_variant_fields() {
let table = Node::Table {
name: "sales".to_string(),
pivot: Some("quarter".to_string()),
sample: 3,
};
let full = NodeRef::from(&table);
let without_pivot = NodeWithoutPivot::from(&table);
assert_eq!(table.name().map(String::as_str), Some("sales"));
assert_eq!(table.pivot().map(String::as_str), Some("quarter"));
assert_eq!(table.sample(), Some(&3));
assert_eq!(table.query(), None);
assert_eq!(full.name().map(String::as_str), Some("sales"));
assert_eq!(full.pivot().map(String::as_str), Some("quarter"));
assert_eq!(full.sample(), Some(&3));
assert_eq!(without_pivot.name().map(String::as_str), Some("sales"));
assert_eq!(without_pivot.pivot(), None);
assert_eq!(without_pivot.sample(), Some(&3));
let subquery = Node::Subquery {
query: "select * from t".to_string(),
pivot: Some("month".to_string()),
};
let without_pivot = NodeWithoutPivot::from(&subquery);
assert_eq!(
without_pivot.query().map(String::as_str),
Some("select * from t")
);
assert_eq!(without_pivot.pivot(), None);
assert_eq!(without_pivot.name(), None);
let other = Node::Other {
note: "plain".to_string(),
};
assert_eq!(
NodeRef::from(&other).note().map(String::as_str),
Some("plain")
);
assert_eq!(NodeRef::from(&other).pivot(), None);
}
#[derive(RefView)]
#[ref_view(trait_name = ThingLike)]
#[ref_view(name = ThingWithoutB, omit(b))]
struct Thing {
a: i32,
b: i32,
}
fn read_thing<T: ThingLike>(thing: &T) -> (i32, Option<i32>) {
(*thing.a(), thing.b().copied())
}
#[test]
fn trait_name_can_be_customized() {
let thing = Thing { a: 1, b: 2 };
assert_eq!(read_thing(&thing), (1, Some(2)));
assert_eq!(read_thing(&ThingRef::from(&thing)), (1, Some(2)));
assert_eq!(read_thing(&ThingWithoutB::from(&thing)), (1, None));
}
#[derive(Debug, PartialEq, Eq)]
enum AccountStatus {
Active,
}
#[derive(Debug, PartialEq, Eq, RefView)]
#[ref_view(derive(Debug, PartialEq, Eq))]
#[ref_view(name = PublicAccount, omit(secret))]
struct Account {
id: u64,
status: AccountStatus,
secret: String,
}
#[ref_view::impl_fn(AccountView)]
fn account_secret_state(account: &Account) -> &'static str {
if account.secret().is_some() {
"secret=present"
} else {
"secret=hidden"
}
}
#[ref_view::impl_trait(AccountView => AccountRef<'_>, PublicAccount<'_>)]
impl fmt::Display for Account {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let secret = account_secret_state(self);
write!(f, "{} {:?} {}", self.id(), self.status(), secret)
}
}
#[test]
fn generated_views_can_derive_requested_traits() {
let account = Account {
id: 9,
status: AccountStatus::Active,
secret: "token".to_string(),
};
let full = AccountRef::from(&account);
let public = PublicAccount::from(&account);
assert_eq!(full, AccountRef::from(&account));
assert_eq!(public, PublicAccount::from(&account));
assert_eq!(
format!("{:?}", full),
r#"AccountRef { id: 9, status: Active, secret: "token" }"#
);
assert_eq!(
format!("{:?}", public),
"PublicAccount { id: 9, status: Active }"
);
assert_eq!(format!("{}", account), "9 Active secret=present");
assert_eq!(format!("{}", full), "9 Active secret=present");
assert_eq!(format!("{}", public), "9 Active secret=hidden");
}