1use crate::func::FuncRef;
2use crate::module::check_limits;
3use crate::Error;
4use alloc::{rc::Rc, vec::Vec};
5use core::cell::RefCell;
6use core::fmt;
7use core::u32;
8use parity_wasm::elements::ResizableLimits;
9
10#[derive(Clone, Debug)]
17pub struct TableRef(Rc<TableInstance>);
18
19impl ::core::ops::Deref for TableRef {
20 type Target = TableInstance;
21 fn deref(&self) -> &TableInstance {
22 &self.0
23 }
24}
25
26pub struct TableInstance {
40 limits: ResizableLimits,
42 buffer: RefCell<Vec<Option<FuncRef>>>,
44}
45
46impl fmt::Debug for TableInstance {
47 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
48 f.debug_struct("TableInstance")
49 .field("limits", &self.limits)
50 .field("buffer.len", &self.buffer.borrow().len())
51 .finish()
52 }
53}
54
55impl TableInstance {
56 pub fn alloc(initial_size: u32, maximum_size: Option<u32>) -> Result<TableRef, Error> {
67 let table = TableInstance::new(ResizableLimits::new(initial_size, maximum_size))?;
68 Ok(TableRef(Rc::new(table)))
69 }
70
71 fn new(limits: ResizableLimits) -> Result<TableInstance, Error> {
72 check_limits(&limits)?;
73 Ok(TableInstance {
74 buffer: RefCell::new(vec![None; limits.initial() as usize]),
75 limits,
76 })
77 }
78
79 pub(crate) fn limits(&self) -> &ResizableLimits {
81 &self.limits
82 }
83
84 pub fn initial_size(&self) -> u32 {
86 self.limits.initial()
87 }
88
89 pub fn maximum_size(&self) -> Option<u32> {
91 self.limits.maximum()
92 }
93
94 pub fn current_size(&self) -> u32 {
96 self.buffer.borrow().len() as u32
97 }
98
99 pub fn grow(&self, by: u32) -> Result<(), Error> {
105 let mut buffer = self.buffer.borrow_mut();
106 let maximum_size = self.maximum_size().unwrap_or(u32::MAX);
107 let new_size = self
108 .current_size()
109 .checked_add(by)
110 .and_then(|new_size| {
111 if maximum_size < new_size {
112 None
113 } else {
114 Some(new_size)
115 }
116 })
117 .ok_or_else(|| {
118 Error::Table(format!(
119 "Trying to grow table by {} items when there are already {} items",
120 by,
121 self.current_size(),
122 ))
123 })?;
124 buffer.resize(new_size as usize, None);
125 Ok(())
126 }
127
128 pub fn get(&self, offset: u32) -> Result<Option<FuncRef>, Error> {
130 let buffer = self.buffer.borrow();
131 let buffer_len = buffer.len();
132 let table_elem = buffer.get(offset as usize).cloned().ok_or_else(|| {
133 Error::Table(format!(
134 "trying to read table item with index {} when there are only {} items",
135 offset, buffer_len
136 ))
137 })?;
138 Ok(table_elem)
139 }
140
141 pub fn set(&self, offset: u32, value: Option<FuncRef>) -> Result<(), Error> {
143 let mut buffer = self.buffer.borrow_mut();
144 let buffer_len = buffer.len();
145 let table_elem = buffer.get_mut(offset as usize).ok_or_else(|| {
146 Error::Table(format!(
147 "trying to update table item with index {} when there are only {} items",
148 offset, buffer_len
149 ))
150 })?;
151 *table_elem = value;
152 Ok(())
153 }
154}