icydb_core/db/predicate/
coercion.rs1use crate::value::CoercionFamily;
7use std::fmt;
8
9#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
19pub enum CoercionId {
20 Strict,
21 NumericWiden,
22 TextCasefold,
23 CollectionElement,
24}
25
26impl CoercionId {
27 #[must_use]
29 pub const fn plan_hash_tag(self) -> u8 {
30 match self {
31 Self::Strict => 0x01,
32 Self::NumericWiden => 0x02,
33 Self::TextCasefold => 0x04,
34 Self::CollectionElement => 0x05,
35 }
36 }
37}
38
39#[derive(Clone, Eq, PartialEq)]
46pub struct CoercionSpec {
47 pub(crate) id: CoercionId,
48 pub(crate) params: Vec<(String, String)>,
49}
50
51impl CoercionSpec {
52 #[must_use]
53 pub const fn new(id: CoercionId) -> Self {
54 Self {
55 id,
56 params: Vec::new(),
57 }
58 }
59}
60
61impl fmt::Debug for CoercionSpec {
62 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63 f.debug_struct("CoercionSpec")
64 .field("id", &self.id)
65 .field("params", &CoercionParamsDebug(&self.params))
66 .finish()
67 }
68}
69
70impl Default for CoercionSpec {
71 fn default() -> Self {
72 Self::new(CoercionId::Strict)
73 }
74}
75
76struct CoercionParamsDebug<'a>(&'a [(String, String)]);
79
80impl fmt::Debug for CoercionParamsDebug<'_> {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 let mut debug = f.debug_map();
83 for (key, value) in self.0 {
84 debug.entry(key, value);
85 }
86
87 debug.finish()
88 }
89}
90
91#[derive(Clone, Copy, Debug, Eq, PartialEq)]
98pub(crate) enum CoercionRuleFamily {
99 Any,
100 Family(CoercionFamily),
101}
102
103#[derive(Clone, Copy, Debug, Eq, PartialEq)]
110pub(crate) struct CoercionRule {
111 left: CoercionRuleFamily,
112 right: CoercionRuleFamily,
113 id: CoercionId,
114}
115
116pub(crate) const COERCION_TABLE: &[CoercionRule] = &[
117 CoercionRule {
118 left: CoercionRuleFamily::Any,
119 right: CoercionRuleFamily::Any,
120 id: CoercionId::Strict,
121 },
122 CoercionRule {
123 left: CoercionRuleFamily::Family(CoercionFamily::Numeric),
124 right: CoercionRuleFamily::Family(CoercionFamily::Numeric),
125 id: CoercionId::NumericWiden,
126 },
127 CoercionRule {
128 left: CoercionRuleFamily::Family(CoercionFamily::Textual),
129 right: CoercionRuleFamily::Family(CoercionFamily::Textual),
130 id: CoercionId::TextCasefold,
131 },
132 CoercionRule {
133 left: CoercionRuleFamily::Any,
134 right: CoercionRuleFamily::Any,
135 id: CoercionId::CollectionElement,
136 },
137];
138
139#[must_use]
141pub(in crate::db) fn supports_coercion(
142 left: CoercionFamily,
143 right: CoercionFamily,
144 id: CoercionId,
145) -> bool {
146 COERCION_TABLE.iter().any(|rule| {
147 rule.id == id && family_matches(rule.left, left) && family_matches(rule.right, right)
148 })
149}
150
151fn family_matches(rule: CoercionRuleFamily, value: CoercionFamily) -> bool {
152 match rule {
153 CoercionRuleFamily::Any => true,
154 CoercionRuleFamily::Family(expected) => expected == value,
155 }
156}