graphrecords_query/registry/
descriptor.rs1use crate::{EntityDomain, IndexDomain, Unit, ValueDomain};
2use std::any::{TypeId, type_name};
3
4struct IndexValueDescriptor;
5struct EntityReferenceDescriptor;
6
7#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
8pub struct DomainDescriptor {
9 identifier: TypeId,
10 name: &'static str,
11}
12
13impl DomainDescriptor {
14 #[must_use]
15 pub fn of<T: 'static>() -> Self {
16 Self {
17 identifier: TypeId::of::<T>(),
18 name: type_name::<T>(),
19 }
20 }
21
22 #[must_use]
23 pub fn is<T: 'static>(&self) -> bool {
24 self.identifier == TypeId::of::<T>()
25 }
26
27 #[must_use]
28 pub const fn name(&self) -> &'static str {
29 self.name
30 }
31}
32
33#[derive(Clone, PartialEq, Eq, Hash, Debug)]
34pub enum IndexDescriptor {
35 Domain(DomainDescriptor),
36 Expanded { parent: Box<Self>, child: Box<Self> },
37 ExpandedSource { parent: Box<Self> },
38}
39
40impl IndexDescriptor {
41 #[must_use]
42 pub fn domain<I: IndexDomain>() -> Self {
43 Self::Domain(DomainDescriptor::of::<I>())
44 }
45
46 #[must_use]
47 pub fn expanded(parent: Self, child: Self) -> Self {
48 Self::Expanded {
49 parent: Box::new(parent),
50 child: Box::new(child),
51 }
52 }
53
54 #[must_use]
55 pub fn expanded_source(parent: Self) -> Self {
56 Self::ExpandedSource {
57 parent: Box::new(parent),
58 }
59 }
60}
61
62#[derive(Clone, PartialEq, Eq, Hash, Debug)]
63pub enum ValueRole {
64 Value,
65 Index(IndexDescriptor),
66 EntityReference(IndexDescriptor),
67 Unit,
68}
69
70#[derive(Clone, PartialEq, Eq, Hash, Debug)]
71pub struct ValueDescriptor {
72 domain: DomainDescriptor,
73 role: ValueRole,
74}
75
76impl ValueDescriptor {
77 #[must_use]
78 pub fn value<V: ValueDomain>() -> Self {
79 Self {
80 domain: DomainDescriptor::of::<V>(),
81 role: ValueRole::Value,
82 }
83 }
84
85 #[must_use]
86 pub fn index(index: IndexDescriptor) -> Self {
87 Self {
88 domain: DomainDescriptor::of::<IndexValueDescriptor>(),
89 role: ValueRole::Index(index),
90 }
91 }
92
93 #[must_use]
94 pub fn entity_reference<E: EntityDomain>() -> Self {
95 Self {
96 domain: DomainDescriptor::of::<EntityReferenceDescriptor>(),
97 role: ValueRole::EntityReference(IndexDescriptor::domain::<E>()),
98 }
99 }
100
101 #[must_use]
102 pub fn entity_reference_index(index: IndexDescriptor) -> Self {
103 Self {
104 domain: DomainDescriptor::of::<EntityReferenceDescriptor>(),
105 role: ValueRole::EntityReference(index),
106 }
107 }
108
109 #[must_use]
110 pub fn unit() -> Self {
111 Self {
112 domain: DomainDescriptor::of::<Unit>(),
113 role: ValueRole::Unit,
114 }
115 }
116
117 #[must_use]
118 pub const fn domain(&self) -> &DomainDescriptor {
119 &self.domain
120 }
121
122 #[must_use]
123 pub const fn role(&self) -> &ValueRole {
124 &self.role
125 }
126}
127
128#[derive(Clone, PartialEq, Eq, Hash, Debug)]
129pub enum LaneShapeDescriptor {
130 Indexed {
131 index: IndexDescriptor,
132 value: ValueDescriptor,
133 },
134 Bare {
135 value: ValueDescriptor,
136 },
137}
138
139impl LaneShapeDescriptor {
140 #[must_use]
141 pub const fn value(&self) -> &ValueDescriptor {
142 match self {
143 Self::Indexed { value, .. } | Self::Bare { value } => value,
144 }
145 }
146}
147
148#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
149pub enum OrderDescriptor {
150 Ordered,
151 Unordered,
152}
153
154#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
155pub enum ArityDescriptor {
156 Multiple { order: OrderDescriptor },
157 Single,
158 Definite,
159}
160
161#[derive(Clone, PartialEq, Eq, Hash, Debug)]
162pub enum OperandDescriptor {
163 Lane {
164 shape: LaneShapeDescriptor,
165 arity: ArityDescriptor,
166 },
167 Group {
168 member: IndexDescriptor,
169 key: IndexDescriptor,
170 payload: Box<Self>,
171 },
172}
173
174impl OperandDescriptor {
175 #[must_use]
176 pub fn lane_shape(&self) -> &LaneShapeDescriptor {
177 match self {
178 Self::Lane { shape, .. } => shape,
179 Self::Group { payload, .. } => payload.lane_shape(),
180 }
181 }
182
183 #[must_use]
184 pub fn lane_arity(&self) -> ArityDescriptor {
185 match self {
186 Self::Lane { arity, .. } => *arity,
187 Self::Group { payload, .. } => payload.lane_arity(),
188 }
189 }
190
191 #[must_use]
192 pub fn group_depth(&self) -> usize {
193 match self {
194 Self::Lane { .. } => 0,
195 Self::Group { payload, .. } => 1 + payload.group_depth(),
196 }
197 }
198
199 #[must_use]
200 pub fn with_lane_value(&self, value: ValueDescriptor) -> Self {
201 match self {
202 Self::Lane { shape, arity } => Self::Lane {
203 shape: match shape {
204 LaneShapeDescriptor::Indexed { index, .. } => LaneShapeDescriptor::Indexed {
205 index: index.clone(),
206 value,
207 },
208 LaneShapeDescriptor::Bare { .. } => LaneShapeDescriptor::Bare { value },
209 },
210 arity: *arity,
211 },
212 Self::Group {
213 member,
214 key,
215 payload,
216 } => Self::Group {
217 member: member.clone(),
218 key: key.clone(),
219 payload: Box::new(payload.with_lane_value(value)),
220 },
221 }
222 }
223}
224
225#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default)]
226pub enum RetentionDescriptor {
227 #[default]
228 Preserving,
229 Dropping,
230}
231
232#[derive(Clone, PartialEq, Eq, Hash, Debug)]
233pub enum ArgumentValueSource {
234 Literal(ValueDescriptor),
235 Operand(OperandDescriptor),
236}
237
238impl ArgumentValueSource {
239 #[must_use]
240 pub fn value(&self) -> &ValueDescriptor {
241 match self {
242 Self::Literal(value) => value,
243 Self::Operand(operand) => operand.lane_shape().value(),
244 }
245 }
246}
247
248#[derive(Clone, PartialEq, Eq, Hash, Debug)]
249pub enum ArgumentMissingPolicy {
250 None,
251 Drop,
252 Replace(ArgumentValueSource),
253}
254
255#[derive(Clone, PartialEq, Eq, Hash, Debug)]
256pub struct ValueArgumentDescriptor {
257 source: ArgumentValueSource,
258 missing: ArgumentMissingPolicy,
259}
260
261impl ValueArgumentDescriptor {
262 #[must_use]
263 pub const fn literal(value: ValueDescriptor) -> Self {
264 Self {
265 source: ArgumentValueSource::Literal(value),
266 missing: ArgumentMissingPolicy::None,
267 }
268 }
269
270 #[must_use]
271 pub const fn operand(operand: OperandDescriptor) -> Self {
272 Self {
273 source: ArgumentValueSource::Operand(operand),
274 missing: ArgumentMissingPolicy::None,
275 }
276 }
277
278 #[must_use]
279 pub fn with_missing(self, missing: ArgumentMissingPolicy) -> Self {
280 Self {
281 source: self.source,
282 missing,
283 }
284 }
285
286 #[must_use]
287 pub const fn source(&self) -> &ArgumentValueSource {
288 &self.source
289 }
290
291 #[must_use]
292 pub const fn missing(&self) -> &ArgumentMissingPolicy {
293 &self.missing
294 }
295
296 #[must_use]
297 pub fn value(&self) -> &ValueDescriptor {
298 self.source.value()
299 }
300
301 #[must_use]
302 pub const fn retention(&self) -> RetentionDescriptor {
303 match self.missing {
304 ArgumentMissingPolicy::Drop => RetentionDescriptor::Dropping,
305 ArgumentMissingPolicy::None | ArgumentMissingPolicy::Replace(_) => {
306 RetentionDescriptor::Preserving
307 }
308 }
309 }
310}
311
312#[derive(Clone, PartialEq, Eq, Hash, Debug)]
313pub enum ArgumentDescriptor {
314 Value(ValueArgumentDescriptor),
315 Field(DomainDescriptor),
316 Selector(DomainDescriptor),
317 Operand(OperandDescriptor),
318}
319
320impl ArgumentDescriptor {
321 #[must_use]
322 pub fn field<T: 'static>() -> Self {
323 Self::Field(DomainDescriptor::of::<T>())
324 }
325
326 #[must_use]
327 pub fn selector<T: 'static>() -> Self {
328 Self::Selector(DomainDescriptor::of::<T>())
329 }
330}