1
//! `Operation::Delete` entity record. No data payload — just an
2
//! entity header carrying the id of the row to remove. Runs after
3
//! a CRUD list is iterated, so the `entity_type` rides a wasm local
4
//! rather than being known at compile time.
5

            
6
use std::mem::offset_of;
7

            
8
use scripting_format::{ENTITY_HEADER_SIZE, EntityHeader, Operation};
9

            
10
use crate::compiler::emit::FunctionEmitter;
11
use crate::compiler::expr::LOCAL_ENTITY_BASE;
12

            
13
use super::headers::OutputSerializer;
14

            
15
impl OutputSerializer {
16
272
    pub fn write_delete_entity(
17
272
        &mut self,
18
272
        emit: &mut FunctionEmitter,
19
272
        entity_type_local: u32,
20
272
        input_header_local: u32,
21
272
    ) {
22
272
        self.load_entity_base(emit);
23
272
        let ent = LOCAL_ENTITY_BASE;
24

            
25
        // entity_type from a runtime local.
26
272
        emit.local_get(ent);
27
272
        emit.i32_const(offset_of!(EntityHeader, entity_type) as i32);
28
272
        emit.i32_add();
29
272
        emit.local_get(entity_type_local);
30
272
        emit.i32_store8_raw();
31

            
32
272
        emit.store_u8_dynamic(
33
272
            ent,
34
272
            offset_of!(EntityHeader, operation) as u32,
35
272
            Operation::Delete as u8,
36
        );
37
272
        emit.store_u8_dynamic(ent, offset_of!(EntityHeader, flags) as u32, 0);
38

            
39
        // Copy the 16-byte id from the input entity header.
40
1088
        for i in 0..4u32 {
41
1088
            emit.local_get(ent);
42
1088
            emit.i32_const((offset_of!(EntityHeader, id) as u32 + i * 4) as i32);
43
1088
            emit.i32_add();
44
1088
            emit.local_get(input_header_local);
45
1088
            emit.i32_load((offset_of!(EntityHeader, id) + (i as usize) * 4) as u64);
46
1088
            emit.i32_store_raw();
47
1088
        }
48

            
49
272
        emit.store_i32_dynamic(ent, offset_of!(EntityHeader, parent_idx) as u32, -1);
50

            
51
        // data_offset = (entity_base - output_base) + ENTITY_HEADER_SIZE.
52
272
        emit.local_get(ent);
53
272
        emit.i32_const(offset_of!(EntityHeader, data_offset) as i32);
54
272
        emit.i32_add();
55
272
        emit.local_get(ent);
56
272
        emit.local_get(self.output_base_local);
57
272
        emit.i32_sub();
58
272
        emit.i32_const(ENTITY_HEADER_SIZE as i32);
59
272
        emit.i32_add();
60
272
        emit.i32_store_raw();
61

            
62
272
        emit.store_i32_dynamic(ent, offset_of!(EntityHeader, data_size) as u32, 0);
63

            
64
272
        self.bump_entity_count(emit);
65
272
        self.advance_past(emit, ENTITY_HEADER_SIZE as u32);
66
272
    }
67
}