wasmer_types/
memory.rs

1use crate::{Pages, ValueType};
2use core::ops::SubAssign;
3use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
4#[cfg(feature = "enable-serde")]
5use serde::{Deserialize, Serialize};
6use std::convert::{TryFrom, TryInto};
7use std::iter::Sum;
8use std::ops::{Add, AddAssign};
9
10/// Implementation styles for WebAssembly linear memory.
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, RkyvSerialize, RkyvDeserialize, Archive)]
12#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
13#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
14#[rkyv(derive(Debug), compare(PartialEq))]
15#[repr(u8)]
16pub enum MemoryStyle {
17    /// The actual memory can be resized and moved.
18    Dynamic {
19        /// Our chosen offset-guard size.
20        ///
21        /// It represents the size in bytes of extra guard pages after the end
22        /// to optimize loads and stores with constant offsets.
23        offset_guard_size: u64,
24    },
25    /// Address space is allocated up front.
26    Static {
27        /// The number of mapped and unmapped pages.
28        bound: Pages,
29        /// Our chosen offset-guard size.
30        ///
31        /// It represents the size in bytes of extra guard pages after the end
32        /// to optimize loads and stores with constant offsets.
33        offset_guard_size: u64,
34    },
35}
36
37impl MemoryStyle {
38    /// Returns the offset-guard size
39    pub fn offset_guard_size(&self) -> u64 {
40        match self {
41            Self::Dynamic { offset_guard_size } => *offset_guard_size,
42            Self::Static {
43                offset_guard_size, ..
44            } => *offset_guard_size,
45        }
46    }
47}
48
49/// Trait for the `Memory32` and `Memory64` marker types.
50///
51/// This allows code to be generic over 32-bit and 64-bit memories.
52/// # Safety
53/// Direct memory access is unsafe
54pub unsafe trait MemorySize: Copy {
55    /// Type used to represent an offset into a memory. This is `u32` or `u64`.
56    type Offset: Default
57        + std::fmt::Debug
58        + std::fmt::Display
59        + Eq
60        + Ord
61        + PartialEq<Self::Offset>
62        + PartialOrd<Self::Offset>
63        + Clone
64        + Copy
65        + Sync
66        + Send
67        + ValueType
68        + Into<u64>
69        + From<u32>
70        + From<u16>
71        + From<u8>
72        + TryFrom<u64>
73        + TryFrom<u32>
74        + TryFrom<u16>
75        + TryFrom<u8>
76        + TryFrom<i32>
77        + TryInto<usize>
78        + TryInto<u64>
79        + TryInto<u32>
80        + TryInto<u16>
81        + TryInto<u8>
82        + TryInto<i32>
83        + TryFrom<usize>
84        + Add<Self::Offset>
85        + Sum<Self::Offset>
86        + AddAssign<Self::Offset>
87        + SubAssign<Self::Offset>
88        + 'static;
89
90    /// Type used to pass this value as an argument or return value for a Wasm function.
91    type Native: super::NativeWasmType;
92
93    /// Zero value used for `WasmPtr::is_null`.
94    const ZERO: Self::Offset;
95
96    /// One value used for counting.
97    const ONE: Self::Offset;
98
99    /// Convert an `Offset` to a `Native`.
100    fn offset_to_native(offset: Self::Offset) -> Self::Native;
101
102    /// Convert a `Native` to an `Offset`.
103    fn native_to_offset(native: Self::Native) -> Self::Offset;
104
105    /// True if the memory is 64-bit
106    fn is_64bit() -> bool;
107}
108
109/// Marker trait for 32-bit memories.
110#[derive(Clone, Copy)]
111pub struct Memory32;
112unsafe impl MemorySize for Memory32 {
113    type Offset = u32;
114    type Native = i32;
115    const ZERO: Self::Offset = 0;
116    const ONE: Self::Offset = 1;
117    fn offset_to_native(offset: Self::Offset) -> Self::Native {
118        offset as Self::Native
119    }
120    fn native_to_offset(native: Self::Native) -> Self::Offset {
121        native as Self::Offset
122    }
123    fn is_64bit() -> bool {
124        false
125    }
126}
127
128/// Marker trait for 64-bit memories.
129#[derive(Clone, Copy)]
130pub struct Memory64;
131unsafe impl MemorySize for Memory64 {
132    type Offset = u64;
133    type Native = i64;
134    const ZERO: Self::Offset = 0;
135    const ONE: Self::Offset = 1;
136    fn offset_to_native(offset: Self::Offset) -> Self::Native {
137        offset as Self::Native
138    }
139    fn native_to_offset(native: Self::Native) -> Self::Offset {
140        native as Self::Offset
141    }
142    fn is_64bit() -> bool {
143        true
144    }
145}