1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
use async_trait::async_trait;
use crate::attribute::{
    AsyncAttribute,
    SyncAttribute
};
use crate::chain::{ConstraintChain, ConstraintEntity, EntityTag, ConstraintT};
use crate::has::HasEntityWithType;


impl<T, C> AcquireAttributeWithResourceAndContext<C> for T
    where
        T: ConstraintT + Sized,
        C: Send {}

#[async_trait]
pub trait AcquireAttributeWithResourceAndContext<C: Send>: Sized + ConstraintT {
    async fn prove_with_resource_and_context_async<
        'ctx,
        Attr,
        const STAG: EntityTag,
        const RTAG: EntityTag,
    >(self, context: C) -> Result<ConstraintChain<STAG, RTAG, Attr, Self>, Attr::Error>
        where
            Attr::Subject: ConstraintEntity + 'static,
            Attr::Resource: ConstraintEntity + 'static,
            C: 'async_trait,
            Self: HasEntityWithType<STAG, Attr::Subject>,
            Self: HasEntityWithType<RTAG, Attr::Resource>,
            Attr: AsyncAttribute<Context<'ctx> = C>,
    {
        let subject = self.get_entity::<_, STAG>();
        let resource = self.get_entity::<_, RTAG>();

        Attr::test_async(subject, resource, context).await?;

        Ok(ConstraintChain::<_, _, _, _>::new(self))
    }

    fn prove_with_resource_and_context<
        'ctx,
        Attr,
        const STAG: EntityTag,
        const RTAG: EntityTag
    >(self, context: C) -> Result<ConstraintChain<STAG, RTAG, Attr, Self>, Attr::Error>
        where
            Attr::Subject: ConstraintEntity + 'static,
            Attr::Resource: ConstraintEntity + 'static,
            Self: HasEntityWithType<STAG, Attr::Subject>,
            Self: HasEntityWithType<RTAG, Attr::Resource>,
            Attr: SyncAttribute<Context<'ctx> = C>,
    {
        let subject = self.get_entity::<_, STAG>();
        let resource = self.get_entity::<_, RTAG>();

        Attr::test(subject, resource, context)?;

        Ok(ConstraintChain::<_, _, _, _>::new(self))
    }
}