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