Class: Wasmtime::Memory
- Inherits:
-
Object
- Object
- Wasmtime::Memory
- Defined in:
- ext/src/ruby_api/memory.rs
Overview
Represents a WebAssembly memory.
Defined Under Namespace
Classes: UnsafeSlice
Class Method Summary collapse
Instance Method Summary collapse
-
#data_size ⇒ Integer
The number of bytes of the memory.
-
#grow(delta) ⇒ Integer
Grows a memory by
deltapages. -
#max_size ⇒ Integer?
The maximum number of memory pages.
-
#min_size ⇒ Integer
The minimum number of memory pages.
-
#read(offset, size) ⇒ String
Read
sizebytes starting atoffset. -
#read_cstring(offset) ⇒ String
Read a NUL-terminated C string starting at
offsetas an ASCII-8BIT (binary)String. -
#read_f32(offset) ⇒ Float
Read a little-endian
f32starting atoffset. -
#read_f64(offset) ⇒ Float
Read a little-endian
f64starting atoffset. -
#read_i32(offset) ⇒ Integer
Read a little-endian
i32starting atoffset. -
#read_i64(offset) ⇒ Integer
Read a little-endian
i64starting atoffset. -
#read_u32(offset) ⇒ Integer
Read a little-endian
u32starting atoffset. -
#read_u64(offset) ⇒ Integer
Read a little-endian
u64starting atoffset. -
#read_unsafe_slice(offset, size) ⇒ Wasmtime::Memory::UnsafeSlice
Read
sizebytes starting atoffsetinto an UnsafeSlice. -
#read_utf8(offset, size) ⇒ String
Read
sizebytes starting atoffset. -
#size ⇒ Integer
The number of pages of the memory.
-
#write(offset, value) ⇒ void
Write
valuestarting atoffset. -
#write_cstring(offset, value) ⇒ void
Write +value+'s bytes followed by a NUL terminator at
offset. -
#write_f32(offset, value) ⇒ void
Write a little-endian
f32starting atoffset. -
#write_f64(offset, value) ⇒ void
Write a little-endian
f64starting atoffset. -
#write_i32(offset, value) ⇒ void
Write a little-endian
i32starting atoffset. -
#write_i64(offset, value) ⇒ void
Write a little-endian
i64starting atoffset. -
#write_u32(offset, value) ⇒ void
Write a little-endian
u32starting atoffset. -
#write_u64(offset, value) ⇒ void
Write a little-endian
u64starting atoffset.
Class Method Details
.new(store, min_size:, max_size: nil) ⇒ Object
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'ext/src/ruby_api/memory.rs', line 87
pub fn new(args: &[Value]) -> Result<Self, Error> {
let args = scan_args::scan_args::<(Obj<Store>,), (), (), (), _, ()>(args)?;
let kw = scan_args::get_kwargs::<_, (u32,), (Option<u32>,), ()>(
args.keywords,
&[*MIN_SIZE],
&[*MAX_SIZE],
)?;
let (store,) = args.required;
let (min,) = kw.required;
let (max,) = kw.optional;
let memtype = wasmtime::MemoryType::new(min, max);
let inner = MemoryImpl::new(store.context_mut(), memtype).map_err(|e| error!("{}", e))?;
let memsize = inner.data_size(store.context_mut());
Ok(Self {
store: store.into(),
inner: ManuallyTracked::wrap(inner, memsize),
})
}
|
Instance Method Details
#data_size ⇒ Integer
Returns The number of bytes of the memory.
433 434 435 |
# File 'ext/src/ruby_api/memory.rs', line 433
pub fn data_size(&self) -> Result<usize, Error> {
Ok(self.get_wasmtime_memory().data_size(self.store.context()?))
}
|
#grow(delta) ⇒ Integer
Grows a memory by delta pages.
Raises if the memory grows beyond its limit.
413 414 415 416 417 418 419 420 421 422 423 |
# File 'ext/src/ruby_api/memory.rs', line 413
pub fn grow(&self, delta: usize) -> Result<u64, Error> {
let ret = self
.get_wasmtime_memory()
.grow(self.store.context_mut()?, delta as _)
.map_err(|e| error!("{}", e));
self.inner
.increase_memory_usage(delta * (WASM_PAGE_SIZE as usize));
ret
}
|
#max_size ⇒ Integer?
Returns The maximum number of memory pages.
129 130 131 132 133 134 |
# File 'ext/src/ruby_api/memory.rs', line 129
pub fn max_size(&self) -> Result<Option<u64>, Error> {
Ok(self
.get_wasmtime_memory()
.ty(self.store.context()?)
.maximum())
}
|
#min_size ⇒ Integer
Returns The minimum number of memory pages.
120 121 122 123 124 125 |
# File 'ext/src/ruby_api/memory.rs', line 120
pub fn min_size(&self) -> Result<u64, Error> {
Ok(self
.get_wasmtime_memory()
.ty(self.store.context()?)
.minimum())
}
|
#read(offset, size) ⇒ String
Read size bytes starting at offset. Result is a ASCII-8BIT encoded string.
143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'ext/src/ruby_api/memory.rs', line 143
pub fn read(
ruby: &Ruby,
rb_self: Obj<Self>,
offset: usize,
size: usize,
) -> Result<RString, Error> {
rb_self
.get_wasmtime_memory()
.data(rb_self.store.context()?)
.get(offset..)
.and_then(|s| s.get(..size))
.map(|s| ruby.str_from_slice(s))
.ok_or_else(|| error!("out of bounds memory access"))
}
|
#read_cstring(offset) ⇒ String
Read a NUL-terminated C string starting at offset as an ASCII-8BIT
(binary) String.
362 363 364 365 366 367 368 369 370 371 372 373 374 375 |
# File 'ext/src/ruby_api/memory.rs', line 362
pub fn read_cstring(ruby: &Ruby, rb_self: Obj<Self>, offset: usize) -> Result<RString, Error> {
let context = rb_self.store.context()?;
let data = rb_self.get_wasmtime_memory().data(context);
let bytes: &[u8] = match data.get(offset..) {
Some(slice) => {
let end = slice.iter().position(|&b| b == 0).unwrap_or(slice.len());
&slice[..end]
}
None => &[],
};
Ok(ruby.str_from_slice(bytes))
}
|
#read_f32(offset) ⇒ Float
Read a little-endian f32 starting at offset.
275 276 277 |
# File 'ext/src/ruby_api/memory.rs', line 275
pub fn read_f32(&self, offset: usize) -> Result<f32, Error> {
Ok(f32::from_le_bytes(self.read_fixed::<4>(offset)?))
}
|
#read_f64(offset) ⇒ Float
Read a little-endian f64 starting at offset.
285 286 287 |
# File 'ext/src/ruby_api/memory.rs', line 285
pub fn read_f64(&self, offset: usize) -> Result<f64, Error> {
Ok(f64::from_le_bytes(self.read_fixed::<8>(offset)?))
}
|
#read_i32(offset) ⇒ Integer
Read a little-endian i32 starting at offset.
235 236 237 |
# File 'ext/src/ruby_api/memory.rs', line 235
pub fn read_i32(&self, offset: usize) -> Result<i32, Error> {
Ok(i32::from_le_bytes(self.read_fixed::<4>(offset)?))
}
|
#read_i64(offset) ⇒ Integer
Read a little-endian i64 starting at offset.
255 256 257 |
# File 'ext/src/ruby_api/memory.rs', line 255
pub fn read_i64(&self, offset: usize) -> Result<i64, Error> {
Ok(i64::from_le_bytes(self.read_fixed::<8>(offset)?))
}
|
#read_u32(offset) ⇒ Integer
Read a little-endian u32 starting at offset.
245 246 247 |
# File 'ext/src/ruby_api/memory.rs', line 245
pub fn read_u32(&self, offset: usize) -> Result<u32, Error> {
Ok(u32::from_le_bytes(self.read_fixed::<4>(offset)?))
}
|
#read_u64(offset) ⇒ Integer
Read a little-endian u64 starting at offset.
265 266 267 |
# File 'ext/src/ruby_api/memory.rs', line 265
pub fn read_u64(&self, offset: usize) -> Result<u64, Error> {
Ok(u64::from_le_bytes(self.read_fixed::<8>(offset)?))
}
|
#read_unsafe_slice(offset, size) ⇒ Wasmtime::Memory::UnsafeSlice
Read size bytes starting at offset into an UnsafeSlice. This
provides a way to read a slice of memory without copying the underlying
data.
The returned UnsafeSlice lazily reads the underlying memory, meaning that the actual pointer to the string buffer is not materialzed until Wasmtime::Memory::UnsafeSlice#to_str is called.
SAFETY: Resizing the memory (as with #grow) will
invalidate the UnsafeSlice, and future attempts to read the slice will raise
an error. However, it is not possible to invalidate the Ruby String
object after calling Wasmtime::Memory::UnsafeSlice#to_str. As such, the caller must ensure
that the Wasmtime Wasmtime::Memory is not resized while holding the Ruby string.
Failing to do so could result in the String buffer pointing to invalid
memory.
In general, you should prefer using #read or #read_utf8 over this method unless you know what you're doing.
205 206 207 208 209 210 211 212 |
# File 'ext/src/ruby_api/memory.rs', line 205
pub fn read_unsafe_slice(
ruby: &Ruby,
rb_self: Obj<Self>,
offset: usize,
size: usize,
) -> Result<Obj<UnsafeSlice<'a>>, Error> {
Ok(ruby.obj_wrap(UnsafeSlice::new(rb_self, offset..(offset + size))?))
}
|
#read_utf8(offset, size) ⇒ String
Read size bytes starting at offset. Result is a UTF-8 encoded string.
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'ext/src/ruby_api/memory.rs', line 165
pub fn read_utf8(
ruby: &Ruby,
rb_self: Obj<Self>,
offset: usize,
size: usize,
) -> Result<RString, Error> {
rb_self
.get_wasmtime_memory()
.data(rb_self.store.context()?)
.get(offset..)
.and_then(|s| s.get(..size))
.ok_or_else(|| error!("out of bounds memory access"))
.and_then(|s| std::str::from_utf8(s).map_err(|e| error!("{}", e)))
.map(|s| ruby.str_new(s))
}
|
#size ⇒ Integer
Returns The number of pages of the memory.
427 428 429 |
# File 'ext/src/ruby_api/memory.rs', line 427
pub fn size(&self) -> Result<u64, Error> {
Ok(self.get_wasmtime_memory().size(self.store.context()?))
}
|
#write(offset, value) ⇒ void
This method returns an undefined value.
Write value starting at offset.
221 222 223 224 225 226 227 |
# File 'ext/src/ruby_api/memory.rs', line 221
pub fn write(&self, offset: usize, value: RString) -> Result<(), Error> {
let slice = unsafe { value.as_slice() };
self.get_wasmtime_memory()
.write(self.store.context_mut()?, offset, slice)
.map_err(|e| error!("{}", e))
}
|
#write_cstring(offset, value) ⇒ void
This method returns an undefined value.
Write +value+'s bytes followed by a NUL terminator at offset.
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 |
# File 'ext/src/ruby_api/memory.rs', line 384
pub fn write_cstring(&self, offset: usize, value: RString) -> Result<(), Error> {
let slice = unsafe { value.as_slice() };
if slice.contains(&0) {
return Err(Error::new(
Ruby::get_with(value).exception_arg_error(),
"string contains null byte",
));
}
let len = slice.len();
let mut context = self.store.context_mut()?;
let dst = self
.get_wasmtime_memory()
.data_mut(&mut context)
.get_mut(offset..)
.and_then(|s| s.get_mut(..len + 1))
.ok_or_else(|| error!("out of bounds memory access"))?;
dst[..len].copy_from_slice(slice);
dst[len] = 0;
Ok(())
}
|
#write_f32(offset, value) ⇒ void
This method returns an undefined value.
Write a little-endian f32 starting at offset.
340 341 342 |
# File 'ext/src/ruby_api/memory.rs', line 340
pub fn write_f32(&self, offset: usize, value: f32) -> Result<(), Error> {
self.write_fixed(offset, value.to_le_bytes())
}
|
#write_f64(offset, value) ⇒ void
This method returns an undefined value.
Write a little-endian f64 starting at offset.
351 352 353 |
# File 'ext/src/ruby_api/memory.rs', line 351
pub fn write_f64(&self, offset: usize, value: f64) -> Result<(), Error> {
self.write_fixed(offset, value.to_le_bytes())
}
|
#write_i32(offset, value) ⇒ void
This method returns an undefined value.
Write a little-endian i32 starting at offset.
296 297 298 |
# File 'ext/src/ruby_api/memory.rs', line 296
pub fn write_i32(&self, offset: usize, value: i32) -> Result<(), Error> {
self.write_fixed(offset, value.to_le_bytes())
}
|
#write_i64(offset, value) ⇒ void
This method returns an undefined value.
Write a little-endian i64 starting at offset.
318 319 320 |
# File 'ext/src/ruby_api/memory.rs', line 318
pub fn write_i64(&self, offset: usize, value: i64) -> Result<(), Error> {
self.write_fixed(offset, value.to_le_bytes())
}
|
#write_u32(offset, value) ⇒ void
This method returns an undefined value.
Write a little-endian u32 starting at offset.
307 308 309 |
# File 'ext/src/ruby_api/memory.rs', line 307
pub fn write_u32(&self, offset: usize, value: u32) -> Result<(), Error> {
self.write_fixed(offset, value.to_le_bytes())
}
|
#write_u64(offset, value) ⇒ void
This method returns an undefined value.
Write a little-endian u64 starting at offset.
329 330 331 |
# File 'ext/src/ruby_api/memory.rs', line 329
pub fn write_u64(&self, offset: usize, value: u64) -> Result<(), Error> {
self.write_fixed(offset, value.to_le_bytes())
}
|