use serde::{Deserialize, Serialize};
use super::reflection::downcast_relationship;
use crate::proxy::ProxyResult;
use crate::proxy::ScalarValue;
#[derive(Debug, Clone)]
pub struct ScalarProxy {
pub relationship: String,
pub attribute: String,
}
impl ScalarProxy {
pub fn new(relationship: &str, attribute: &str) -> Self {
Self {
relationship: relationship.to_string(),
attribute: attribute.to_string(),
}
}
pub async fn get_value<T>(&self, source: &T) -> ProxyResult<Option<ScalarValue>>
where
T: super::reflection::Reflectable,
{
let relationship = match source.get_relationship(&self.relationship) {
Some(rel) => rel,
None => return Ok(None), };
let related =
downcast_relationship::<Box<dyn super::reflection::Reflectable>>(relationship)?;
let value = related.get_attribute(&self.attribute);
Ok(value)
}
pub async fn set_value<T>(&self, source: &mut T, value: ScalarValue) -> ProxyResult<()>
where
T: super::reflection::Reflectable,
{
source.set_relationship_attribute(&self.relationship, &self.attribute, value)?;
Ok(())
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ScalarComparison {
Eq(ScalarValue),
Ne(ScalarValue),
Gt(ScalarValue),
Gte(ScalarValue),
Lt(ScalarValue),
Lte(ScalarValue),
In(Vec<ScalarValue>),
NotIn(Vec<ScalarValue>),
IsNull,
IsNotNull,
Like(String),
NotLike(String),
}
impl ScalarComparison {
pub fn eq(value: impl Into<ScalarValue>) -> Self {
ScalarComparison::Eq(value.into())
}
pub fn ne(value: impl Into<ScalarValue>) -> Self {
ScalarComparison::Ne(value.into())
}
pub fn gt(value: impl Into<ScalarValue>) -> Self {
ScalarComparison::Gt(value.into())
}
pub fn gte(value: impl Into<ScalarValue>) -> Self {
ScalarComparison::Gte(value.into())
}
pub fn lt(value: impl Into<ScalarValue>) -> Self {
ScalarComparison::Lt(value.into())
}
pub fn lte(value: impl Into<ScalarValue>) -> Self {
ScalarComparison::Lte(value.into())
}
pub fn in_values(values: Vec<ScalarValue>) -> Self {
ScalarComparison::In(values)
}
pub fn not_in_values(values: Vec<ScalarValue>) -> Self {
ScalarComparison::NotIn(values)
}
pub fn is_null() -> Self {
ScalarComparison::IsNull
}
pub fn is_not_null() -> Self {
ScalarComparison::IsNotNull
}
pub fn like(pattern: &str) -> Self {
ScalarComparison::Like(pattern.to_string())
}
pub fn not_like(pattern: &str) -> Self {
ScalarComparison::NotLike(pattern.to_string())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_scalar_proxy_creation() {
let proxy = ScalarProxy::new("profile", "bio");
assert_eq!(proxy.relationship, "profile");
assert_eq!(proxy.attribute, "bio");
}
#[test]
fn test_proxy_scalar_comparison_unit() {
let eq = ScalarComparison::eq("test");
assert!(matches!(eq, ScalarComparison::Eq(_)));
let gt = ScalarComparison::gt(42);
assert!(matches!(gt, ScalarComparison::Gt(_)));
let is_null = ScalarComparison::is_null();
assert!(matches!(is_null, ScalarComparison::IsNull));
let like = ScalarComparison::like("%test%");
assert!(matches!(like, ScalarComparison::Like(_)));
}
}