1use crate::*;
2
3pub struct Memory(pub MemoryHandle);
4
5pub struct ManagedMemory(pub Memory);
6
7pub mod internal {
8 use super::*;
9
10 pub fn memory_alloc(n: u64) -> MemoryHandle {
11 let length = n;
12 let offset = unsafe { extism::alloc(length) };
13 MemoryHandle { offset, length }
14 }
15
16 pub fn memory_free(handle: MemoryHandle) {
17 unsafe { extism::free(handle.offset) }
18 }
19
20 pub fn memory_bytes(handle: MemoryHandle) -> Vec<u8> {
21 let mut data = vec![0; handle.length as usize];
22 unsafe { extism::load(handle.offset, &mut data) };
23 data
24 }
25
26 pub fn memory_length(offs: u64) -> u64 {
28 unsafe { extism::length(offs) }
29 }
30
31 pub fn memory_length_unsafe(offs: u64) -> u64 {
33 unsafe { extism::length_unsafe(offs) }
34 }
35
36 pub fn load(handle: MemoryHandle, mut buf: impl AsMut<[u8]>) {
38 let buf = buf.as_mut();
39 unsafe {
40 extism::load(handle.offset, &mut buf[0..handle.length as usize]);
41 }
42 }
43
44 pub fn store(handle: MemoryHandle, buf: impl AsRef<[u8]>) {
46 let buf = buf.as_ref();
47 unsafe { extism::store(handle.offset, &buf[0..handle.length as usize]) }
48 }
49
50 pub fn find(offset: u64) -> Option<MemoryHandle> {
52 let length = unsafe { extism::length(offset) };
53
54 if length == 0 {
55 return None;
56 }
57
58 Some(MemoryHandle { offset, length })
59 }
60}
61
62impl Memory {
63 pub fn offset(&self) -> u64 {
64 self.0.offset
65 }
66
67 pub fn len(&self) -> usize {
68 self.0.length as usize
69 }
70
71 pub fn is_empty(&self) -> bool {
72 self.0.length == 0
73 }
74
75 pub fn null() -> Self {
76 Memory(MemoryHandle {
77 offset: 0,
78 length: 0,
79 })
80 }
81
82 pub fn new<'a, T: ToBytes<'a>>(x: &T) -> Result<Self, Error> {
84 let data = x.to_bytes()?;
85 let data = data.as_ref();
86 let length = data.len() as u64;
87 let offset = unsafe { extism::alloc(length) };
88 unsafe { extism::store(offset, data) };
89 Ok(Self(MemoryHandle { offset, length }))
90 }
91
92 pub fn from_bytes(data: impl AsRef<[u8]>) -> Result<Self, Error> {
94 let memory = Memory::new(&data.as_ref())?;
95 Ok(memory)
96 }
97
98 pub fn to_vec(&self) -> Vec<u8> {
100 let mut dest = vec![0u8; self.0.length as usize];
101 internal::load(self.0, &mut dest);
102 dest
103 }
104
105 pub fn to_string(&self) -> Result<String, Error> {
107 let x = String::from_utf8(self.to_vec())?;
108 Ok(x)
109 }
110
111 pub fn set_output(self) {
113 unsafe {
114 extism::output_set(self.0.offset, self.0.length);
115 }
116 }
117
118 pub fn log(&self, level: LogLevel) {
120 unsafe {
121 match level {
122 LogLevel::Info => extism::log_info(self.0.offset),
123 LogLevel::Debug => extism::log_debug(self.0.offset),
124 LogLevel::Warn => extism::log_warn(self.0.offset),
125 LogLevel::Error => extism::log_error(self.0.offset),
126 LogLevel::Trace => extism::log_trace(self.0.offset),
127 }
128 }
129 }
130
131 pub fn to<T: FromBytesOwned>(&self) -> Result<T, Error> {
133 T::from_bytes_owned(&self.to_vec())
134 }
135
136 pub fn find(offs: u64) -> Option<Memory> {
138 internal::find(offs).map(Memory)
139 }
140
141 pub fn free(self) {
143 internal::memory_free(self.0)
144 }
145}
146
147impl From<Memory> for () {
148 fn from(_: Memory) {}
149}
150
151impl From<()> for Memory {
152 fn from(_: ()) -> Memory {
153 Memory(MemoryHandle::null())
154 }
155}
156
157impl From<Memory> for i64 {
158 fn from(m: Memory) -> Self {
159 m.0.offset as i64
160 }
161}
162
163impl From<Memory> for u64 {
164 fn from(m: Memory) -> Self {
165 m.0.offset
166 }
167}
168
169impl From<u64> for Memory {
170 fn from(offset: u64) -> Memory {
171 Memory::find(offset).unwrap_or_else(Memory::null)
172 }
173}
174
175impl From<i64> for Memory {
176 fn from(offset: i64) -> Memory {
177 Memory::find(offset as u64).unwrap_or_else(Memory::null)
178 }
179}
180
181#[repr(transparent)]
182#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
183pub struct MemoryPointer<T>(u64, std::marker::PhantomData<T>);
184
185impl<T> MemoryPointer<T> {
186 pub unsafe fn new(x: u64) -> Self {
187 MemoryPointer(x, Default::default())
188 }
189}
190
191impl<T: FromBytesOwned> MemoryPointer<T> {
192 pub fn get(&self) -> Result<T, Error> {
193 let mem = Memory::find(self.0);
194 match mem {
195 Some(mem) => T::from_bytes_owned(&mem.to_vec()),
196 None => anyhow::bail!("Invalid pointer offset {}", self.0),
197 }
198 }
199}
200
201impl Drop for ManagedMemory {
202 fn drop(&mut self) {
203 internal::memory_free((self.0).0)
204 }
205}
206
207impl ManagedMemory {
208 pub fn new(mem: Memory) -> Self {
209 ManagedMemory(mem)
210 }
211
212 pub fn offset(&self) -> u64 {
213 self.0.offset()
214 }
215
216 pub fn len(&self) -> usize {
217 self.0.len()
218 }
219}
220
221impl From<Memory> for ManagedMemory {
222 fn from(value: Memory) -> Self {
223 ManagedMemory(value)
224 }
225}
226
227impl AsRef<Memory> for ManagedMemory {
228 fn as_ref(&self) -> &Memory {
229 &self.0
230 }
231}
232
233impl AsMut<Memory> for ManagedMemory {
234 fn as_mut(&mut self) -> &mut Memory {
235 &mut self.0
236 }
237}