1mod conv;
2mod util;
3
4use ahash::HashMap;
5pub use ahash::HashMapExt as VariableMapExt;
6use serde::ser::{SerializeMap, SerializeTupleVariant};
7use serde::{Deserialize, Serialize, Serializer};
8use std::cell::RefCell;
9use std::fmt::{Display, Write};
10use std::hash::{Hash, Hasher};
11use std::rc::Rc;
12
13type RcCell<T> = Rc<RefCell<T>>;
14
15pub const MAX_TYPE_DEPTH: usize = 32;
16
17#[derive(Clone, Eq, PartialEq, Deserialize)]
18pub enum VariableType {
19 Any,
20 Null,
21 Bool,
22 String,
23 Number,
24 Date,
25 Interval,
26 Array(Rc<VariableType>),
27 Object(RcCell<HashMap<Rc<str>, VariableType>>),
28
29 Const(Rc<str>),
30 Enum(Option<Rc<str>>, Vec<Rc<str>>),
31 Nullable(Rc<VariableType>),
32}
33
34impl VariableType {
35 pub fn array(self) -> Self {
36 Self::Array(Rc::new(self))
37 }
38}
39
40const TYPE_NAME: &str = "VariableType";
41
42struct Guarded<'a> {
43 inner: &'a VariableType,
44 path: &'a [*const ()],
45}
46
47struct GuardedFields<'a> {
48 fields: &'a HashMap<Rc<str>, VariableType>,
49 path: Vec<*const ()>,
50}
51
52impl Serialize for VariableType {
53 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
54 Guarded {
55 inner: self,
56 path: &[],
57 }
58 .serialize(serializer)
59 }
60}
61
62impl Serialize for Guarded<'_> {
63 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
64 match self.inner {
65 VariableType::Any => serializer.serialize_unit_variant(TYPE_NAME, 0, "Any"),
66 VariableType::Null => serializer.serialize_unit_variant(TYPE_NAME, 1, "Null"),
67 VariableType::Bool => serializer.serialize_unit_variant(TYPE_NAME, 2, "Bool"),
68 VariableType::String => serializer.serialize_unit_variant(TYPE_NAME, 3, "String"),
69 VariableType::Number => serializer.serialize_unit_variant(TYPE_NAME, 4, "Number"),
70 VariableType::Date => serializer.serialize_unit_variant(TYPE_NAME, 5, "Date"),
71 VariableType::Interval => serializer.serialize_unit_variant(TYPE_NAME, 6, "Interval"),
72 VariableType::Array(inner) => serializer.serialize_newtype_variant(
73 TYPE_NAME,
74 7,
75 "Array",
76 &Guarded {
77 inner,
78 path: self.path,
79 },
80 ),
81 VariableType::Object(obj) => {
82 let ptr = Rc::as_ptr(obj) as *const ();
83 let cut = self.path.len() >= MAX_TYPE_DEPTH || self.path.contains(&ptr);
84 let empty = HashMap::default();
85 let borrowed;
86 let fields: &HashMap<Rc<str>, VariableType> = if cut {
87 &empty
88 } else {
89 borrowed = obj.borrow();
90 &borrowed
91 };
92 let mut path = self.path.to_vec();
93 path.push(ptr);
94 serializer.serialize_newtype_variant(
95 TYPE_NAME,
96 8,
97 "Object",
98 &GuardedFields { fields, path },
99 )
100 }
101 VariableType::Const(c) => {
102 serializer.serialize_newtype_variant(TYPE_NAME, 9, "Const", c.as_ref())
103 }
104 VariableType::Enum(name, values) => {
105 let mut tv = serializer.serialize_tuple_variant(TYPE_NAME, 10, "Enum", 2)?;
106 tv.serialize_field(name)?;
107 tv.serialize_field(values)?;
108 tv.end()
109 }
110 VariableType::Nullable(inner) => serializer.serialize_newtype_variant(
111 TYPE_NAME,
112 11,
113 "Nullable",
114 &Guarded {
115 inner,
116 path: self.path,
117 },
118 ),
119 }
120 }
121}
122
123impl Serialize for GuardedFields<'_> {
124 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
125 let mut map = serializer.serialize_map(Some(self.fields.len()))?;
126 for (key, value) in self.fields.iter() {
127 map.serialize_entry(
128 key.as_ref(),
129 &Guarded {
130 inner: value,
131 path: &self.path,
132 },
133 )?;
134 }
135 map.end()
136 }
137}
138
139impl Default for VariableType {
140 fn default() -> Self {
141 VariableType::Null
142 }
143}
144
145impl std::fmt::Debug for VariableType {
146 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
147 std::fmt::Debug::fmt(
148 &Guarded {
149 inner: self,
150 path: &[],
151 },
152 f,
153 )
154 }
155}
156
157impl std::fmt::Debug for Guarded<'_> {
158 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
159 match self.inner {
160 VariableType::Any => f.write_str("Any"),
161 VariableType::Null => f.write_str("Null"),
162 VariableType::Bool => f.write_str("Bool"),
163 VariableType::String => f.write_str("String"),
164 VariableType::Number => f.write_str("Number"),
165 VariableType::Date => f.write_str("Date"),
166 VariableType::Interval => f.write_str("Interval"),
167 VariableType::Array(inner) | VariableType::Nullable(inner) => {
168 let name = if matches!(self.inner, VariableType::Array(_)) {
169 "Array"
170 } else {
171 "Nullable"
172 };
173 f.debug_tuple(name)
174 .field(&Guarded {
175 inner,
176 path: self.path,
177 })
178 .finish()
179 }
180 VariableType::Const(value) => f.debug_tuple("Const").field(value).finish(),
181 VariableType::Enum(name, values) => {
182 f.debug_tuple("Enum").field(name).field(values).finish()
183 }
184 VariableType::Object(obj) => {
185 let ptr = Rc::as_ptr(obj) as *const ();
186 if self.path.len() >= MAX_TYPE_DEPTH || self.path.contains(&ptr) {
187 return f.write_str("Object(<recursive>)");
188 }
189 let mut path = self.path.to_vec();
190 path.push(ptr);
191 f.debug_tuple("Object")
192 .field(&DebugCell(GuardedFields {
193 fields: &obj.borrow(),
194 path,
195 }))
196 .finish()
197 }
198 }
199 }
200}
201
202struct DebugCell<'a>(GuardedFields<'a>);
203
204impl std::fmt::Debug for DebugCell<'_> {
205 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
206 f.debug_struct("RefCell").field("value", &self.0).finish()
207 }
208}
209
210impl std::fmt::Debug for GuardedFields<'_> {
211 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
212 f.debug_map()
213 .entries(self.fields.iter().map(|(key, value)| {
214 (
215 key,
216 Guarded {
217 inner: value,
218 path: &self.path,
219 },
220 )
221 }))
222 .finish()
223 }
224}
225
226impl Display for VariableType {
227 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
228 match self {
229 VariableType::Any => write!(f, "any"),
230 VariableType::Null => write!(f, "null"),
231 VariableType::Bool => write!(f, "bool"),
232 VariableType::String => write!(f, "string"),
233 VariableType::Number => write!(f, "number"),
234 VariableType::Date => write!(f, "date"),
235 VariableType::Interval => write!(f, "interval"),
236 VariableType::Const(c) => write!(f, "\"{c}\""),
237 VariableType::Enum(name, e) => {
238 if let Some(name) = name {
239 return name.fmt(f);
240 }
241
242 let mut first = true;
243 for s in e.iter() {
244 if !first {
245 f.write_str(" | ")?;
246 }
247
248 f.write_char('"')?;
249 f.write_str(s)?;
250 f.write_char('"')?;
251 first = false;
252 }
253
254 Ok(())
255 }
256 VariableType::Array(v) => write!(f, "{v}[]"),
257 VariableType::Object(_) => write!(f, "object"),
258 VariableType::Nullable(inner) => write!(f, "{inner}?"),
259 }
260 }
261}
262
263impl Hash for VariableType {
264 fn hash<H: Hasher>(&self, state: &mut H) {
265 match &self {
266 VariableType::Any => 0.hash(state),
267 VariableType::Null => 1.hash(state),
268 VariableType::Bool => 2.hash(state),
269 VariableType::String => 3.hash(state),
270 VariableType::Number => 4.hash(state),
271 VariableType::Date => 5.hash(state),
272 VariableType::Interval => 6.hash(state),
273 VariableType::Const(c) => {
274 7.hash(state);
275 c.hash(state)
276 }
277 VariableType::Enum(name, e) => {
278 8.hash(state);
279 name.hash(state);
280 e.hash(state)
281 }
282 VariableType::Array(arr) => {
283 9.hash(state);
284 arr.hash(state)
285 }
286 VariableType::Object(obj) => {
287 10.hash(state);
288
289 let obj = obj.borrow();
290 let mut pairs: Vec<_> = obj.iter().collect();
291 pairs.sort_by_key(|i| i.0);
292
293 Hash::hash(&pairs, state);
294 }
295 VariableType::Nullable(inner) => {
296 11.hash(state);
297 inner.hash(state);
298 }
299 }
300 }
301}