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
26#[derive(Clone, Eq, PartialEq)]
33pub struct CoercionSpec {
34 pub(crate) id: CoercionId,
35 pub(crate) params: Vec<(String, String)>,
36}
37
38impl CoercionSpec {
39 #[must_use]
40 pub const fn new(id: CoercionId) -> Self {
41 Self {
42 id,
43 params: Vec::new(),
44 }
45 }
46
47 #[must_use]
49 pub const fn id(&self) -> CoercionId {
50 self.id
51 }
52
53 #[must_use]
55 pub const fn params(&self) -> &[(String, String)] {
56 self.params.as_slice()
57 }
58}
59
60impl fmt::Debug for CoercionSpec {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 f.debug_struct("CoercionSpec")
63 .field("id", &self.id)
64 .field("params", &CoercionParamsDebug(&self.params))
65 .finish()
66 }
67}
68
69impl Default for CoercionSpec {
70 fn default() -> Self {
71 Self::new(CoercionId::Strict)
72 }
73}
74
75struct CoercionParamsDebug<'a>(&'a [(String, String)]);
78
79impl fmt::Debug for CoercionParamsDebug<'_> {
80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81 let mut debug = f.debug_map();
82 for (key, value) in self.0 {
83 debug.entry(key, value);
84 }
85
86 debug.finish()
87 }
88}
89
90#[must_use]
92pub(in crate::db) fn supports_coercion(
93 left: CoercionFamily,
94 right: CoercionFamily,
95 id: CoercionId,
96) -> bool {
97 match id {
98 CoercionId::Strict | CoercionId::CollectionElement => true,
99 CoercionId::NumericWiden => {
100 left == CoercionFamily::Numeric && right == CoercionFamily::Numeric
101 }
102 CoercionId::TextCasefold => {
103 left == CoercionFamily::Textual && right == CoercionFamily::Textual
104 }
105 }
106}
107
108#[cfg(test)]
113mod tests {
114 use crate::{
115 db::predicate::{CoercionId, coercion::supports_coercion},
116 value::CoercionFamily,
117 };
118
119 #[test]
120 fn supports_coercion_matches_canonical_family_matrix() {
121 assert!(supports_coercion(
122 CoercionFamily::Numeric,
123 CoercionFamily::Textual,
124 CoercionId::Strict,
125 ));
126 assert!(supports_coercion(
127 CoercionFamily::Textual,
128 CoercionFamily::Numeric,
129 CoercionId::CollectionElement,
130 ));
131
132 assert!(supports_coercion(
133 CoercionFamily::Numeric,
134 CoercionFamily::Numeric,
135 CoercionId::NumericWiden,
136 ));
137 assert!(!supports_coercion(
138 CoercionFamily::Numeric,
139 CoercionFamily::Textual,
140 CoercionId::NumericWiden,
141 ));
142
143 assert!(supports_coercion(
144 CoercionFamily::Textual,
145 CoercionFamily::Textual,
146 CoercionId::TextCasefold,
147 ));
148 assert!(!supports_coercion(
149 CoercionFamily::Textual,
150 CoercionFamily::Numeric,
151 CoercionId::TextCasefold,
152 ));
153 }
154}