1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
use solana_program::pubkey::Pubkey;
use crate::constants::{BUCKETS_COUNT, VANILLA_COST_SIZE, VANILLA_MEMO_SIZE};
pub const POOLS_LOG_ID_OFFSET: usize = 0;
pub const POOLS_LOG_TIME_OFFSET: usize = 8;
pub const POOLS_LOG_EVENT_TYPE_OFFSET: usize = 16;
pub const POOLS_LOG_FRACTIONS_OFFSET: usize = 20;
pub const POOLS_LOG_TASK_ID_OFFSET: usize = 24;
pub const POOLS_LOG_POOL_ID_OFFSET: usize = 28;
pub const POOLS_LOG_INSTR_ID_OFFSET: usize = 32;
pub const POOLS_LOG_COUNTER_OFFSET: usize = 36;
pub const POOLS_LOG_PUBKEY_OFFSET: usize = 44;
pub const POOLS_LOG_COST_OFFSET: usize = 76;
pub const POOLS_LOG_PX_OFFSET: usize = 84;
pub const POOLS_LOG_QTY_OFFSET: usize = 844;
pub const POOLS_LOG_VANILLA_MEMO_OFFSET: usize = 1224;
pub const POOLS_LOG_VANILLA_COST_OFFSET: usize = 1273;
pub const POOLS_LOG_SIZE: usize = 1305;

#[repr(C)]
#[derive(Clone, Copy)]
pub struct PoolsLog {
    // 8 bytes, POOLS_LOG_ID_OFFSET
    pub id: [u8; 8],
    // 8 bytes, POOLS_LOG_TIME_OFFSET
    pub time: [u8; 8],
    // 4 bytes, POOLS_LOG_EVENT_TYPE_OFFSET
    pub event_type: [u8; 4],
    // 4 bytes, POOLS_LOG_FRACTIONS_OFFSET
    pub fractions: [u8; 4],
    // 4 bytes, POOLS_LOG_TASK_ID_OFFSET
    pub task_id: [u8; 4],
    // 4 bytes, POOLS_LOG_POOL_ID_OFFSET
    pub pool_id: [u8; 4],
    // 4 bytes, POOLS_LOG_INSTR_ID_OFFSET
    pub instr_id: [u8; 4],
    // 8 bytes, POOLS_LOG_COUNTER_OFFSET
    pub counter: [u8; 8],
    // 32 bytes, POOLS_LOG_PUBKEY_OFFSET
    pub pubkey: Pubkey,
    // 8 bytes, POOLS_LOG_COST_OFFSET
    pub cost: [u8; 8],
    // 760 bytes, POOLS_LOG_PX_OFFSET
    pub px: [[u8; 8]; BUCKETS_COUNT],
    // 380 bytes, POOLS_LOG_QTY_OFFSET
    pub qty: [[u8; 4]; BUCKETS_COUNT],
    // 49 bytes, POOLS_LOG_VANILLA_MEMO_OFFSET
    pub vanilla_memo: [u8; VANILLA_MEMO_SIZE],
    // 32 bytes, POOLS_LOG_VANILLA_COST_OFFSET
    pub vanilla_cost: [[u8; 8]; VANILLA_COST_SIZE],
}

impl PoolsLog {
    #[inline(always)]
    pub fn get_id(&self) -> i64 {
        i64::from_ne_bytes(self.id)
    }

    #[inline(always)]
    pub fn set_id(&mut self, value: i64) {
        self.id = value.to_ne_bytes();
    }

    #[inline(always)]
    pub fn get_time(&self) -> i64 {
        i64::from_ne_bytes(self.time)
    }

    #[inline(always)]
    pub fn set_time(&mut self, value: i64) {
        self.time = value.to_ne_bytes();
    }

    #[inline(always)]
    pub fn get_event_type(&self) -> u32 {
        u32::from_ne_bytes(self.event_type)
    }

    #[inline(always)]
    pub fn set_event_type(&mut self, value: u32) {
        self.event_type = value.to_ne_bytes();
    }

    #[inline(always)]
    pub fn get_fractions(&self) -> u32 {
        u32::from_ne_bytes(self.fractions)
    }

    #[inline(always)]
    pub fn set_fractions(&mut self, value: u32) {
        self.fractions = value.to_ne_bytes();
    }

    #[inline(always)]
    pub fn get_task_id(&self) -> u32 {
        u32::from_ne_bytes(self.task_id)
    }

    #[inline(always)]
    pub fn set_task_id(&mut self, value: u32) {
        self.task_id = value.to_ne_bytes();
    }

    #[inline(always)]
    pub fn get_pool_id(&self) -> u32 {
        u32::from_ne_bytes(self.pool_id)
    }

    #[inline(always)]
    pub fn set_pool_id(&mut self, value: u32) {
        self.pool_id = value.to_ne_bytes();
    }

