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