1use std::{fmt::Debug, ops::Deref};
2
3use serde::{Deserialize, Serialize};
4
5use crate::{
6 constants::{MAX_SOLIDITY_MAPPING_KEYS, MAX_SUBQUERY_INPUTS, MAX_SUBQUERY_OUTPUTS},
7 Field, HiLo,
8};
9
10use super::native::SubqueryType;
11
12pub const SUBQUERY_KEY_LEN: usize = 1 + MAX_SUBQUERY_INPUTS;
13pub const SUBQUERY_RESULT_LEN: usize = SUBQUERY_KEY_LEN + MAX_SUBQUERY_OUTPUTS;
14
15#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, Serialize, Deserialize)]
17pub struct SubqueryKey<T>(pub [T; SUBQUERY_KEY_LEN]);
18
19#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, Serialize, Deserialize)]
21pub struct SubqueryOutput<T>(pub [T; MAX_SUBQUERY_OUTPUTS]);
22
23impl<T> Deref for SubqueryKey<T> {
24 type Target = [T];
25 fn deref(&self) -> &Self::Target {
26 &self.0
27 }
28}
29
30impl<T> Deref for SubqueryOutput<T> {
31 type Target = [T];
32 fn deref(&self) -> &Self::Target {
33 &self.0
34 }
35}
36
37#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, Serialize, Deserialize)]
38pub struct FlattenedSubqueryResult<T> {
39 pub key: SubqueryKey<T>,
40 pub value: SubqueryOutput<T>,
41}
42
43impl<T> FlattenedSubqueryResult<T> {
44 pub fn new(key: SubqueryKey<T>, value: SubqueryOutput<T>) -> Self {
45 Self { key, value }
46 }
47}
48
49impl<T: Clone> FlattenedSubqueryResult<T> {
50 pub fn flatten(&self) -> [T; SUBQUERY_RESULT_LEN] {
51 self.to_fixed_array()
52 }
53
54 pub fn to_fixed_array(&self) -> [T; SUBQUERY_RESULT_LEN] {
55 [&self.key.0[..], &self.value.0[..]].concat().try_into().unwrap_or_else(|_| unreachable!())
56 }
57}
58
59#[derive(Clone, Copy, Debug)]
61pub struct FieldSubqueryResult<F: Field> {
62 pub subquery: FieldSubquery<F>,
63 pub value: SubqueryOutput<F>,
64}
65
66impl<F: Field> FieldSubqueryResult<F> {
67 pub fn flatten(self) -> FlattenedSubqueryResult<F> {
68 FlattenedSubqueryResult { key: self.subquery.flatten(), value: self.value }
69 }
70 pub fn to_fixed_array(self) -> [F; SUBQUERY_RESULT_LEN] {
71 self.flatten().to_fixed_array()
72 }
73}
74
75impl<F: Field> From<FieldSubqueryResult<F>> for FlattenedSubqueryResult<F> {
76 fn from(value: FieldSubqueryResult<F>) -> Self {
77 value.flatten()
78 }
79}
80
81impl<F: Field> From<FieldSubquery<F>> for SubqueryKey<F> {
82 fn from(subquery: FieldSubquery<F>) -> Self {
83 let mut key = [F::ZERO; 1 + MAX_SUBQUERY_INPUTS];
84 key[0] = F::from(subquery.subquery_type as u64);
85 key[1..].copy_from_slice(&subquery.encoded_subquery_data);
86 Self(key)
87 }
88}
89
90#[derive(Clone, Copy, Debug)]
93pub struct FieldSubquery<T> {
94 pub subquery_type: SubqueryType,
95 pub encoded_subquery_data: [T; MAX_SUBQUERY_INPUTS],
96}
97
98impl<F: Field> FieldSubquery<F> {
99 pub fn flatten(&self) -> SubqueryKey<F> {
100 let mut key = [F::ZERO; SUBQUERY_KEY_LEN];
101 key[0] = F::from(self.subquery_type as u64);
102 key[1..].copy_from_slice(&self.encoded_subquery_data);
103 SubqueryKey(key)
104 }
105}
106
107#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Default)]
109pub struct FieldHeaderSubquery<T> {
110 pub block_number: T,
111 pub field_idx: T,
112}
113
114#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Default)]
115pub struct FieldAccountSubquery<T> {
116 pub block_number: T,
117 pub addr: T, pub field_idx: T,
119}
120
121#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Default)]
122pub struct FieldStorageSubquery<T> {
123 pub block_number: T,
124 pub addr: T, pub slot: HiLo<T>,
126}
127
128#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Default)]
129pub struct FieldTxSubquery<T> {
130 pub block_number: T,
131 pub tx_idx: T,
132 pub field_or_calldata_idx: T,
133}
134
135#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Default)]
136pub struct FieldReceiptSubquery<T> {
137 pub block_number: T,
138 pub tx_idx: T,
139 pub field_or_log_idx: T,
140 pub topic_or_data_or_address_idx: T,
141 pub event_schema: HiLo<T>,
142}
143
144#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Default)]
145pub struct FieldSolidityNestedMappingSubquery<T> {
146 pub block_number: T,
147 pub addr: T, pub mapping_slot: HiLo<T>,
149 pub mapping_depth: T,
150 pub keys: [HiLo<T>; MAX_SOLIDITY_MAPPING_KEYS],
151}
152
153#[derive(Clone, Copy, Debug, Hash, Serialize, Deserialize, PartialEq, Eq)]
156pub struct AnySubqueryResult<S, T> {
157 pub subquery: S,
158 pub value: T,
159}
160
161impl<S, T> AnySubqueryResult<S, T> {
162 pub fn new(subquery: S, value: T) -> Self {
163 Self { subquery, value }
164 }
165}
166
167pub type FieldHeaderSubqueryResult<T> = AnySubqueryResult<FieldHeaderSubquery<T>, HiLo<T>>;
168pub type FieldAccountSubqueryResult<T> = AnySubqueryResult<FieldAccountSubquery<T>, HiLo<T>>;
169pub type FieldStorageSubqueryResult<T> = AnySubqueryResult<FieldStorageSubquery<T>, HiLo<T>>;
170pub type FieldTxSubqueryResult<T> = AnySubqueryResult<FieldTxSubquery<T>, HiLo<T>>;
171pub type FieldReceiptSubqueryResult<T> = AnySubqueryResult<FieldReceiptSubquery<T>, HiLo<T>>;
172pub type FieldSolidityNestedMappingSubqueryResult<T> =
173 AnySubqueryResult<FieldSolidityNestedMappingSubquery<T>, HiLo<T>>;