1use crate::{traits::FieldValueKind, types::EntityTag};
7
8#[derive(Clone, Copy, Debug, Eq, PartialEq)]
19pub enum FieldStorageDecode {
20 ByKind,
22 Value,
24}
25
26#[derive(Clone, Copy, Debug, Eq, PartialEq)]
36pub enum ScalarCodec {
37 Blob,
38 Bool,
39 Date,
40 Duration,
41 Float32,
42 Float64,
43 Int64,
44 Principal,
45 Subaccount,
46 Text,
47 Timestamp,
48 Uint64,
49 Ulid,
50 Unit,
51}
52
53#[derive(Clone, Copy, Debug, Eq, PartialEq)]
63pub enum LeafCodec {
64 Scalar(ScalarCodec),
65 CborFallback,
66}
67
68#[derive(Clone, Copy, Debug)]
78pub struct EnumVariantModel {
79 pub(crate) ident: &'static str,
81 pub(crate) payload_kind: Option<&'static FieldKind>,
83 pub(crate) payload_storage_decode: FieldStorageDecode,
85}
86
87impl EnumVariantModel {
88 #[must_use]
90 pub const fn new(
91 ident: &'static str,
92 payload_kind: Option<&'static FieldKind>,
93 payload_storage_decode: FieldStorageDecode,
94 ) -> Self {
95 Self {
96 ident,
97 payload_kind,
98 payload_storage_decode,
99 }
100 }
101
102 #[must_use]
104 pub const fn ident(&self) -> &'static str {
105 self.ident
106 }
107
108 #[must_use]
110 pub const fn payload_kind(&self) -> Option<&'static FieldKind> {
111 self.payload_kind
112 }
113
114 #[must_use]
116 pub const fn payload_storage_decode(&self) -> FieldStorageDecode {
117 self.payload_storage_decode
118 }
119}
120
121#[derive(Debug)]
131pub struct FieldModel {
132 pub(crate) name: &'static str,
134 pub(crate) kind: FieldKind,
136 pub(crate) storage_decode: FieldStorageDecode,
138 pub(crate) leaf_codec: LeafCodec,
140}
141
142impl FieldModel {
143 #[must_use]
145 pub const fn new(name: &'static str, kind: FieldKind) -> Self {
146 Self::new_with_storage_decode(name, kind, FieldStorageDecode::ByKind)
147 }
148
149 #[must_use]
151 pub const fn new_with_storage_decode(
152 name: &'static str,
153 kind: FieldKind,
154 storage_decode: FieldStorageDecode,
155 ) -> Self {
156 Self {
157 name,
158 kind,
159 storage_decode,
160 leaf_codec: leaf_codec_for(kind, storage_decode),
161 }
162 }
163
164 #[must_use]
166 pub const fn name(&self) -> &'static str {
167 self.name
168 }
169
170 #[must_use]
172 pub const fn kind(&self) -> FieldKind {
173 self.kind
174 }
175
176 #[must_use]
178 pub const fn storage_decode(&self) -> FieldStorageDecode {
179 self.storage_decode
180 }
181
182 #[must_use]
184 pub const fn leaf_codec(&self) -> LeafCodec {
185 self.leaf_codec
186 }
187}
188
189const fn leaf_codec_for(kind: FieldKind, storage_decode: FieldStorageDecode) -> LeafCodec {
193 if matches!(storage_decode, FieldStorageDecode::Value) {
194 return LeafCodec::CborFallback;
195 }
196
197 match kind {
198 FieldKind::Blob => LeafCodec::Scalar(ScalarCodec::Blob),
199 FieldKind::Bool => LeafCodec::Scalar(ScalarCodec::Bool),
200 FieldKind::Date => LeafCodec::Scalar(ScalarCodec::Date),
201 FieldKind::Duration => LeafCodec::Scalar(ScalarCodec::Duration),
202 FieldKind::Float32 => LeafCodec::Scalar(ScalarCodec::Float32),
203 FieldKind::Float64 => LeafCodec::Scalar(ScalarCodec::Float64),
204 FieldKind::Int => LeafCodec::Scalar(ScalarCodec::Int64),
205 FieldKind::Principal => LeafCodec::Scalar(ScalarCodec::Principal),
206 FieldKind::Subaccount => LeafCodec::Scalar(ScalarCodec::Subaccount),
207 FieldKind::Text => LeafCodec::Scalar(ScalarCodec::Text),
208 FieldKind::Timestamp => LeafCodec::Scalar(ScalarCodec::Timestamp),
209 FieldKind::Uint => LeafCodec::Scalar(ScalarCodec::Uint64),
210 FieldKind::Ulid => LeafCodec::Scalar(ScalarCodec::Ulid),
211 FieldKind::Unit => LeafCodec::Scalar(ScalarCodec::Unit),
212 FieldKind::Relation { key_kind, .. } => leaf_codec_for(*key_kind, storage_decode),
213 FieldKind::Account
214 | FieldKind::Decimal { .. }
215 | FieldKind::Enum { .. }
216 | FieldKind::Int128
217 | FieldKind::IntBig
218 | FieldKind::List(_)
219 | FieldKind::Map { .. }
220 | FieldKind::Set(_)
221 | FieldKind::Structured { .. }
222 | FieldKind::Uint128
223 | FieldKind::UintBig => LeafCodec::CborFallback,
224 }
225}
226
227#[derive(Clone, Copy, Debug, Eq, PartialEq)]
234pub enum RelationStrength {
235 Strong,
236 Weak,
237}
238
239#[derive(Clone, Copy, Debug)]
249pub enum FieldKind {
250 Account,
252 Blob,
253 Bool,
254 Date,
255 Decimal {
256 scale: u32,
258 },
259 Duration,
260 Enum {
261 path: &'static str,
263 variants: &'static [EnumVariantModel],
265 },
266 Float32,
267 Float64,
268 Int,
269 Int128,
270 IntBig,
271 Principal,
272 Subaccount,
273 Text,
274 Timestamp,
275 Uint,
276 Uint128,
277 UintBig,
278 Ulid,
279 Unit,
280
281 Relation {
284 target_path: &'static str,
286 target_entity_name: &'static str,
288 target_entity_tag: EntityTag,
290 target_store_path: &'static str,
292 key_kind: &'static Self,
293 strength: RelationStrength,
294 },
295
296 List(&'static Self),
298 Set(&'static Self),
299 Map {
303 key: &'static Self,
304 value: &'static Self,
305 },
306
307 Structured {
311 queryable: bool,
312 },
313}
314
315impl FieldKind {
316 #[must_use]
317 pub const fn value_kind(&self) -> FieldValueKind {
318 match self {
319 Self::Account
320 | Self::Blob
321 | Self::Bool
322 | Self::Date
323 | Self::Duration
324 | Self::Enum { .. }
325 | Self::Float32
326 | Self::Float64
327 | Self::Int
328 | Self::Int128
329 | Self::IntBig
330 | Self::Principal
331 | Self::Subaccount
332 | Self::Text
333 | Self::Timestamp
334 | Self::Uint
335 | Self::Uint128
336 | Self::UintBig
337 | Self::Ulid
338 | Self::Unit
339 | Self::Decimal { .. }
340 | Self::Relation { .. } => FieldValueKind::Atomic,
341 Self::List(_) | Self::Set(_) => FieldValueKind::Structured { queryable: true },
342 Self::Map { .. } => FieldValueKind::Structured { queryable: false },
343 Self::Structured { queryable } => FieldValueKind::Structured {
344 queryable: *queryable,
345 },
346 }
347 }
348
349 #[must_use]
357 pub const fn is_deterministic_collection_shape(&self) -> bool {
358 match self {
359 Self::Relation { key_kind, .. } => key_kind.is_deterministic_collection_shape(),
360
361 Self::List(inner) | Self::Set(inner) => inner.is_deterministic_collection_shape(),
362
363 Self::Map { key, value } => {
364 key.is_deterministic_collection_shape() && value.is_deterministic_collection_shape()
365 }
366
367 _ => true,
368 }
369 }
370}