1use core::fmt;
2use hive_router_query_planner::ast::selection_item::SelectionItem;
3use serde::{
4 de::{self, Deserializer, MapAccess, SeqAccess, Visitor},
5 ser::{SerializeMap, SerializeSeq},
6};
7use sonic_rs::{JsonNumberTrait, ValueRef};
8use std::{
9 borrow::Cow,
10 fmt::Display,
11 hash::{Hash, Hasher},
12};
13use xxhash_rust::xxh3::Xxh3;
14
15use crate::{introspection::schema::PossibleTypes, utils::consts::TYPENAME_FIELD_NAME};
16
17#[derive(Debug, Clone, Default)]
18pub enum Value<'a> {
19 #[default]
20 Null,
21 F64(f64),
22 I64(i64),
23 U64(u64),
24 Bool(bool),
25 String(Cow<'a, str>),
26 Array(Vec<Value<'a>>),
27 Object(Vec<(&'a str, Value<'a>)>),
28}
29
30impl Hash for Value<'_> {
31 fn hash<H: Hasher>(&self, state: &mut H) {
32 match self {
33 Value::Null => 0.hash(state),
34 Value::F64(f) => f.to_bits().hash(state),
35 Value::I64(i) => i.hash(state),
36 Value::U64(u) => u.hash(state),
37 Value::Bool(b) => b.hash(state),
38 Value::String(s) => s.hash(state),
39 Value::Array(arr) => arr.hash(state),
40 Value::Object(obj) => obj.hash(state),
41 }
42 }
43}
44
45impl<'a> Value<'a> {
46 pub fn take_entities(&mut self) -> Option<Vec<Value<'a>>> {
47 match self {
48 Value::Object(data) => {
49 if let Ok(entities_idx) = data.binary_search_by_key(&"_entities", |(k, _)| *k) {
50 if let Value::Array(arr) = data.remove(entities_idx).1 {
51 return Some(arr);
52 }
53 }
54 None
55 }
56 _ => None,
57 }
58 }
59
60 pub fn to_hash(
61 &self,
62 selection_items: &[SelectionItem],
63 possible_types: &PossibleTypes,
64 ) -> u64 {
65 let mut hasher = Xxh3::new();
66 self.hash_with_requires(&mut hasher, selection_items, possible_types);
67 hasher.finish()
68 }
69
70 fn hash_with_requires<H: Hasher>(
71 &self,
72 state: &mut H,
73 selection_items: &[SelectionItem],
74 possible_types: &PossibleTypes,
75 ) {
76 if selection_items.is_empty() {
77 self.hash(state);
78 return;
79 }
80
81 match self {
82 Value::Object(obj) => {
83 Value::hash_object_with_requires(state, obj, selection_items, possible_types);
84 }
85 Value::Array(arr) => {
86 for item in arr {
87 item.hash_with_requires(state, selection_items, possible_types);
88 }
89 }
90 _ => {
91 self.hash(state);
92 }
93 }
94 }
95
96 fn hash_object_with_requires<H: Hasher>(
97 state: &mut H,
98 obj: &[(&'a str, Value<'a>)],
99 selection_items: &[SelectionItem],
100 possible_types: &PossibleTypes,
101 ) {
102 for item in selection_items {
103 match item {
104 SelectionItem::Field(field_selection) => {
105 let field_name = &field_selection.name;
106 if let Ok(idx) = obj.binary_search_by_key(&field_name.as_str(), |(k, _)| k) {
107 let (key, value) = &obj[idx];
108 key.hash(state);
109 value.hash_with_requires(
110 state,
111 &field_selection.selections.items,
112 possible_types,
113 );
114 }
115 }
116 SelectionItem::InlineFragment(inline_fragment) => {
117 let type_condition = &inline_fragment.type_condition;
118 let type_name = obj
119 .binary_search_by_key(&TYPENAME_FIELD_NAME, |(k, _)| k)
120 .ok()
121 .and_then(|idx| obj[idx].1.as_str())
122 .unwrap_or(type_condition);
123
124 if possible_types.entity_satisfies_type_condition(type_name, type_condition) {
125 Value::hash_object_with_requires(
126 state,
127 obj,
128 &inline_fragment.selections.items,
129 possible_types,
130 );
131 }
132 }
133 SelectionItem::FragmentSpread(_) => {
134 unreachable!("Fragment spreads should not exist in FetchNode::requires.")
135 }
136 }
137 }
138 }
139
140 pub fn from(json: ValueRef<'a>) -> Value<'a> {
141 match json {
142 ValueRef::Null => Value::Null,
143 ValueRef::Bool(b) => Value::Bool(b),
144 ValueRef::String(s) => Value::String(s.into()),
145 ValueRef::Number(num) => {
146 if let Some(num) = num.as_u64() {
147 return Value::U64(num);
148 }
149
150 if let Some(num) = num.as_i64() {
151 return Value::I64(num);
152 }
153
154 if let Some(num) = num.as_f64() {
157 return Value::F64(num);
158 }
159
160 Value::Null
161 }
162 ValueRef::Array(arr) => {
163 let mut vec = Vec::with_capacity(arr.len());
164 vec.extend(arr.iter().map(|v| Value::from(v.as_ref())));
165 Value::Array(vec)
166 }
167 ValueRef::Object(obj) => {
168 let mut vec = Vec::with_capacity(obj.len());
169 vec.extend(obj.iter().map(|(k, v)| (k, Value::from(v.as_ref()))));
170 vec.sort_unstable_by_key(|(k, _)| *k);
171 Value::Object(vec)
172 }
173 }
174 }
175
176 pub fn as_object(&self) -> Option<&Vec<(&'a str, Value<'a>)>> {
177 match self {
178 Value::Object(obj) => Some(obj),
179 _ => None,
180 }
181 }
182
183 pub fn as_str(&self) -> Option<&str> {
184 match self {
185 Value::String(s) => Some(s),
186 _ => None,
187 }
188 }
189
190 pub fn is_null(&self) -> bool {
191 matches!(self, Value::Null)
192 }
193
194 pub fn is_object(&self) -> bool {
195 matches!(self, Value::Object(_))
196 }
197}
198
199pub trait ValueRefExt {
201 fn to_data<'a>(&'a self) -> Option<ValueRef<'a>>;
202 fn to_entities<'a>(&'a self) -> Option<Vec<ValueRef<'a>>>;
203}
204
205impl ValueRefExt for ValueRef<'_> {
207 fn to_data<'a>(&'a self) -> Option<ValueRef<'a>> {
208 match self {
209 ValueRef::Object(obj) => obj.get(&"data").map(|v| v.as_ref()),
210 _ => None,
211 }
212 }
213
214 fn to_entities<'a>(&'a self) -> Option<Vec<ValueRef<'a>>> {
215 match self.to_data().unwrap() {
216 ValueRef::Object(obj) => obj.get(&"_entities").and_then(|v| match v.as_ref() {
217 ValueRef::Array(arr) => Some(arr.iter().map(|v| v.as_ref()).collect()),
218 _ => None,
219 }),
220 _ => None,
221 }
222 }
223}
224
225impl Display for Value<'_> {
226 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
227 match self {
228 Value::Null => write!(f, "null"),
229 Value::Bool(b) => write!(f, "{}", b),
230 Value::String(s) => write!(f, "\"{}\"", s),
231 Value::F64(n) => write!(f, "{}", n),
232 Value::U64(n) => write!(f, "{}", n),
233 Value::I64(n) => write!(f, "{}", n),
234 Value::Array(arr) => {
235 write!(f, "[")?;
236 for (i, v) in arr.iter().enumerate() {
237 if i > 0 {
238 write!(f, ", ")?;
239 }
240 write!(f, "{}", v)?;
241 }
242 write!(f, "]")
243 }
244 Value::Object(obj) => {
245 write!(f, "{{")?;
246 for (i, (k, v)) in obj.iter().enumerate() {
247 if i > 0 {
248 write!(f, ", ")?;
249 }
250 write!(f, "\"{}\": {}", k, v)?;
251 }
252 write!(f, "}}")
253 }
254 }
255 }
256}
257
258struct ValueVisitor<'a> {
259 _marker: std::marker::PhantomData<&'a ()>,
261}
262
263impl<'de> de::Deserialize<'de> for Value<'de> {
264 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
265 where
266 D: Deserializer<'de>,
267 {
268 deserializer.deserialize_any(ValueVisitor {
269 _marker: std::marker::PhantomData,
270 })
271 }
272}
273
274impl<'de> Visitor<'de> for ValueVisitor<'de> {
275 type Value = Value<'de>;
276
277 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
278 formatter.write_str("any valid JSON value")
279 }
280
281 fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E> {
282 Ok(Value::Bool(value))
283 }
284
285 fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E> {
286 Ok(Value::I64(value))
287 }
288
289 fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E> {
290 Ok(Value::U64(value))
291 }
292
293 fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E> {
294 Ok(Value::F64(value))
295 }
296
297 fn visit_borrowed_str<E>(self, value: &'de str) -> Result<Self::Value, E>
299 where
300 E: de::Error,
301 {
302 Ok(Value::String(value.into()))
303 }
304
305 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
306 where
307 E: de::Error,
308 {
309 Ok(Value::String(v.to_owned().into()))
310 }
311
312 fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
313 where
314 E: de::Error,
315 {
316 Ok(Value::String(value.into()))
317 }
318
319 fn visit_unit<E>(self) -> Result<Self::Value, E> {
320 Ok(Value::Null)
321 }
322
323 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
325 where
326 A: SeqAccess<'de>,
327 {
328 let mut elements = Vec::with_capacity(seq.size_hint().unwrap_or(0));
329 while let Some(elem) = seq.next_element()? {
330 elements.push(elem);
331 }
332 Ok(Value::Array(elements))
333 }
334
335 fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
337 where
338 M: MapAccess<'de>,
339 {
340 let mut entries = Vec::with_capacity(map.size_hint().unwrap_or(0));
341 while let Some((key, value)) = map.next_entry()? {
342 entries.push((key, value));
343 }
344 entries.sort_unstable_by_key(|(k, _)| *k);
346 Ok(Value::Object(entries))
347 }
348}
349
350impl serde::Serialize for Value<'_> {
351 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
352 where
353 S: serde::Serializer,
354 {
355 match self {
356 Value::Null => serializer.serialize_unit(),
357 Value::Bool(b) => serializer.serialize_bool(*b),
358 Value::I64(n) => serializer.serialize_i64(*n),
359 Value::U64(n) => serializer.serialize_u64(*n),
360 Value::F64(n) => serializer.serialize_f64(*n),
361 Value::String(s) => serializer.serialize_str(s),
362 Value::Array(arr) => {
363 let mut seq = serializer.serialize_seq(Some(arr.len()))?;
364 for v in arr {
365 seq.serialize_element(v)?;
366 }
367 seq.end()
368 }
369 Value::Object(obj) => {
370 let mut map = serializer.serialize_map(Some(obj.len()))?;
371 for (k, v) in obj {
372 map.serialize_entry(k, v)?;
373 }
374 map.end()
375 }
376 }
377 }
378}
379
380#[cfg(test)]
381mod tests {
382 use super::Value;
383 use serde::Deserialize;
384 use std::borrow::Cow;
385
386 #[test]
387 fn deserializes_escaped_string_as_owned() {
388 let bytes = br#"{"message": "hello\nworld"}"#;
389 let mut deserializer = sonic_rs::Deserializer::from_slice(bytes);
390
391 let value = Value::deserialize(&mut deserializer).unwrap();
392
393 let obj = match value {
394 Value::Object(obj) => obj,
395 _ => panic!("Expected Value::Object"),
396 };
397
398 let message_value = &obj.iter().find(|(k, _)| *k == "message").unwrap().1;
399
400 match message_value {
401 Value::String(value) => {
402 assert_eq!(value, "hello\nworld");
403 assert!(
404 matches!(value, Cow::Owned(_)),
405 "Expected Cow::Owned for escaped string"
406 );
407 }
408 _ => panic!("Expected Value::String"),
409 }
410 }
411
412 #[test]
413 fn deserializes_simple_string_as_borrowed() {
414 let bytes = br#"{"message": "hello world"}"#;
415 let mut deserializer = sonic_rs::Deserializer::from_slice(bytes);
416 let value = Value::deserialize(&mut deserializer).unwrap();
417
418 let obj = match value {
419 Value::Object(obj) => obj,
420 _ => panic!("Expected Value::Object"),
421 };
422
423 let message_value = &obj.iter().find(|(k, _)| *k == "message").unwrap().1;
424
425 match message_value {
426 Value::String(value) => {
427 assert_eq!(value, "hello world");
428 assert!(
429 matches!(value, Cow::Borrowed(_)),
430 "Expected Cow::Borrowed for simple string"
431 );
432 }
433 _ => panic!("Expected Value::String"),
434 }
435 }
436}