Skip to main content

graphrecords_query/registry/
descriptor.rs

1use 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}