rune/runtime/unit/
storage.rs
1use core::fmt;
2use core::iter;
3use core::mem::size_of;
4use core::slice;
5
6use crate as rune;
7use crate::alloc::prelude::*;
8use crate::alloc::{self, Vec};
9
10#[cfg(feature = "byte-code")]
11use musli::storage;
12use serde::{Deserialize, Serialize};
13
14use crate::runtime::Inst;
15
16mod sealed {
17 pub trait Sealed {}
18
19 #[cfg(feature = "byte-code")]
20 impl Sealed for crate::runtime::unit::ByteCodeUnit {}
21 impl Sealed for crate::runtime::unit::ArrayUnit {}
22}
23
24pub trait UnitEncoder: self::sealed::Sealed {
26 #[doc(hidden)]
29 fn offset(&self) -> usize;
30
31 #[doc(hidden)]
33 fn encode(&mut self, inst: Inst) -> Result<(), EncodeError>;
34
35 #[doc(hidden)]
37 fn extend_offsets(&mut self, extra: usize) -> alloc::Result<usize>;
38
39 #[doc(hidden)]
41 fn mark_offset(&mut self, index: usize);
42
43 #[doc(hidden)]
45 fn label_jump(&self, base: usize, offset: usize, jump: usize) -> usize;
46}
47
48pub trait UnitStorage: self::sealed::Sealed + fmt::Debug + Default {
50 #[doc(hidden)]
52 type Iter<'this>: Iterator<Item = (usize, Inst)>
53 where
54 Self: 'this;
55
56 #[doc(hidden)]
59 fn end(&self) -> usize;
60
61 #[doc(hidden)]
63 fn bytes(&self) -> usize;
64
65 #[doc(hidden)]
67 fn iter(&self) -> Self::Iter<'_>;
68
69 #[doc(hidden)]
71 fn get(&self, ip: usize) -> Result<Option<(Inst, usize)>, BadInstruction>;
72
73 #[doc(hidden)]
75 fn translate(&self, jump: usize) -> Result<usize, BadJump>;
76}
77
78#[derive(Debug, TryClone, Default, Serialize, Deserialize)]
80pub struct ArrayUnit {
81 instructions: Vec<Inst>,
82}
83
84impl UnitEncoder for ArrayUnit {
85 #[inline]
86 fn offset(&self) -> usize {
87 self.instructions.len()
88 }
89
90 #[inline]
91 fn encode(&mut self, inst: Inst) -> Result<(), EncodeError> {
92 self.instructions.try_push(inst)?;
93 Ok(())
94 }
95
96 #[inline]
97 fn extend_offsets(&mut self, _: usize) -> alloc::Result<usize> {
98 Ok(self.instructions.len())
99 }
100
101 #[inline]
102 fn mark_offset(&mut self, _: usize) {}
103
104 #[inline]
105 fn label_jump(&self, base: usize, offset: usize, _: usize) -> usize {
106 base.wrapping_add(offset)
107 }
108}
109
110impl UnitStorage for ArrayUnit {
111 type Iter<'this> = iter::Enumerate<iter::Copied<slice::Iter<'this, Inst>>>;
112
113 #[inline]
114 fn end(&self) -> usize {
115 self.instructions.len()
116 }
117
118 #[inline]
119 fn bytes(&self) -> usize {
120 self.instructions.len().wrapping_mul(size_of::<Inst>())
121 }
122
123 #[inline]
124 fn iter(&self) -> Self::Iter<'_> {
125 self.instructions.iter().copied().enumerate()
126 }
127
128 #[inline]
129 fn get(&self, ip: usize) -> Result<Option<(Inst, usize)>, BadInstruction> {
130 let Some(inst) = self.instructions.get(ip) else {
131 return Ok(None);
132 };
133
134 Ok(Some((*inst, 1)))
135 }
136
137 #[inline]
138 fn translate(&self, jump: usize) -> Result<usize, BadJump> {
139 Ok(jump)
140 }
141}
142
143#[derive(Debug)]
145#[doc(hidden)]
146pub struct EncodeError {
147 kind: EncodeErrorKind,
148}
149
150#[cfg(feature = "byte-code")]
151impl From<storage::Error> for EncodeError {
152 #[inline]
153 fn from(error: storage::Error) -> Self {
154 Self {
155 kind: EncodeErrorKind::StorageError { error },
156 }
157 }
158}
159
160impl From<alloc::Error> for EncodeError {
161 #[inline]
162 fn from(error: alloc::Error) -> Self {
163 Self {
164 kind: EncodeErrorKind::AllocError { error },
165 }
166 }
167}
168
169impl fmt::Display for EncodeError {
170 #[inline]
171 fn fmt(
172 &self,
173 #[cfg_attr(not(feature = "byte-code"), allow(unused))] f: &mut fmt::Formatter<'_>,
174 ) -> fmt::Result {
175 match &self.kind {
176 #[cfg(feature = "byte-code")]
177 EncodeErrorKind::StorageError { .. } => write!(f, "Storage error"),
178 EncodeErrorKind::AllocError { error } => error.fmt(f),
179 }
180 }
181}
182
183impl core::error::Error for EncodeError {
184 #[inline]
185 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
186 match &self.kind {
187 #[cfg(all(feature = "byte-code", feature = "std"))]
188 EncodeErrorKind::StorageError { error } => Some(error),
189 _ => None,
190 }
191 }
192}
193
194#[derive(Debug)]
195enum EncodeErrorKind {
196 #[cfg(feature = "byte-code")]
197 StorageError {
198 #[cfg_attr(not(feature = "std"), allow(dead_code))]
199 error: storage::Error,
200 },
201 AllocError {
202 error: alloc::Error,
203 },
204}
205
206#[derive(Debug)]
209#[cfg_attr(test, derive(PartialEq))]
210pub struct BadInstruction {
211 pub(crate) ip: usize,
212}
213
214impl fmt::Display for BadInstruction {
215 #[inline]
216 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
217 write!(f, "Bad instruction at instruction {}", self.ip)
218 }
219}
220
221impl core::error::Error for BadInstruction {}
222
223#[derive(Debug)]
226#[cfg_attr(test, derive(PartialEq))]
227pub struct BadJump {
228 pub(crate) jump: usize,
229}
230
231impl fmt::Display for BadJump {
232 #[inline]
233 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
234 write!(f, "Bad jump index {}", self.jump)
235 }
236}
237
238impl core::error::Error for BadJump {}