1use gatekeep::{Fact, FactId, GatekeepError, SubjectSlot};
2use keepsake::{RelationId, RelationSpec};
3use thiserror::Error;
4
5#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
7pub enum QueryPresence {
8 #[default]
10 Resolve,
11 Defer,
13}
14
15#[derive(Clone, Debug, PartialEq, Eq)]
17pub struct FactBinding {
18 pub(crate) fact: FactId,
19 pub(crate) relation_id: RelationId,
20 pub(crate) subject_slot: Option<SubjectSlot>,
21 pub(crate) query_presence: QueryPresence,
22}
23
24impl FactBinding {
25 #[must_use]
27 pub const fn new(fact: FactId, relation_id: RelationId) -> Self {
28 Self::with_subject_and_query_presence(fact, relation_id, None, QueryPresence::Resolve)
29 }
30
31 #[must_use]
33 pub const fn with_query_presence(
34 fact: FactId,
35 relation_id: RelationId,
36 query_presence: QueryPresence,
37 ) -> Self {
38 Self::with_subject_and_query_presence(fact, relation_id, None, query_presence)
39 }
40
41 #[must_use]
43 pub const fn on_subject(
44 fact: FactId,
45 relation_id: RelationId,
46 subject_slot: SubjectSlot,
47 ) -> Self {
48 Self::with_subject_and_query_presence(
49 fact,
50 relation_id,
51 Some(subject_slot),
52 QueryPresence::Resolve,
53 )
54 }
55
56 #[must_use]
59 pub const fn with_subject_and_query_presence(
60 fact: FactId,
61 relation_id: RelationId,
62 subject_slot: Option<SubjectSlot>,
63 query_presence: QueryPresence,
64 ) -> Self {
65 Self {
66 fact,
67 relation_id,
68 subject_slot,
69 query_presence,
70 }
71 }
72
73 pub fn for_relation_spec<F, R>() -> Result<Self, FactBindingError>
80 where
81 F: Fact,
82 R: RelationSpec,
83 {
84 Self::for_relation_spec_with_query_presence::<F, R>(QueryPresence::Resolve)
85 }
86
87 pub fn for_relation_spec_on_subject<F, R>(
95 subject_slot: SubjectSlot,
96 ) -> Result<Self, FactBindingError>
97 where
98 F: Fact,
99 R: RelationSpec,
100 {
101 Self::for_relation_spec_on_subject_with_query_presence::<F, R>(
102 subject_slot,
103 QueryPresence::Resolve,
104 )
105 }
106
107 pub fn resolve_relation<F, R>() -> Result<Self, FactBindingError>
115 where
116 F: Fact,
117 R: RelationSpec,
118 {
119 Self::for_relation_spec_with_query_presence::<F, R>(QueryPresence::Resolve)
120 }
121
122 pub fn defer_relation<F, R>() -> Result<Self, FactBindingError>
130 where
131 F: Fact,
132 R: RelationSpec,
133 {
134 Self::for_relation_spec_with_query_presence::<F, R>(QueryPresence::Defer)
135 }
136
137 pub fn for_relation_spec_with_query_presence<F, R>(
145 query_presence: QueryPresence,
146 ) -> Result<Self, FactBindingError>
147 where
148 F: Fact,
149 R: RelationSpec,
150 {
151 Ok(Self::with_query_presence(
152 F::ID.to_owned_id()?,
153 R::ID,
154 query_presence,
155 ))
156 }
157
158 pub fn for_relation_spec_on_subject_with_query_presence<F, R>(
166 subject_slot: SubjectSlot,
167 query_presence: QueryPresence,
168 ) -> Result<Self, FactBindingError>
169 where
170 F: Fact,
171 R: RelationSpec,
172 {
173 Ok(Self::with_subject_and_query_presence(
174 F::ID.to_owned_id()?,
175 R::ID,
176 Some(subject_slot),
177 query_presence,
178 ))
179 }
180
181 #[must_use]
183 pub const fn fact(&self) -> &FactId {
184 &self.fact
185 }
186
187 #[must_use]
189 pub const fn relation_id(&self) -> RelationId {
190 self.relation_id
191 }
192
193 #[must_use]
195 pub const fn subject_slot(&self) -> Option<&SubjectSlot> {
196 self.subject_slot.as_ref()
197 }
198
199 #[must_use]
201 pub const fn query_presence(&self) -> QueryPresence {
202 self.query_presence
203 }
204}
205
206#[derive(Debug, Error, Clone, PartialEq, Eq)]
208pub enum FactBindingError {
209 #[error(transparent)]
211 Gatekeep(#[from] GatekeepError),
212}