use crate::proxy::AssociationProxy;
use std::marker::PhantomData;
pub type GetterFn<T, U> = fn(&T) -> Result<U, crate::proxy::ProxyError>;
pub type SetterFn<T, U> = fn(&mut T, U) -> Result<(), crate::proxy::ProxyError>;
pub type ValidatorFn<U> = fn(&U) -> Result<(), crate::proxy::ProxyError>;
pub struct ProxyBuilder<T, U> {
name: Option<String>,
relationship: Option<String>,
attribute: Option<String>,
creator: Option<fn(U) -> T>,
getter: Option<GetterFn<T, U>>,
setter: Option<SetterFn<T, U>>,
validator: Option<ValidatorFn<U>>,
transform: Option<fn(U) -> U>,
_phantom: PhantomData<(T, U)>,
}
impl<T, U> Default for ProxyBuilder<T, U> {
fn default() -> Self {
Self::new()
}
}
impl<T, U> ProxyBuilder<T, U> {
pub fn new() -> Self {
Self {
name: None,
relationship: None,
attribute: None,
creator: None,
getter: None,
setter: None,
validator: None,
transform: None,
_phantom: PhantomData,
}
}
pub fn with_name(name: &str) -> Self {
Self {
name: Some(name.to_string()),
relationship: None,
attribute: None,
creator: None,
getter: None,
setter: None,
validator: None,
transform: None,
_phantom: PhantomData,
}
}
pub fn relationship(mut self, name: &str) -> Self {
self.relationship = Some(name.to_string());
self
}
pub fn attribute(mut self, name: &str) -> Self {
self.attribute = Some(name.to_string());
self
}
pub fn creator(mut self, creator: fn(U) -> T) -> Self {
self.creator = Some(creator);
self
}
pub fn for_relationship(self, name: &str) -> Self {
self.relationship(name)
}
pub fn with_getter(mut self, getter: fn(&T) -> Result<U, crate::proxy::ProxyError>) -> Self {
self.getter = Some(getter);
self
}
pub fn with_setter(
mut self,
setter: fn(&mut T, U) -> Result<(), crate::proxy::ProxyError>,
) -> Self {
self.setter = Some(setter);
self
}
pub fn with_validator(
mut self,
validator: fn(&U) -> Result<(), crate::proxy::ProxyError>,
) -> Self {
self.validator = Some(validator);
self
}
pub fn with_transform(mut self, transform: fn(U) -> U) -> Self {
self.transform = Some(transform);
self
}
pub fn has_custom_accessors(&self) -> bool {
self.getter.is_some() || self.setter.is_some()
}
pub fn has_validator(&self) -> bool {
self.validator.is_some()
}
pub fn has_transform(&self) -> bool {
self.transform.is_some()
}
pub fn name(&self) -> Option<&str> {
self.name.as_deref()
}
pub fn get_relationship(&self) -> Option<&str> {
self.relationship.as_deref()
}
pub fn get_attribute(&self) -> Option<&str> {
self.attribute.as_deref()
}
pub fn build(self) -> AssociationProxy<T, U> {
let relationship = self.relationship.expect("Relationship must be set");
let attribute = self.attribute.expect("Attribute must be set");
let mut proxy = AssociationProxy::new(&relationship, &attribute);
if let Some(creator) = self.creator {
proxy = proxy.with_creator(creator);
}
proxy
}
pub fn try_build(self) -> Option<AssociationProxy<T, U>> {
let relationship = self.relationship?;
let attribute = self.attribute?;
let mut proxy = AssociationProxy::new(&relationship, &attribute);
if let Some(creator) = self.creator {
proxy = proxy.with_creator(creator);
}
Some(proxy)
}
}
pub fn association_proxy<T, U>(relationship: &str, attribute: &str) -> AssociationProxy<T, U> {
AssociationProxy::new(relationship, attribute)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_proxy_builder_basic_unit() {
let proxy: AssociationProxy<(), ()> = ProxyBuilder::new()
.relationship("rel")
.attribute("attr")
.build();
assert_eq!(proxy.relationship, "rel");
assert_eq!(proxy.attribute, "attr");
}
}