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
/*
 * Copyright 2021 Fluence Labs Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use super::record_lift_memory;
use super::ILifter;
use super::LiResult;
use crate::traits::RecordResolvable;
use crate::utils::ser_type_size;
use crate::IType;
use crate::IValue;

use it_memory_traits::{SequentialMemoryView, SequentialReader};

pub fn array_lift_memory<R: RecordResolvable, MV: for<'a> SequentialMemoryView<'a>>(
    lifter: &ILifter<'_, R, MV>,
    value_type: &IType,
    offset: u32,
    elements_count: u32,
) -> LiResult<IValue> {
    if elements_count == 0 {
        return Ok(IValue::Array(vec![]));
    }

    let reader = &lifter.reader;

    let ivalues = match value_type {
        IType::Boolean => reader.read_bool_array(offset, elements_count)?,
        IType::S8 => reader.read_s8_array(offset, elements_count)?,
        IType::S16 => reader.read_s16_array(offset, elements_count)?,
        IType::S32 => reader.read_s32_array(offset, elements_count)?,
        IType::S64 => reader.read_s64_array(offset, elements_count)?,
        IType::I32 => reader.read_i32_array(offset, elements_count)?,
        IType::I64 => reader.read_i64_array(offset, elements_count)?,
        IType::U8 => reader.read_u8_array(offset, elements_count)?,
        IType::U16 => reader.read_u16_array(offset, elements_count)?,
        IType::U32 => reader.read_u32_array(offset, elements_count)?,
        IType::U64 => reader.read_u64_array(offset, elements_count)?,
        IType::F32 => reader.read_f32_array(offset, elements_count)?,
        IType::F64 => reader.read_f64_array(offset, elements_count)?,
        IType::String => read_string_array(lifter, offset, elements_count)?,
        IType::ByteArray => read_array_array(lifter, &IType::U8, offset, elements_count)?,
        IType::Array(ty) => read_array_array(lifter, &ty, offset, elements_count)?,
        IType::Record(record_type_id) => {
            read_record_array(lifter, *record_type_id, offset, elements_count)?
        }
    };

    Ok(IValue::Array(ivalues))
}

fn read_string_array<R: RecordResolvable, MV: for<'a> SequentialMemoryView<'a>>(
    lifter: &ILifter<'_, R, MV>,
    offset: u32,
    elements_count: u32,
) -> LiResult<Vec<IValue>> {
    let mut result = Vec::with_capacity(elements_count as usize);
    let seq_reader = lifter
        .reader
        .sequential_reader(offset, ser_type_size(&IType::String) * elements_count)?;

    for _ in 0..elements_count {
        let offset = seq_reader.read_u32();
        let size = seq_reader.read_u32();

        let raw_str = lifter.reader.read_raw_u8_array(offset, size)?;
        let str = String::from_utf8(raw_str)?;
        result.push(IValue::String(str));
    }

    Ok(result)
}

fn read_array_array<R: RecordResolvable, MV: for<'a> SequentialMemoryView<'a>>(
    lifter: &ILifter<'_, R, MV>,
    ty: &IType,
    offset: u32,
    elements_count: u32,
) -> LiResult<Vec<IValue>> {
    let mut result = Vec::with_capacity(elements_count as usize);
    let seq_reader = lifter
        .reader
        .sequential_reader(offset, ser_type_size(ty) * elements_count)?;

    for _ in 0..elements_count {
        let offset = seq_reader.read_u32();
        let size = seq_reader.read_u32();

        let array = array_lift_memory(lifter, ty, offset, size)?;
        result.push(array);
    }

    Ok(result)
}

fn read_record_array<R: RecordResolvable, MV: for<'a> SequentialMemoryView<'a>>(
    lifter: &ILifter<'_, R, MV>,
    record_type_id: u64,
    offset: u32,
    elements_count: u32,
) -> LiResult<Vec<IValue>> {
    let mut result = Vec::with_capacity(elements_count as usize);
    let seq_reader = lifter
        .reader
        .sequential_reader(offset, ser_type_size(&IType::Record(0)) * elements_count)?;

    for _ in 0..elements_count {
        let offset = seq_reader.read_u32();
        let record_ty = lifter.resolver.resolve_record(record_type_id)?;

        let record = record_lift_memory(lifter, &record_ty, offset)?;
        result.push(record);
    }

    Ok(result)
}