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
// Copyright (c) Zefchain Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

//! How to access the memory of a Wasmtime guest instance.

use std::borrow::Cow;

use wasmtime::{Extern, Memory};

use super::{super::traits::InstanceWithMemory, EntrypointInstance, ReentrantInstance};
use crate::{GuestPointer, RuntimeError, RuntimeMemory};

macro_rules! impl_memory_traits {
    ($instance:ty) => {
        impl<UserData> InstanceWithMemory for $instance {
            fn memory_from_export(&self, export: Extern) -> Result<Option<Memory>, RuntimeError> {
                Ok(match export {
                    Extern::Memory(memory) => Some(memory),
                    _ => None,
                })
            }
        }

        impl<UserData> RuntimeMemory<$instance> for Memory {
            fn read<'instance>(
                &self,
                instance: &'instance $instance,
                location: GuestPointer,
                length: u32,
            ) -> Result<Cow<'instance, [u8]>, RuntimeError> {
                let start = location.0 as usize;
                let end = start + length as usize;

                Ok(Cow::Borrowed(&self.data(instance)[start..end]))
            }

            fn write(
                &mut self,
                instance: &mut $instance,
                location: GuestPointer,
                bytes: &[u8],
            ) -> Result<(), RuntimeError> {
                let start = location.0 as usize;
                let end = start + bytes.len();

                self.data_mut(instance)[start..end].copy_from_slice(bytes);

                Ok(())
            }
        }
    };
}

impl_memory_traits!(EntrypointInstance<UserData>);
impl_memory_traits!(ReentrantInstance<'_, UserData>);