    #[inline(always)]
    pub fn get_instr_id(&self) -> u32 {
        u32::from_ne_bytes(self.instr_id)
    }

    #[inline(always)]
    pub fn set_instr_id(&mut self, value: u32) {
        self.instr_id = value.to_ne_bytes();
    }

    #[inline(always)]
    pub fn get_counter(&self) -> u64 {
        u64::from_ne_bytes(self.counter)
    }

    #[inline(always)]
    pub fn set_counter(&mut self, value: u64) {
        self.counter = value.to_ne_bytes();
    }

    #[inline(always)]
    pub fn get_cost(&self) -> i64 {
        i64::from_ne_bytes(self.cost)
    }

    #[inline(always)]
    pub fn set_cost(&mut self, value: i64) {
        self.cost = value.to_ne_bytes();
    }

    #[inline(always)]
    pub fn get_px(&self, index: usize) -> i64 {
        i64::from_ne_bytes(self.px[index])
    }

    #[inline(always)]
    pub fn set_px(&mut self, index: usize, value: i64) {
        self.px[index] = value.to_ne_bytes();
    }

    #[inline(always)]
    pub fn set_qty(&mut self, index: usize, value: i32) {
        self.qty[index] = value.to_ne_bytes();
    }

    #[inline(always)]
    pub fn get_qty(&self, index: usize) -> i32 {
        i32::from_ne_bytes(self.qty[index])
    }

    #[inline(always)]
    pub fn get_vanilla_cost(&self, index: usize) -> i64 {
        i64::from_ne_bytes(self.vanilla_cost[index])
    }

    #[inline(always)]
    pub fn set_vanilla_cost(&mut self, index: usize, value: i64) {
        self.vanilla_cost[index] = value.to_ne_bytes();
    }
}

#[cfg(test)]
impl Default for PoolsLog {
    fn default() -> Self {
        Self {
            id: [0; 8],
            time: [0; 8],
            event_type: [0; 4],
            fractions: [0; 4],
            task_id: [0; 4],
            pool_id: [0; 4],
            instr_id: [0; 4],
            counter: [0; 8],
            pubkey: Pubkey::default(),
            cost: [0; 8],
            px: [[0; 8]; BUCKETS_COUNT],
            qty: [[0; 4]; BUCKETS_COUNT],
            vanilla_memo: [0; VANILLA_MEMO_SIZE],
            vanilla_cost: [[0; 8]; VANILLA_COST_SIZE],
        }
    }
}

#[cfg(test)]
mod tests {
    use std::mem;
    use super::*;

    #[test]
    fn test_pools_log_offsets() {
        let log = PoolsLog::default();
        let base_ptr = &log as *const _ as usize;

        // checking fields size and offset
        assert_eq!(
            &log.id as *const _ as usize - base_ptr,
            POOLS_LOG_ID_OFFSET
        );
        assert_eq!(
            &log.time as *const _ as usize - base_ptr,
            POOLS_LOG_TIME_OFFSET
        );
        assert_eq!(
            &log.event_type as *const _ as usize - base_ptr,
            POOLS_LOG_EVENT_TYPE_OFFSET
        );
        assert_eq!(
            &log.fractions as *const _ as usize - base_ptr,
            POOLS_LOG_FRACTIONS_OFFSET
        );
        assert_eq!(
            &log.task_id as *const _ as usize - base_ptr,
            POOLS_LOG_TASK_ID_OFFSET
        );
        assert_eq!(
            &log.pool_id as *const _ as usize - base_ptr,
            POOLS_LOG_POOL_ID_OFFSET
        );
        assert_eq!(
            &log.instr_id as *const _ as usize - base_ptr,
            POOLS_LOG_INSTR_ID_OFFSET
        );
        assert_eq!(
            &log.counter as *const _ as usize - base_ptr,
            POOLS_LOG_COUNTER_OFFSET
        );
        assert_eq!(
            &log.pubkey as *const _ as usize - base_ptr,
            POOLS_LOG_PUBKEY_OFFSET
        );
        assert_eq!(
            &log.cost as *const _ as usize - base_ptr,
            POOLS_LOG_COST_OFFSET
        );
        assert_eq!(
            &log.px as *const _ as usize - base_ptr,
            POOLS_LOG_PX_OFFSET
        );
        assert_eq!(
            &log.qty as *const _ as usize - base_ptr,
            POOLS_LOG_QTY_OFFSET
        );
        assert_eq!(
            &log.vanilla_memo as *const _ as usize - base_ptr,
            POOLS_LOG_VANILLA_MEMO_OFFSET
        );
        assert_eq!(
            &log.vanilla_cost as *const _ as usize - base_ptr,
            POOLS_LOG_VANILLA_COST_OFFSET
        );

        // checking total size
        assert_eq!(mem::size_of::<PoolsLog>(), POOLS_LOG_SIZE);
    }
}