Coverage for wasmtime/_table.py: 100%

51 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-02-20 16:25 +0000

1from . import _ffi as ffi 

2from ctypes import * 

3from wasmtime import TableType, Store, WasmtimeError, Val 

4from typing import Optional, Any 

5from ._store import Storelike 

6 

7 

8class Table: 

9 _table: ffi.wasmtime_table_t 

10 

11 def __init__(self, store: Store, ty: TableType, init: Any): 

12 """ 

13 Creates a new table within `store` with the specified `ty`. 

14 """ 

15 

16 init_val = Val._convert_to_raw(store, ty.element, init) 

17 

18 table = ffi.wasmtime_table_t() 

19 error = ffi.wasmtime_table_new(store._context(), ty.ptr(), byref(init_val), byref(table)) 

20 ffi.wasmtime_val_unroot(store._context(), byref(init_val)) 

21 if error: 

22 raise WasmtimeError._from_ptr(error) 

23 self._table = table 

24 

25 @classmethod 

26 def _from_raw(cls, table: ffi.wasmtime_table_t) -> "Table": 

27 ty: "Table" = cls.__new__(cls) 

28 ty._table = table 

29 return ty 

30 

31 def type(self, store: Storelike) -> TableType: 

32 """ 

33 Gets the type of this table as a `TableType` 

34 """ 

35 

36 ptr = ffi.wasmtime_table_type(store._context(), byref(self._table)) 

37 return TableType._from_ptr(ptr, None) 

38 

39 def size(self, store: Storelike) -> int: 

40 """ 

41 Gets the size, in elements, of this table 

42 """ 

43 return ffi.wasmtime_table_size(store._context(), byref(self._table)) 

44 

45 def grow(self, store: Storelike, amt: int, init: Any) -> int: 

46 """ 

47 Grows this table by the specified number of slots, using the specified 

48 initializer for all new table slots. 

49 

50 Raises a `WasmtimeError` if the table could not be grown. 

51 Returns the previous size of the table otherwise. 

52 """ 

53 init_val = Val._convert_to_raw(store, self.type(store).element, init) 

54 prev = c_uint64(0) 

55 error = ffi.wasmtime_table_grow(store._context(), byref(self._table), c_uint64(amt), byref(init_val), byref(prev)) 

56 ffi.wasmtime_val_unroot(store._context(), byref(init_val)) 

57 if error: 

58 raise WasmtimeError._from_ptr(error) 

59 return prev.value 

60 

61 def get(self, store: Store, idx: int) -> Optional[Any]: 

62 """ 

63 Gets an individual element within this table. 

64 

65 Returns `None` for null references in the table (i.e. a null `funcref` 

66 or a null `externref). 

67 

68 Returns a `Func` for non-null `funcref` table elements. 

69 

70 Returns the wrapped extern data for non-null `externref` table elements. 

71 

72 Returns `None` if `idx` is out of bounds. 

73 """ 

74 raw = ffi.wasmtime_val_t() 

75 ok = ffi.wasmtime_table_get(store._context(), byref(self._table), idx, byref(raw)) 

76 if not ok: 

77 return None 

78 val = Val._from_raw(store, raw) 

79 if val.value: 

80 return val.value 

81 else: 

82 return val 

83 

84 def set(self, store: Store, idx: int, val: Any) -> None: 

85 """ 

86 Sets an individual element within this table. 

87 

88 `idx` must be an integer index. 

89 

90 The `val` specified must be convertible into this table's element 

91 type. I.e. for a `funcref` table, `val` must either be a `Func` or 

92 `None`, and for an `externref` table, `val` may be any arbitrary 

93 external data. 

94 

95 Raises a `WasmtimeError` if `idx` is out of bounds. 

96 """ 

97 value = Val._convert_to_raw(store, self.type(store).element, val) 

98 error = ffi.wasmtime_table_set(store._context(), byref(self._table), idx, byref(value)) 

99 ffi.wasmtime_val_unroot(store._context(), byref(value)) 

100 if error: 

101 raise WasmtimeError._from_ptr(error) 

102 

103 def _as_extern(self) -> ffi.wasmtime_extern_t: 

104 union = ffi.wasmtime_extern_union(table=self._table) 

105 return ffi.wasmtime_extern_t(ffi.WASMTIME_EXTERN_TABLE, union)