facet_core/types/def/
scalar.rs

1use crate::PtrConst;
2
3/// Definition for scalar types
4#[derive(Clone, Copy, Debug)]
5#[repr(C)]
6#[non_exhaustive]
7pub struct ScalarDef {
8    /// Affinity of the scalar — is spiritually more like a number, more like a string, something else?
9    /// example: an IPv4 address is both. good luck.
10    pub affinity: ScalarAffinity,
11}
12
13impl ScalarDef {
14    /// Returns a builder for ScalarDef
15    pub const fn builder() -> ScalarDefBuilder {
16        ScalarDefBuilder::new()
17    }
18}
19
20/// Builder for ScalarDef
21#[derive(Default)]
22pub struct ScalarDefBuilder {
23    affinity: Option<ScalarAffinity>,
24}
25
26impl ScalarDefBuilder {
27    /// Creates a new ScalarDefBuilder
28    #[allow(clippy::new_without_default)]
29    pub const fn new() -> Self {
30        Self { affinity: None }
31    }
32
33    /// Sets the affinity for the ScalarDef
34    pub const fn affinity(mut self, affinity: ScalarAffinity) -> Self {
35        self.affinity = Some(affinity);
36        self
37    }
38
39    /// Builds the ScalarDef
40    pub const fn build(self) -> ScalarDef {
41        ScalarDef {
42            affinity: self.affinity.unwrap(),
43        }
44    }
45}
46
47/// Scalar affinity: what a scalar spiritually is: a number, a string, a bool, something else
48/// entirely?
49#[derive(Clone, Copy, Debug)]
50#[repr(C)]
51#[non_exhaustive]
52pub enum ScalarAffinity {
53    /// Number-like scalar affinity
54    Number(NumberAffinity),
55    /// Complex-Number-like scalar affinity
56    ComplexNumber(ComplexNumberAffinity),
57    /// String-like scalar affinity
58    String(StringAffinity),
59    /// Boolean scalar affinity
60    Boolean(BoolAffinity),
61    /// Empty scalar affinity
62    Empty(EmptyAffinity),
63    /// Socket address scalar affinity
64    SocketAddr(SocketAddrAffinity),
65    /// Ip Address scalar affinity
66    IpAddr(IpAddrAffinity),
67    /// UUID or UUID-like identifier, containing 16 bytes of information
68    UUID(UuidAffinity),
69    /// ULID or ULID-like identifier, containing 16 bytes of information
70    ULID(UlidAffinity),
71    /// Timestamp or Datetime-like scalar affinity
72    Time(TimeAffinity),
73    /// Something you're not supposed to look inside of
74    Opaque(OpaqueAffinity),
75    /// Other scalar affinity
76    Other(OtherAffinity),
77    /// Character scalar affinity
78    Char(CharAffinity),
79    /// Path scalar affinity (file/disk paths)
80    Path(PathAffinity),
81}
82
83impl ScalarAffinity {
84    /// Returns a NumberAffinityBuilder
85    pub const fn number() -> NumberAffinityBuilder {
86        NumberAffinityBuilder::new()
87    }
88
89    /// Returns a ComplexNumberAffinityBuilder
90    pub const fn complex_number() -> ComplexNumberAffinityBuilder {
91        ComplexNumberAffinityBuilder::new()
92    }
93
94    /// Returns a StringAffinityBuilder
95    pub const fn string() -> StringAffinityBuilder {
96        StringAffinityBuilder::new()
97    }
98
99    /// Returns a BoolAffinityBuilder
100    pub const fn boolean() -> BoolAffinityBuilder {
101        BoolAffinityBuilder::new()
102    }
103
104    /// Returns an EmptyAffinityBuilder
105    pub const fn empty() -> EmptyAffinityBuilder {
106        EmptyAffinityBuilder::new()
107    }
108
109    /// Returns a SocketAddrAffinityBuilder
110    pub const fn socket_addr() -> SocketAddrAffinityBuilder {
111        SocketAddrAffinityBuilder::new()
112    }
113
114    /// Returns an IpAddrAffinityBuilder
115    pub const fn ip_addr() -> IpAddrAffinityBuilder {
116        IpAddrAffinityBuilder::new()
117    }
118
119    /// Returns an UuidAffinityBuilder
120    pub const fn uuid() -> UuidAffinityBuilder {
121        UuidAffinityBuilder::new()
122    }
123
124    /// Returns a UlidAffinityBuilder
125    pub const fn ulid() -> UlidAffinityBuilder {
126        UlidAffinityBuilder::new()
127    }
128
129    /// Returns an TimeAffinityBuilder
130    pub const fn time() -> TimeAffinityBuilder {
131        TimeAffinityBuilder::new()
132    }
133
134    /// Returns an OpaqueAffinityBuilder
135    pub const fn opaque() -> OpaqueAffinityBuilder {
136        OpaqueAffinityBuilder::new()
137    }
138
139    /// Returns an OtherAffinityBuilder
140    pub const fn other() -> OtherAffinityBuilder {
141        OtherAffinityBuilder::new()
142    }
143
144    /// Returns a CharAffinityBuilder
145    pub const fn char() -> CharAffinityBuilder {
146        CharAffinityBuilder::new()
147    }
148
149    /// Returns a PathAffinityBuilder
150    pub const fn path() -> PathAffinityBuilder {
151        PathAffinityBuilder::new()
152    }
153}
154
155//////////////////////////////////////////////////////////////////////////////////////////
156// Affinities
157//////////////////////////////////////////////////////////////////////////////////////////
158
159/// Definition for number-like scalar affinities
160#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
161#[repr(C)]
162#[non_exhaustive]
163pub struct NumberAffinity {
164    /// Bit representation of numbers
165    pub bits: NumberBits,
166
167    /// Minimum representable value
168    pub min: PtrConst<'static>,
169
170    /// Maximum representable value
171    pub max: PtrConst<'static>,
172
173    /// Positive infinity representable value
174    pub positive_infinity: Option<PtrConst<'static>>,
175
176    /// Negative infinity representable value
177    pub negative_infinity: Option<PtrConst<'static>>,
178
179    /// Example NaN (Not a Number) value.
180    /// Why sample? Because there are many NaN values, and we need to provide a representative one.
181    pub nan_sample: Option<PtrConst<'static>>,
182
183    /// Positive zero representation. If there's only one zero, only set this one.
184    pub positive_zero: Option<PtrConst<'static>>,
185
186    /// Negative zero representation
187    pub negative_zero: Option<PtrConst<'static>>,
188
189    /// "Machine epsilon" (<https://en.wikipedia.org/wiki/Machine_epsilon>), AKA relative
190    /// approximation error, if relevant
191    pub epsilon: Option<PtrConst<'static>>,
192}
193
194/// Represents whether a numeric type is signed or unsigned
195#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
196#[repr(C)]
197pub enum Signedness {
198    /// Signed numeric type
199    Signed,
200    /// Unsigned numeric type
201    Unsigned,
202}
203
204/// Bit representation of numbers
205#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
206#[repr(C)]
207#[non_exhaustive]
208pub enum NumberBits {
209    /// Integer number limits with specified number of bits
210    Integer {
211        /// Number of bits in the integer representation
212        bits: usize,
213        /// Whether the integer is signed or unsigned
214        sign: Signedness,
215    },
216    /// Floating-point number limits with specified sign, exponent and mantissa bits
217    Float {
218        /// Number of bits used for the sign (typically 1)
219        sign_bits: usize,
220        /// Number of bits used for the exponent
221        exponent_bits: usize,
222        /// Number of bits used for the mantissa (fraction part)
223        mantissa_bits: usize,
224        /// Floating-point numbers that are large enough to not be "in subnormal mode"
225        /// have their mantissa represent a number between 1 (included) and 2 (excluded)
226        /// This indicates whether the representation of the mantissa has the significant digit
227        /// (always 1) explicitly written out
228        has_explicit_first_mantissa_bit: bool,
229    },
230    /// Fixed-point number limits with specified integer and fractional bits
231    Fixed {
232        /// Number of bits used for the sign (typically 0 or 1)
233        sign_bits: usize,
234        /// Number of bits used for the integer part
235        integer_bits: usize,
236        /// Number of bits used for the fractional part
237        fraction_bits: usize,
238    },
239    /// Decimal number limits with unsized-integer, scaling, and sign bits
240    Decimal {
241        /// Number of bits used for the sign (typically 0 or 1)
242        sign_bits: usize,
243        /// Number of bits used for the integer part
244        integer_bits: usize,
245        /// Number of bits used for the scale part
246        scale_bits: usize,
247    },
248}
249
250impl NumberAffinity {
251    /// Returns a builder for NumberAffinity
252    pub const fn builder() -> NumberAffinityBuilder {
253        NumberAffinityBuilder::new()
254    }
255}
256
257/// Builder for NumberAffinity
258#[repr(C)]
259pub struct NumberAffinityBuilder {
260    limits: Option<NumberBits>,
261    min: Option<PtrConst<'static>>,
262    max: Option<PtrConst<'static>>,
263    positive_infinity: Option<PtrConst<'static>>,
264    negative_infinity: Option<PtrConst<'static>>,
265    nan_sample: Option<PtrConst<'static>>,
266    positive_zero: Option<PtrConst<'static>>,
267    negative_zero: Option<PtrConst<'static>>,
268    epsilon: Option<PtrConst<'static>>,
269}
270
271impl NumberAffinityBuilder {
272    /// Creates a new NumberAffinityBuilder
273    #[allow(clippy::new_without_default)]
274    pub const fn new() -> Self {
275        Self {
276            limits: None,
277            min: None,
278            max: None,
279            positive_infinity: None,
280            negative_infinity: None,
281            nan_sample: None,
282            positive_zero: None,
283            negative_zero: None,
284            epsilon: None,
285        }
286    }
287
288    /// Sets the number limits as integer with specified bits and sign
289    pub const fn integer(mut self, bits: usize, sign: Signedness) -> Self {
290        self.limits = Some(NumberBits::Integer { bits, sign });
291        self
292    }
293
294    /// Sets the number limits as signed integer with specified bits
295    pub const fn signed_integer(self, bits: usize) -> Self {
296        self.integer(bits, Signedness::Signed)
297    }
298
299    /// Sets the number limits as unsigned integer with specified bits
300    pub const fn unsigned_integer(self, bits: usize) -> Self {
301        self.integer(bits, Signedness::Unsigned)
302    }
303
304    /// Sets the number limits as float with specified bits
305    pub const fn float(
306        mut self,
307        sign_bits: usize,
308        exponent_bits: usize,
309        mantissa_bits: usize,
310        has_explicit_first_mantissa_bit: bool,
311    ) -> Self {
312        self.limits = Some(NumberBits::Float {
313            sign_bits,
314            exponent_bits,
315            mantissa_bits,
316            has_explicit_first_mantissa_bit,
317        });
318        self
319    }
320
321    /// Sets the number limits as fixed-point with specified bits
322    pub const fn fixed(
323        mut self,
324        sign_bits: usize,
325        integer_bits: usize,
326        fraction_bits: usize,
327    ) -> Self {
328        self.limits = Some(NumberBits::Fixed {
329            sign_bits,
330            integer_bits,
331            fraction_bits,
332        });
333        self
334    }
335
336    /// Sets the min value for the NumberAffinity
337    pub const fn min(mut self, min: PtrConst<'static>) -> Self {
338        self.min = Some(min);
339        self
340    }
341
342    /// Sets the max value for the NumberAffinity
343    pub const fn max(mut self, max: PtrConst<'static>) -> Self {
344        self.max = Some(max);
345        self
346    }
347
348    /// Sets the positive infinity value for the NumberAffinity
349    pub const fn positive_infinity(mut self, value: PtrConst<'static>) -> Self {
350        self.positive_infinity = Some(value);
351        self
352    }
353
354    /// Sets the negative infinity value for the NumberAffinity
355    pub const fn negative_infinity(mut self, value: PtrConst<'static>) -> Self {
356        self.negative_infinity = Some(value);
357        self
358    }
359
360    /// Sets the NaN sample value for the NumberAffinity
361    pub const fn nan_sample(mut self, value: PtrConst<'static>) -> Self {
362        self.nan_sample = Some(value);
363        self
364    }
365
366    /// Sets the positive zero value for the NumberAffinity
367    pub const fn positive_zero(mut self, value: PtrConst<'static>) -> Self {
368        self.positive_zero = Some(value);
369        self
370    }
371
372    /// Sets the negative zero value for the NumberAffinity
373    pub const fn negative_zero(mut self, value: PtrConst<'static>) -> Self {
374        self.negative_zero = Some(value);
375        self
376    }
377
378    /// Sets the relative uncertainty for the NumberAffinity
379    pub const fn epsilon(mut self, value: PtrConst<'static>) -> Self {
380        self.epsilon = Some(value);
381        self
382    }
383
384    /// Builds the ScalarAffinity
385    pub const fn build(self) -> ScalarAffinity {
386        ScalarAffinity::Number(NumberAffinity {
387            bits: self.limits.unwrap(),
388            min: self.min.unwrap(),
389            max: self.max.unwrap(),
390            positive_infinity: self.positive_infinity,
391            negative_infinity: self.negative_infinity,
392            nan_sample: self.nan_sample,
393            positive_zero: self.positive_zero,
394            negative_zero: self.negative_zero,
395            epsilon: self.epsilon,
396        })
397    }
398}
399
400/// Definition for string-like scalar affinities
401#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
402#[repr(C)]
403#[non_exhaustive]
404pub struct ComplexNumberAffinity {
405    /// hiding the actual enum in a non-pub element
406    inner: ComplexNumberAffinityInner,
407}
408
409#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
410#[repr(C)]
411#[non_exhaustive]
412enum ComplexNumberAffinityInner {
413    /// represented as a+ib
414    Cartesian {
415        /// the underlying number affinity for both components
416        /// (assuming they are the same seems reasonable)
417        component: NumberAffinity,
418    },
419    /// represented as a*exp(ib)
420    Polar {
421        /// the number affinity for the absolute value
422        absolute: NumberAffinity,
423        /// the number affinity for the ...angle? bearing?
424        bearing: NumberAffinity,
425    },
426}
427
428impl ComplexNumberAffinity {
429    /// Returns a builder for ComplexNumberAffinity
430    pub const fn builder() -> ComplexNumberAffinityBuilder {
431        ComplexNumberAffinityBuilder::new()
432    }
433}
434
435/// Builder for ComplexNumberAffinity
436#[repr(C)]
437pub struct ComplexNumberAffinityBuilder {
438    inner: ComplexNumberAffinityBuilderInner,
439}
440
441#[repr(C)]
442enum ComplexNumberAffinityBuilderInner {
443    Undefined,
444    Cartesian {
445        // note: this could have been a NumberAffinityBuilder,
446        // but we want to be able to set this up from existing Number types
447        component: NumberAffinity,
448    },
449    Polar {
450        absolute: NumberAffinity,
451        bearing: NumberAffinity,
452    },
453}
454
455impl ComplexNumberAffinityBuilder {
456    /// Creates a new ComplexNumberAffinityBuilder
457    #[allow(clippy::new_without_default)]
458    pub const fn new() -> Self {
459        Self {
460            inner: ComplexNumberAffinityBuilderInner::Undefined,
461        }
462    }
463
464    /// sets the coordinates system to be cartesian
465    pub const fn cartesian(self, component: NumberAffinity) -> Self {
466        Self {
467            inner: ComplexNumberAffinityBuilderInner::Cartesian { component },
468        }
469    }
470
471    /// sets the coordinates system to be polar
472    pub const fn polar(self, absolute: NumberAffinity, bearing: NumberAffinity) -> Self {
473        Self {
474            inner: ComplexNumberAffinityBuilderInner::Polar { absolute, bearing },
475        }
476    }
477
478    /// Builds the ScalarAffinity
479    pub const fn build(self) -> ScalarAffinity {
480        use ComplexNumberAffinityBuilderInner as Inner;
481        use ComplexNumberAffinityInner as AffInner;
482        let inner = match self.inner {
483            Inner::Undefined => panic!(),
484            Inner::Cartesian { component } => AffInner::Cartesian { component },
485            Inner::Polar { absolute, bearing } => AffInner::Polar { absolute, bearing },
486        };
487        ScalarAffinity::ComplexNumber(ComplexNumberAffinity { inner })
488    }
489}
490
491/// Definition for string-like scalar affinities
492#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
493#[repr(C)]
494#[non_exhaustive]
495pub struct StringAffinity {
496    /// Maximum inline length
497    pub max_inline_length: Option<usize>,
498}
499
500impl StringAffinity {
501    /// Returns a builder for StringAffinity
502    pub const fn builder() -> StringAffinityBuilder {
503        StringAffinityBuilder::new()
504    }
505}
506
507/// Builder for StringAffinity
508#[repr(C)]
509pub struct StringAffinityBuilder {
510    max_inline_length: Option<usize>,
511}
512
513impl StringAffinityBuilder {
514    /// Creates a new StringAffinityBuilder
515    #[allow(clippy::new_without_default)]
516    pub const fn new() -> Self {
517        Self {
518            max_inline_length: None,
519        }
520    }
521
522    /// Sets the max_inline_length for the StringAffinity
523    pub const fn max_inline_length(mut self, max_inline_length: usize) -> Self {
524        self.max_inline_length = Some(max_inline_length);
525        self
526    }
527
528    /// Builds the ScalarAffinity
529    pub const fn build(self) -> ScalarAffinity {
530        ScalarAffinity::String(StringAffinity {
531            max_inline_length: self.max_inline_length,
532        })
533    }
534}
535
536/// Definition for boolean scalar affinities
537#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
538#[repr(C)]
539#[non_exhaustive]
540pub struct BoolAffinity {}
541
542impl BoolAffinity {
543    /// Returns a builder for BoolAffinity
544    pub const fn builder() -> BoolAffinityBuilder {
545        BoolAffinityBuilder::new()
546    }
547}
548
549/// Builder for BoolAffinity
550#[repr(C)]
551pub struct BoolAffinityBuilder {}
552
553impl BoolAffinityBuilder {
554    /// Creates a new BoolAffinityBuilder
555    #[allow(clippy::new_without_default)]
556    pub const fn new() -> Self {
557        Self {}
558    }
559
560    /// Builds the ScalarAffinity
561    pub const fn build(self) -> ScalarAffinity {
562        ScalarAffinity::Boolean(BoolAffinity {})
563    }
564}
565
566/// Definition for empty scalar affinities
567#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
568#[repr(C)]
569#[non_exhaustive]
570pub struct EmptyAffinity {}
571
572impl EmptyAffinity {
573    /// Returns a builder for EmptyAffinity
574    pub const fn builder() -> EmptyAffinityBuilder {
575        EmptyAffinityBuilder::new()
576    }
577}
578
579/// Builder for EmptyAffinity
580#[repr(C)]
581pub struct EmptyAffinityBuilder {}
582
583impl EmptyAffinityBuilder {
584    /// Creates a new EmptyAffinityBuilder
585    #[allow(clippy::new_without_default)]
586    pub const fn new() -> Self {
587        Self {}
588    }
589
590    /// Builds the ScalarAffinity
591    pub const fn build(self) -> ScalarAffinity {
592        ScalarAffinity::Empty(EmptyAffinity {})
593    }
594}
595
596/// Definition for socket address scalar affinities
597#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
598#[repr(C)]
599#[non_exhaustive]
600pub struct SocketAddrAffinity {}
601
602impl SocketAddrAffinity {
603    /// Returns a builder for SocketAddrAffinity
604    pub const fn builder() -> SocketAddrAffinityBuilder {
605        SocketAddrAffinityBuilder::new()
606    }
607}
608
609/// Builder for SocketAddrAffinity
610#[repr(C)]
611pub struct SocketAddrAffinityBuilder {}
612
613impl SocketAddrAffinityBuilder {
614    /// Creates a new SocketAddrAffinityBuilder
615    #[allow(clippy::new_without_default)]
616    pub const fn new() -> Self {
617        Self {}
618    }
619
620    /// Builds the ScalarAffinity
621    pub const fn build(self) -> ScalarAffinity {
622        ScalarAffinity::SocketAddr(SocketAddrAffinity {})
623    }
624}
625
626/// Definition for IP address scalar affinities
627#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
628#[repr(C)]
629#[non_exhaustive]
630pub struct IpAddrAffinity {}
631
632impl IpAddrAffinity {
633    /// Returns a builder for IpAddrAffinity
634    pub const fn builder() -> IpAddrAffinityBuilder {
635        IpAddrAffinityBuilder::new()
636    }
637}
638
639/// Builder for IpAddrAffinity
640#[repr(C)]
641pub struct IpAddrAffinityBuilder {}
642
643impl IpAddrAffinityBuilder {
644    /// Creates a new IpAddrAffinityBuilder
645    #[allow(clippy::new_without_default)]
646    pub const fn new() -> Self {
647        Self {}
648    }
649
650    /// Builds the ScalarAffinity
651    pub const fn build(self) -> ScalarAffinity {
652        ScalarAffinity::IpAddr(IpAddrAffinity {})
653    }
654}
655
656/// Definition for UUID and UUID-like scalar affinities
657#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
658#[repr(C)]
659#[non_exhaustive]
660pub struct UuidAffinity {}
661
662impl UuidAffinity {
663    /// Returns a builder for UuidAffinity
664    pub const fn builder() -> UuidAffinityBuilder {
665        UuidAffinityBuilder::new()
666    }
667}
668
669/// Builder for UuidAffinity
670#[repr(C)]
671pub struct UuidAffinityBuilder {}
672
673impl UuidAffinityBuilder {
674    /// Creates a new UuidAffinityBuilder
675    #[allow(clippy::new_without_default)]
676    pub const fn new() -> Self {
677        Self {}
678    }
679
680    /// Builds the ScalarAffinity
681    pub const fn build(self) -> ScalarAffinity {
682        ScalarAffinity::UUID(UuidAffinity {})
683    }
684}
685
686/// Definition for ULID and ULID-like scalar affinities
687#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
688#[repr(C)]
689#[non_exhaustive]
690pub struct UlidAffinity {}
691
692impl UlidAffinity {
693    /// Returns a builder for UlidAffinity
694    pub const fn builder() -> UlidAffinityBuilder {
695        UlidAffinityBuilder::new()
696    }
697}
698
699/// Builder for UlidAffinity
700#[repr(C)]
701pub struct UlidAffinityBuilder {}
702
703impl UlidAffinityBuilder {
704    /// Creates a new UlidAffinityBuilder
705    #[allow(clippy::new_without_default)]
706    pub const fn new() -> Self {
707        UlidAffinityBuilder {}
708    }
709
710    /// Builds the ScalarAffinity
711    pub const fn build(self) -> ScalarAffinity {
712        ScalarAffinity::ULID(UlidAffinity {})
713    }
714}
715
716/// Definition for Datetime/Timestamp scalar affinities
717#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
718#[repr(C)]
719#[non_exhaustive]
720pub struct TimeAffinity {
721    /// What serves as the reference, or "time zero"
722    /// for implementations that don't depend on an epoch in the traditionnal sense,
723    /// the first moment of year 1AD can be used
724    epoch: Option<PtrConst<'static>>,
725
726    /// The first moment representable
727    min: Option<PtrConst<'static>>,
728
729    /// The last moment representable
730    max: Option<PtrConst<'static>>,
731
732    /// The moment immediately after the epoch,
733    /// serving as a proxy for the smallest interval of time representable
734    /// (do use None if this interval depends on when in time the interval occurs, e.g. if someone
735    /// ever decides to store a timestamp on floating-point numbers)
736    granularity: Option<PtrConst<'static>>,
737
738    // TODO: the following solution leaves a LOT to desire.
739    // Some examples of things where this breaks:
740    // - leap years, day length in daylight savings, leap seconds
741    // - datetime objects that seamlessly switch from Julian to Gregorian calendar
742    //   - even worse if this transition is based on when a given country did, if there even is
743    //   something that does this
744    // - datetime objects that allow you to specify both individual Gregorian months and ISO 8601
745    //   weeks (but of course not at the same time, which is the whole difficulty)
746    /// For DateTime types made of interval elements some of which are optional
747    /// (for instance, letting you say "the 1st of March" without specifying year, hours, etc.)
748    /// Specify how long the interval elements (hour, minute, etc.) are
749    /// (all represented as moments separated from the epoch by said intervals)
750    /// the intervals MUST be of increasing length. (TODO bikeshedding for this line)
751    interval_elements: Option<&'static [PtrConst<'static>]>,
752
753    /// the minimum interval between timezone-local times which correspond to the same global time
754    /// (planet-local time? I mean duh that's what global means right?)
755    /// store a copy of the epoch for a lack of timezone support, and None for "it's more
756    /// complicated than that".
757    timezone_granularity: Option<PtrConst<'static>>,
758}
759
760impl TimeAffinity {
761    /// Returns a builder for TimeAffinity
762    pub const fn builder() -> TimeAffinityBuilder {
763        TimeAffinityBuilder::new()
764    }
765}
766
767/// Builder for UuidAffinity
768#[repr(C)]
769pub struct TimeAffinityBuilder {
770    epoch: Option<PtrConst<'static>>,
771    min: Option<PtrConst<'static>>,
772    max: Option<PtrConst<'static>>,
773    granularity: Option<PtrConst<'static>>,
774    interval_elements: Option<&'static [PtrConst<'static>]>,
775    timezone_granularity: Option<PtrConst<'static>>,
776}
777
778impl TimeAffinityBuilder {
779    /// Creates a new UuidAffinityBuilder
780    #[allow(clippy::new_without_default)]
781    pub const fn new() -> Self {
782        Self {
783            epoch: None,
784            min: None,
785            max: None,
786            granularity: None,
787            interval_elements: None,
788            timezone_granularity: None,
789        }
790    }
791
792    /// Sets the epoch for the TimeAffinity
793    pub const fn epoch(mut self, epoch: PtrConst<'static>) -> Self {
794        self.epoch = Some(epoch);
795        self
796    }
797
798    /// Sets the min value for the TimeAffinity
799    pub const fn min(mut self, min: PtrConst<'static>) -> Self {
800        self.min = Some(min);
801        self
802    }
803
804    /// Sets the max value for the TimeAffinity
805    pub const fn max(mut self, max: PtrConst<'static>) -> Self {
806        self.max = Some(max);
807        self
808    }
809
810    /// Sets the granularity for the TimeAffinity
811    pub const fn granularity(mut self, granularity: PtrConst<'static>) -> Self {
812        self.granularity = Some(granularity);
813        self
814    }
815
816    /// Sets the interval elements for the TimeAffinity
817    pub const fn interval_elements(
818        mut self,
819        interval_elements: &'static [PtrConst<'static>],
820    ) -> Self {
821        self.interval_elements = Some(interval_elements);
822        self
823    }
824
825    /// Sets the timezone granularity for the TimeAffinity
826    pub const fn timezone_granularity(mut self, timezone_granularity: PtrConst<'static>) -> Self {
827        self.timezone_granularity = Some(timezone_granularity);
828        self
829    }
830
831    /// Builds the ScalarAffinity
832    pub const fn build(self) -> ScalarAffinity {
833        ScalarAffinity::Time(TimeAffinity {
834            epoch: self.epoch,
835            min: self.min,
836            max: self.max,
837            granularity: self.granularity,
838            interval_elements: self.interval_elements,
839            timezone_granularity: self.timezone_granularity,
840        })
841    }
842}
843
844/// Definition for opaque scalar affinities
845#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
846#[repr(C)]
847#[non_exhaustive]
848pub struct OpaqueAffinity {}
849
850impl OpaqueAffinity {
851    /// Returns a builder for OpaqueAffinity
852    pub const fn builder() -> OpaqueAffinityBuilder {
853        OpaqueAffinityBuilder::new()
854    }
855}
856
857/// Builder for OpaqueAffinity
858#[repr(C)]
859pub struct OpaqueAffinityBuilder {}
860
861impl OpaqueAffinityBuilder {
862    /// Creates a new OpaqueAffinityBuilder
863    #[allow(clippy::new_without_default)]
864    pub const fn new() -> Self {
865        Self {}
866    }
867
868    /// Builds the ScalarAffinity
869    pub const fn build(self) -> ScalarAffinity {
870        ScalarAffinity::Opaque(OpaqueAffinity {})
871    }
872}
873
874/// Definition for other scalar affinities
875#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
876#[repr(C)]
877#[non_exhaustive]
878pub struct OtherAffinity {}
879
880impl OtherAffinity {
881    /// Returns a builder for OtherAffinity
882    pub const fn builder() -> OtherAffinityBuilder {
883        OtherAffinityBuilder::new()
884    }
885}
886
887/// Builder for OtherAffinity
888#[repr(C)]
889pub struct OtherAffinityBuilder {}
890
891impl OtherAffinityBuilder {
892    /// Creates a new OtherAffinityBuilder
893    #[allow(clippy::new_without_default)]
894    pub const fn new() -> Self {
895        Self {}
896    }
897
898    /// Builds the ScalarAffinity
899    pub const fn build(self) -> ScalarAffinity {
900        ScalarAffinity::Other(OtherAffinity {})
901    }
902}
903
904/// Definition for character scalar affinities
905#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
906#[repr(C)]
907#[non_exhaustive]
908pub struct CharAffinity {}
909
910impl CharAffinity {
911    /// Returns a builder for CharAffinity
912    pub const fn builder() -> CharAffinityBuilder {
913        CharAffinityBuilder::new()
914    }
915}
916
917/// Builder for CharAffinity
918#[repr(C)]
919pub struct CharAffinityBuilder {}
920
921impl CharAffinityBuilder {
922    /// Creates a new CharAffinityBuilder
923    #[allow(clippy::new_without_default)]
924    pub const fn new() -> Self {
925        Self {}
926    }
927
928    /// Builds the ScalarAffinity
929    pub const fn build(self) -> ScalarAffinity {
930        ScalarAffinity::Char(CharAffinity {})
931    }
932}
933
934/// Definition for path scalar affinities
935#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
936#[repr(C)]
937#[non_exhaustive]
938pub struct PathAffinity {}
939
940impl PathAffinity {
941    /// Returns a builder for PathAffinity
942    pub const fn builder() -> PathAffinityBuilder {
943        PathAffinityBuilder::new()
944    }
945}
946
947/// Builder for PathAffinity
948#[repr(C)]
949pub struct PathAffinityBuilder {}
950
951impl PathAffinityBuilder {
952    /// Creates a new PathAffinityBuilder
953    #[allow(clippy::new_without_default)]
954    pub const fn new() -> Self {
955        Self {}
956    }
957
958    /// Builds the ScalarAffinity
959    pub const fn build(self) -> ScalarAffinity {
960        ScalarAffinity::Path(PathAffinity {})
961    }
962}