//! Field guards use crate::{Context, Result}; /// Field guard /// /// Guard is a pre-condition for a field that is resolved if `Ok(())` is returned, otherwise an error is returned. /// /// This trait is defined through the [`async-trait`](https://crates.io/crates/async-trait) macro. #[async_trait::async_trait] pub trait Guard { /// Check whether the guard will allow access to the field. async fn check(&self, ctx: &Context<'_>) -> Result<()>; } /// An extension trait for `Guard`. pub trait GuardExt: Guard + Sized { /// Perform `and` operator on two rules fn and(self, other: R) -> And { And(self, other) } /// Perform `or` operator on two rules fn or(self, other: R) -> Or { Or(self, other) } } impl GuardExt for T {} /// Guard for [`GuardExt::and`](trait.GuardExt.html#method.and). pub struct And(A, B); #[async_trait::async_trait] impl Guard for And { async fn check(&self, ctx: &Context<'_>) -> Result<()> { self.0.check(ctx).await?; self.1.check(ctx).await } } /// Guard for [`GuardExt::or`](trait.GuardExt.html#method.or). pub struct Or(A, B); #[async_trait::async_trait] impl Guard for Or { async fn check(&self, ctx: &Context<'_>) -> Result<()> { let second_result = self.1.check(ctx).await; self.0.check(ctx).await.or(second_result) } }