icydb_diagnostic_code/
fact.rs1use std::fmt;
8
9pub const MAX_PUBLIC_DIAGNOSTIC_FACTS: usize = 80;
11
12macro_rules! define_fact_tag_registry {
13 ($($name:ident = $raw:literal;)+) => {
14 #[derive(Clone, Copy, Eq, Hash, PartialEq)]
16 pub enum DiagnosticFactTag {
17 $(
18 #[doc = concat!("Public fact tag ", stringify!($raw), ".")]
19 $name,
20 )+
21 }
22
23 impl DiagnosticFactTag {
24 #[must_use]
26 pub const fn raw(self) -> u8 {
27 match self {
28 $(Self::$name => $raw,)+
29 }
30 }
31
32 #[must_use]
34 pub const fn known(raw: u8) -> Option<Self> {
35 match raw {
36 $($raw => Some(Self::$name),)+
37 _ => None,
38 }
39 }
40 }
41
42 #[cfg(test)]
43 const ORDERED_FACT_TAGS: &[DiagnosticFactTag] = &[
44 $(DiagnosticFactTag::$name,)+
45 ];
46 };
47}
48
49define_fact_tag_registry! {
52 AcceptedSchemaFingerprintMethod = 1;
53 AcceptedSchemaFingerprintHigh = 2;
54 AcceptedSchemaFingerprintLow = 3;
55 ExpectedFingerprintPrefix = 4;
56 ActualFingerprintPrefix = 5;
57 EntityTag = 6;
58 ExpectedEntityTag = 7;
59 ActualEntityTag = 8;
60 ConstraintId = 9;
61 FieldId = 10;
62 IndexId = 11;
63 RelationId = 12;
64 MutationOperation = 13;
65 RowOperation = 14;
66 BatchPosition = 15;
67 FirstBatchPosition = 16;
68 DuplicateBatchPosition = 17;
69 ClauseIndex = 18;
70 TermIndex = 19;
71 FirstTermIndex = 20;
72 DuplicateTermIndex = 21;
73 ProjectionIndex = 22;
74 GroupIndex = 23;
75 AggregateIndex = 24;
76 ArgumentIndex = 25;
77 BranchIndex = 26;
78 ComponentIndex = 27;
79 ParameterIndex = 28;
80 SourceSpanStart = 29;
81 SourceSpanEnd = 30;
82 Expected = 31;
83 Actual = 32;
84 Minimum = 33;
85 Maximum = 34;
86 Limit = 35;
87 ExpectedCount = 36;
88 ActualCount = 37;
89 ExpectedRevision = 38;
90 ActualRevision = 39;
91 CurrentRevision = 40;
92 RequestedRevision = 41;
93 ExpectedVersion = 42;
94 ActualVersion = 43;
95 CurrentVersion = 44;
96 RequestedVersion = 45;
97 ExpectedOffset = 46;
98 ActualOffset = 47;
99 ExpectedArity = 48;
100 ActualArity = 49;
101 ExpectedLength = 50;
102 ActualLength = 51;
103 ExpectedSlotCount = 52;
104 ActualSlotCount = 53;
105 RowLayout = 54;
106 HistoryFloor = 55;
107 CurrentLayout = 56;
108 PhysicalSlot = 57;
109 PhysicalGeneration = 58;
110 ExpectedMemoryId = 59;
111 ActualMemoryId = 60;
112 ConstraintKind = 61;
113 ConstraintContext = 62;
114 FieldKind = 63;
115 ValueKind = 64;
116 TypeFamily = 65;
117 FunctionKind = 66;
118 OperatorKind = 67;
119 AggregateKind = 68;
120 KeyNamespaceKind = 69;
121 ComponentKind = 70;
122 MismatchKind = 71;
123 DecodeReason = 72;
124 BudgetResource = 73;
125 MigrationPhase = 74;
126 DatabaseControlRecordKind = 75;
127 StateKind = 76;
128 PayloadComponent = 77;
129 ExpectedSignaturePrefix = 78;
130 ActualSignaturePrefix = 79;
131 FindingPosition = 80;
132 RootField = 81;
133 RecordMember = 82;
134 TupleElement = 83;
135 Newtype = 84;
136 EnumVariant = 85;
137 ListElement = 86;
138 SetElement = 87;
139 MapEntryKey = 88;
140 MapEntryValue = 89;
141}
142
143impl fmt::Debug for DiagnosticFactTag {
144 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145 write!(f, "{}", self.raw())
146 }
147}
148
149#[must_use]
151pub const fn pack_u32_pair(high: u32, low: u32) -> u64 {
152 (high as u64) << 32 | low as u64
153}
154
155#[must_use]
157pub const fn unpack_u32_pair(value: u64) -> (u32, u32) {
158 let bytes = value.to_be_bytes();
159 (
160 u32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]),
161 u32::from_be_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]),
162 )
163}
164
165#[cfg(test)]
166mod tests {
167 use super::{DiagnosticFactTag, ORDERED_FACT_TAGS, pack_u32_pair, unpack_u32_pair};
168
169 #[test]
170 fn fact_tag_registry_is_fixed_unique_and_contiguous() {
171 for (index, tag) in ORDERED_FACT_TAGS.iter().copied().enumerate() {
172 let expected = u8::try_from(index + 1).expect("fact-tag index fits u8");
173 assert_eq!(tag.raw(), expected);
174 assert_eq!(DiagnosticFactTag::known(expected), Some(tag));
175 }
176
177 assert_eq!(DiagnosticFactTag::known(0), None);
178 assert_eq!(DiagnosticFactTag::known(90), None);
179 assert_eq!(DiagnosticFactTag::known(u8::MAX), None);
180 }
181
182 #[test]
183 fn accepted_identity_pair_packing_is_exact() {
184 for pair in [
185 (0, 0),
186 (1, 2),
187 (u32::MAX, 0),
188 (0, u32::MAX),
189 (u32::MAX, u32::MAX),
190 ] {
191 assert_eq!(unpack_u32_pair(pack_u32_pair(pair.0, pair.1)), pair);
192 }
193 }
194}