rune/runtime/unit/
byte_code.rs1use core::mem::size_of;
2
3#[cfg(feature = "byte-code")]
4use musli::storage;
5#[cfg(feature = "musli")]
6use musli::{Decode, Encode};
7#[cfg(feature = "serde")]
8use serde::{Deserialize, Serialize};
9
10use crate as rune;
11use crate::alloc::prelude::*;
12use crate::alloc::{self, Vec};
13use crate::runtime::unit::{BadInstruction, BadJump, EncodeError, UnitEncoder, UnitStorage};
14use crate::runtime::Inst;
15
16#[derive(Debug, TryClone, Default)]
20#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
21#[cfg_attr(feature = "musli", derive(Decode, Encode))]
22pub struct ByteCodeUnit {
23 #[cfg_attr(feature = "musli", musli(bytes))]
25 bytes: Vec<u8>,
26 offsets: Vec<usize>,
28}
29
30pub struct ByteCodeUnitIter<'a> {
32 address: &'a [u8],
33 len: usize,
34}
35
36impl Iterator for ByteCodeUnitIter<'_> {
37 type Item = (usize, Inst);
38
39 #[inline]
40 fn next(&mut self) -> Option<Self::Item> {
41 if self.address.is_empty() {
42 return None;
43 }
44
45 let ip = self.len.checked_sub(self.address.len())?;
46 let inst = storage::decode(self.address).ok()?;
47 Some((ip, inst))
48 }
49}
50
51impl UnitEncoder for ByteCodeUnit {
52 #[inline]
53 fn offset(&self) -> usize {
54 self.bytes.len()
55 }
56
57 #[inline]
58 fn encode(&mut self, inst: Inst) -> Result<(), EncodeError> {
59 storage::to_writer(&mut self.bytes, &inst)?;
60 Ok(())
61 }
62
63 #[inline]
64 fn extend_offsets(&mut self, extra: usize) -> alloc::Result<usize> {
65 let base = self.offsets.len();
66 self.offsets.try_extend((0..extra).map(|_| 0))?;
67 Ok(base)
68 }
69
70 #[inline]
71 fn mark_offset(&mut self, index: usize) {
72 if let Some(o) = self.offsets.get_mut(index) {
73 *o = self.bytes.len();
74 }
75 }
76
77 #[inline]
78 fn label_jump(&self, base: usize, _: usize, jump: usize) -> usize {
79 base.wrapping_add(jump)
80 }
81}
82
83impl UnitStorage for ByteCodeUnit {
84 type Iter<'this> = ByteCodeUnitIter<'this>;
85
86 #[inline]
87 fn end(&self) -> usize {
88 self.bytes.len()
89 }
90
91 #[inline]
92 fn bytes(&self) -> usize {
93 self.bytes
94 .len()
95 .wrapping_add(self.offsets.len().wrapping_mul(size_of::<usize>()))
96 }
97
98 #[inline]
99 fn iter(&self) -> Self::Iter<'_> {
100 ByteCodeUnitIter {
101 address: &self.bytes[..],
102 len: self.bytes.len(),
103 }
104 }
105
106 fn get(&self, ip: usize) -> Result<Option<(Inst, usize)>, BadInstruction> {
107 let Some(bytes) = self.bytes.get(ip..) else {
108 return Ok(None);
109 };
110
111 let start = bytes.as_ptr();
112 let inst: Inst = storage::decode(bytes).map_err(|_| BadInstruction { ip })?;
113 let len = (bytes.as_ptr() as usize).wrapping_sub(start as usize);
114 Ok(Some((inst, len)))
115 }
116
117 #[inline]
118 fn translate(&self, jump: usize) -> Result<usize, BadJump> {
119 let Some(&offset) = self.offsets.get(jump) else {
120 return Err(BadJump { jump });
121 };
122
123 Ok(offset)
124 }
125}