it_lilo/lowerer/
lower_array.rs

1/*
2 * Copyright 2021 Fluence Labs Limited
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use super::ILowerer;
18use super::LoResult;
19use crate::traits::Allocatable;
20use crate::utils::ser_value_size;
21use crate::utils::type_tag_form_ivalue;
22use crate::IValue;
23
24use it_memory_traits::MemoryView;
25
26pub struct LoweredArray {
27    pub offset: u32,
28    pub size: u32,
29}
30
31impl LoweredArray {
32    pub fn new(offset: u32, size: u32) -> Self {
33        Self { offset, size }
34    }
35
36    pub fn empty() -> Self {
37        Self { offset: 0, size: 0 }
38    }
39}
40
41#[async_recursion::async_recursion]
42pub async fn array_lower_memory<
43    A: Allocatable<MV, Store>,
44    MV: MemoryView<Store>,
45    Store: it_memory_traits::Store,
46>(
47    store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
48    lowerer: &mut ILowerer<'_, A, MV, Store>,
49    array_values: Vec<IValue>,
50) -> LoResult<LoweredArray> {
51    if array_values.is_empty() {
52        return Ok(LoweredArray::empty());
53    }
54
55    let elements_count = array_values.len() as u32;
56    let size = ser_value_size(&array_values[0]) * elements_count;
57    let type_tag = type_tag_form_ivalue(&array_values[0]);
58    let seq_writer = lowerer
59        .writer
60        .sequential_writer(store, size, type_tag)
61        .await?;
62
63    // here it's known that all interface values have the same type
64    for value in array_values {
65        match value {
66            IValue::Boolean(value) => seq_writer.write_u8(store, &lowerer.writer, value as _),
67            IValue::S8(value) => seq_writer.write_u8(store, &lowerer.writer, value as _),
68            IValue::S16(value) => {
69                seq_writer.write_bytes(store, &lowerer.writer, &value.to_le_bytes())
70            }
71            IValue::S32(value) => {
72                seq_writer.write_bytes(store, &lowerer.writer, &value.to_le_bytes())
73            }
74            IValue::S64(value) => {
75                seq_writer.write_bytes(store, &lowerer.writer, &value.to_le_bytes())
76            }
77            IValue::U8(value) => {
78                seq_writer.write_bytes(store, &lowerer.writer, &value.to_le_bytes())
79            }
80            IValue::U16(value) => {
81                seq_writer.write_bytes(store, &lowerer.writer, &value.to_le_bytes())
82            }
83            IValue::U32(value) => {
84                seq_writer.write_bytes(store, &lowerer.writer, &value.to_le_bytes())
85            }
86            IValue::U64(value) => {
87                seq_writer.write_bytes(store, &lowerer.writer, &value.to_le_bytes())
88            }
89            IValue::I32(value) => {
90                seq_writer.write_bytes(store, &lowerer.writer, &value.to_le_bytes())
91            }
92            IValue::I64(value) => {
93                seq_writer.write_bytes(store, &lowerer.writer, &value.to_le_bytes())
94            }
95            IValue::F32(value) => {
96                seq_writer.write_bytes(store, &lowerer.writer, &value.to_le_bytes())
97            }
98            IValue::F64(value) => {
99                seq_writer.write_bytes(store, &lowerer.writer, &value.to_le_bytes())
100            }
101            IValue::String(value) => {
102                let offset = lowerer.writer.write_bytes(store, &value.as_bytes()).await? as u32;
103
104                seq_writer.write_bytes(store, &lowerer.writer, &offset.to_le_bytes());
105                seq_writer.write_bytes(store, &lowerer.writer, &(value.len() as u32).to_le_bytes());
106            }
107            IValue::ByteArray(values) => {
108                let offset = lowerer.writer.write_bytes(store, &values).await? as u32;
109
110                seq_writer.write_bytes(store, &lowerer.writer, &offset.to_le_bytes());
111                seq_writer.write_bytes(
112                    store,
113                    &lowerer.writer,
114                    &(values.len() as u32).to_le_bytes(),
115                );
116            }
117            IValue::Array(values) => {
118                let LoweredArray { offset, size } =
119                    array_lower_memory(store, lowerer, values).await?;
120
121                seq_writer.write_bytes(store, &lowerer.writer, &(offset as u32).to_le_bytes());
122                seq_writer.write_bytes(store, &lowerer.writer, &(size as u32).to_le_bytes());
123            }
124            IValue::Record(values) => {
125                let offset = super::record_lower_memory(store, lowerer, values).await? as u32;
126                seq_writer.write_bytes(store, &lowerer.writer, &offset.to_le_bytes());
127            }
128        }
129    }
130
131    let offset = seq_writer.start_offset();
132    let lowered_array = LoweredArray::new(offset, elements_count);
133    Ok(lowered_array)
134}