it_lilo/lifter/
memory_reader.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::LiResult;
18use crate::read_array_ty;
19use crate::read_ty;
20use crate::IValue;
21
22use it_memory_traits::MemoryView;
23
24use std::cell::Cell;
25use std::marker::PhantomData;
26
27pub struct MemoryReader<MV: MemoryView<Store>, Store: it_memory_traits::Store> {
28    pub(self) view: MV,
29    _phantom: PhantomData<Store>,
30}
31
32impl<MV: MemoryView<Store>, Store: it_memory_traits::Store> MemoryReader<MV, Store> {
33    pub fn new(view: MV) -> Self {
34        Self {
35            view,
36            _phantom: PhantomData,
37        }
38    }
39
40    /// Returns reader that allows read sequentially. It's important that memory limit is checked
41    /// only inside this function. All others functions of the returned reader don't have any
42    /// checks assuming that reader is well-formed.
43    pub fn sequential_reader(
44        &self,
45        store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
46        offset: u32,
47        size: u32,
48    ) -> LiResult<SequentialReader<'_, MV, Store>> {
49        self.view.check_bounds(store, offset, size)?;
50        let seq_reader = SequentialReader::new(&self, offset);
51        Ok(seq_reader)
52    }
53
54    pub fn read_raw_u8_array(
55        &self,
56        store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
57        offset: u32,
58        elements_count: u32,
59    ) -> LiResult<Vec<u8>> {
60        let reader = self.sequential_reader(store, offset, elements_count)?;
61        let mut result = Vec::with_capacity(elements_count as usize);
62
63        for _ in 0..elements_count {
64            let value = reader.read_u8(store);
65            result.push(value);
66        }
67
68        Ok(result)
69    }
70
71    pub fn read_bool_array(
72        &self,
73        store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
74        offset: u32,
75        elements_count: u32,
76    ) -> LiResult<Vec<IValue>> {
77        let reader = self.sequential_reader(store, offset, elements_count)?;
78        let mut result = Vec::with_capacity(elements_count as usize);
79
80        for _ in 0..elements_count {
81            let value = reader.read_u8(store);
82            result.push(IValue::Boolean(value != 0));
83        }
84
85        Ok(result)
86    }
87
88    read_array_ty!(read_u8_array, u8, U8);
89    read_array_ty!(read_s8_array, i8, S8);
90    read_array_ty!(read_u16_array, u16, U16);
91    read_array_ty!(read_s16_array, i16, S16);
92    read_array_ty!(read_u32_array, u32, U32);
93    read_array_ty!(read_s32_array, i32, S32);
94    read_array_ty!(read_i32_array, i32, I32);
95    read_array_ty!(read_f32_array, f32, F32);
96    read_array_ty!(read_u64_array, u64, U64);
97    read_array_ty!(read_s64_array, i64, S64);
98    read_array_ty!(read_i64_array, i64, I64);
99    read_array_ty!(read_f64_array, f64, F64);
100}
101
102pub struct SequentialReader<'r, MV: MemoryView<Store>, Store: it_memory_traits::Store> {
103    reader: &'r MemoryReader<MV, Store>,
104    offset: Cell<u32>,
105}
106
107impl<'r, MV: MemoryView<Store>, Store: it_memory_traits::Store> SequentialReader<'r, MV, Store> {
108    fn new(reader: &'r MemoryReader<MV, Store>, offset: u32) -> Self {
109        Self {
110            reader,
111            offset: Cell::new(offset),
112        }
113    }
114
115    pub fn read_bool(
116        &self,
117        store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
118    ) -> bool {
119        self.read_u8(store) != 0
120    }
121
122    read_ty!(read_u8, u8, 1);
123    read_ty!(read_i8, i8, 1);
124    read_ty!(read_u16, u16, 2);
125    read_ty!(read_i16, i16, 2);
126    read_ty!(read_u32, u32, 4);
127    read_ty!(read_i32, i32, 4);
128    read_ty!(read_f32, f32, 4);
129    read_ty!(read_u64, u64, 8);
130    read_ty!(read_i64, i64, 8);
131    read_ty!(read_f64, f64, 8);
132}