1#[cfg(feature = "component-model")]
5use crate::component;
6use crate::{
7 BuiltinFunctionIndex, DefinedFuncIndex, HostCall, ModuleInternedTypeIndex, StaticModuleIndex,
8};
9use core::cmp;
10use serde_derive::{Deserialize, Serialize};
11
12#[repr(u32)]
17#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
18pub enum FuncKeyKind {
19 DefinedWasmFunction = FuncKey::new_kind(0b000),
21
22 ArrayToWasmTrampoline = FuncKey::new_kind(0b001),
24
25 WasmToArrayTrampoline = FuncKey::new_kind(0b010),
27
28 WasmToBuiltinTrampoline = FuncKey::new_kind(0b011),
30
31 PulleyHostCall = FuncKey::new_kind(0b100),
33
34 #[cfg(feature = "component-model")]
36 ComponentTrampoline = FuncKey::new_kind(0b101),
37
38 #[cfg(feature = "component-model")]
40 ResourceDropTrampoline = FuncKey::new_kind(0b110),
41}
42
43impl From<FuncKeyKind> for u32 {
44 fn from(kind: FuncKeyKind) -> Self {
45 kind as u32
46 }
47}
48
49impl FuncKeyKind {
50 pub fn into_raw(self) -> u32 {
52 self.into()
53 }
54
55 pub fn from_raw(raw: u32) -> Self {
59 match raw {
60 x if x == Self::DefinedWasmFunction.into() => Self::DefinedWasmFunction,
61 x if x == Self::ArrayToWasmTrampoline.into() => Self::ArrayToWasmTrampoline,
62 x if x == Self::WasmToArrayTrampoline.into() => Self::WasmToArrayTrampoline,
63 x if x == Self::WasmToBuiltinTrampoline.into() => Self::WasmToBuiltinTrampoline,
64 x if x == Self::PulleyHostCall.into() => Self::PulleyHostCall,
65
66 #[cfg(feature = "component-model")]
67 x if x == Self::ComponentTrampoline.into() => Self::ComponentTrampoline,
68 #[cfg(feature = "component-model")]
69 x if x == Self::ResourceDropTrampoline.into() => Self::ResourceDropTrampoline,
70
71 _ => panic!("invalid raw value passed to `FuncKind::from_raw`: {raw}"),
72 }
73 }
74}
75
76#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
80pub struct FuncKeyNamespace(u32);
81
82impl From<FuncKeyNamespace> for u32 {
83 fn from(ns: FuncKeyNamespace) -> Self {
84 ns.0
85 }
86}
87
88impl FuncKeyNamespace {
89 pub fn into_raw(self) -> u32 {
91 self.0
92 }
93
94 pub fn from_raw(raw: u32) -> Self {
98 match FuncKeyKind::from_raw(raw & FuncKey::KIND_MASK) {
99 FuncKeyKind::DefinedWasmFunction | FuncKeyKind::ArrayToWasmTrampoline => Self(raw),
100 FuncKeyKind::WasmToArrayTrampoline
101 | FuncKeyKind::WasmToBuiltinTrampoline
102 | FuncKeyKind::PulleyHostCall => {
103 assert_eq!(raw & FuncKey::MODULE_MASK, 0);
104 Self(raw)
105 }
106
107 #[cfg(feature = "component-model")]
108 FuncKeyKind::ComponentTrampoline => {
109 let _ = Abi::from_raw(raw & FuncKey::MODULE_MASK);
110 Self(raw)
111 }
112
113 #[cfg(feature = "component-model")]
114 FuncKeyKind::ResourceDropTrampoline => {
115 assert_eq!(raw & FuncKey::MODULE_MASK, 0);
116 Self(raw)
117 }
118 }
119 }
120
121 pub fn kind(&self) -> FuncKeyKind {
123 let raw = self.0 & FuncKey::KIND_MASK;
124 FuncKeyKind::from_raw(raw)
125 }
126}
127
128#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
130pub struct FuncKeyIndex(u32);
131
132impl From<FuncKeyIndex> for u32 {
133 fn from(index: FuncKeyIndex) -> Self {
134 index.0
135 }
136}
137
138impl FuncKeyIndex {
139 pub fn into_raw(self) -> u32 {
141 self.0
142 }
143
144 pub fn from_raw(raw: u32) -> Self {
150 FuncKeyIndex(raw)
151 }
152}
153
154#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
156pub enum Abi {
157 Wasm = 0,
159 Array = 1,
161}
162
163#[cfg(feature = "component-model")]
164impl Abi {
165 fn from_raw(raw: u32) -> Self {
166 match raw {
167 x if x == Self::Wasm.into_raw() => Self::Wasm,
168 x if x == Self::Array.into_raw() => Self::Array,
169 _ => panic!("invalid raw representation passed to `Abi::from_raw`: {raw}"),
170 }
171 }
172
173 fn into_raw(self) -> u32 {
174 (self as u8).into()
175 }
176}
177
178#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
181pub enum FuncKey {
182 DefinedWasmFunction(StaticModuleIndex, DefinedFuncIndex),
184
185 ArrayToWasmTrampoline(StaticModuleIndex, DefinedFuncIndex),
187
188 WasmToArrayTrampoline(ModuleInternedTypeIndex),
190
191 WasmToBuiltinTrampoline(BuiltinFunctionIndex),
193
194 PulleyHostCall(HostCall),
196
197 #[cfg(feature = "component-model")]
199 ComponentTrampoline(Abi, component::TrampolineIndex),
200
201 #[cfg(feature = "component-model")]
203 ResourceDropTrampoline,
204}
205
206impl Ord for FuncKey {
207 fn cmp(&self, other: &Self) -> cmp::Ordering {
208 let raw_self = self.into_raw_parts();
211 let raw_other = other.into_raw_parts();
212 raw_self.cmp(&raw_other)
213 }
214}
215
216impl PartialOrd for FuncKey {
217 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
218 Some(self.cmp(other))
219 }
220}
221
222impl FuncKey {
223 const KIND_BITS: u32 = 3;
224 const KIND_OFFSET: u32 = 32 - Self::KIND_BITS;
225 const KIND_MASK: u32 = ((1 << Self::KIND_BITS) - 1) << Self::KIND_OFFSET;
226 const MODULE_MASK: u32 = !Self::KIND_MASK;
227
228 const fn new_kind(kind: u32) -> u32 {
229 assert!(kind < (1 << Self::KIND_BITS));
230 kind << Self::KIND_OFFSET
231 }
232
233 #[inline]
235 pub fn into_parts(self) -> (FuncKeyNamespace, FuncKeyIndex) {
236 let (namespace, index) = match self {
237 FuncKey::DefinedWasmFunction(module, def_func) => {
238 assert_eq!(module.as_u32() & Self::KIND_MASK, 0);
239 let namespace = FuncKeyKind::DefinedWasmFunction.into_raw() | module.as_u32();
240 let index = def_func.as_u32();
241 (namespace, index)
242 }
243 FuncKey::ArrayToWasmTrampoline(module, def_func) => {
244 assert_eq!(module.as_u32() & Self::KIND_MASK, 0);
245 let namespace = FuncKeyKind::ArrayToWasmTrampoline.into_raw() | module.as_u32();
246 let index = def_func.as_u32();
247 (namespace, index)
248 }
249 FuncKey::WasmToArrayTrampoline(ty) => {
250 let namespace = FuncKeyKind::WasmToArrayTrampoline.into_raw();
251 let index = ty.as_u32();
252 (namespace, index)
253 }
254 FuncKey::WasmToBuiltinTrampoline(builtin) => {
255 let namespace = FuncKeyKind::WasmToBuiltinTrampoline.into_raw();
256 let index = builtin.index();
257 (namespace, index)
258 }
259 FuncKey::PulleyHostCall(host_call) => {
260 let namespace = FuncKeyKind::PulleyHostCall.into_raw();
261 let index = host_call.index();
262 (namespace, index)
263 }
264
265 #[cfg(feature = "component-model")]
266 FuncKey::ComponentTrampoline(abi, trampoline) => {
267 let abi = abi.into_raw();
268 assert_eq!(abi & Self::KIND_MASK, 0);
269 let namespace = FuncKeyKind::ComponentTrampoline.into_raw() | abi;
270 let index = trampoline.as_u32();
271 (namespace, index)
272 }
273 #[cfg(feature = "component-model")]
274 FuncKey::ResourceDropTrampoline => {
275 let namespace = FuncKeyKind::ResourceDropTrampoline.into_raw();
276 let index = 0;
277 (namespace, index)
278 }
279 };
280 (FuncKeyNamespace(namespace), FuncKeyIndex(index))
281 }
282
283 pub fn kind(self) -> FuncKeyKind {
285 self.namespace().kind()
286 }
287
288 pub fn namespace(self) -> FuncKeyNamespace {
290 self.into_parts().0
291 }
292
293 pub fn index(self) -> FuncKeyIndex {
295 self.into_parts().1
296 }
297
298 pub fn into_raw_parts(self) -> (u32, u32) {
308 let (ns, index) = self.into_parts();
309 (ns.into_raw(), index.into_raw())
310 }
311
312 pub fn from_parts(namespace: FuncKeyNamespace, index: FuncKeyIndex) -> Self {
321 Self::from_raw_parts(namespace.into_raw(), index.into_raw())
322 }
323
324 pub fn from_raw_parts(a: u32, b: u32) -> Self {
331 match FuncKeyKind::from_raw(a & Self::KIND_MASK) {
332 FuncKeyKind::DefinedWasmFunction => {
333 let module = StaticModuleIndex::from_u32(a & Self::MODULE_MASK);
334 let def_func = DefinedFuncIndex::from_u32(b);
335 Self::DefinedWasmFunction(module, def_func)
336 }
337 FuncKeyKind::ArrayToWasmTrampoline => {
338 let module = StaticModuleIndex::from_u32(a & Self::MODULE_MASK);
339 let def_func = DefinedFuncIndex::from_u32(b);
340 Self::ArrayToWasmTrampoline(module, def_func)
341 }
342 FuncKeyKind::WasmToArrayTrampoline => {
343 assert_eq!(a & Self::MODULE_MASK, 0);
344 let ty = ModuleInternedTypeIndex::from_u32(b);
345 Self::WasmToArrayTrampoline(ty)
346 }
347 FuncKeyKind::WasmToBuiltinTrampoline => {
348 assert_eq!(a & Self::MODULE_MASK, 0);
349 let builtin = BuiltinFunctionIndex::from_u32(b);
350 Self::WasmToBuiltinTrampoline(builtin)
351 }
352 FuncKeyKind::PulleyHostCall => {
353 assert_eq!(a & Self::MODULE_MASK, 0);
354 let host_call = HostCall::from_index(b);
355 Self::PulleyHostCall(host_call)
356 }
357
358 #[cfg(feature = "component-model")]
359 FuncKeyKind::ComponentTrampoline => {
360 let abi = Abi::from_raw(a & Self::MODULE_MASK);
361 let trampoline = component::TrampolineIndex::from_u32(b);
362 Self::ComponentTrampoline(abi, trampoline)
363 }
364 #[cfg(feature = "component-model")]
365 FuncKeyKind::ResourceDropTrampoline => {
366 assert_eq!(a & Self::MODULE_MASK, 0);
367 assert_eq!(b, 0);
368 Self::ResourceDropTrampoline
369 }
370 }
371 }
372
373 pub fn unwrap_defined_wasm_function(self) -> (StaticModuleIndex, DefinedFuncIndex) {
375 match self {
376 Self::DefinedWasmFunction(module, def_func) => (module, def_func),
377 _ => panic!("`FuncKey::unwrap_defined_wasm_function` called on {self:?}"),
378 }
379 }
380
381 pub fn unwrap_array_to_wasm_trampoline(self) -> (StaticModuleIndex, DefinedFuncIndex) {
383 match self {
384 Self::ArrayToWasmTrampoline(module, def_func) => (module, def_func),
385 _ => panic!("`FuncKey::unwrap_array_to_wasm_trampoline` called on {self:?}"),
386 }
387 }
388
389 pub fn unwrap_wasm_to_array_trampoline(self) -> ModuleInternedTypeIndex {
391 match self {
392 Self::WasmToArrayTrampoline(ty) => ty,
393 _ => panic!("`FuncKey::unwrap_wasm_to_array_trampoline` called on {self:?}"),
394 }
395 }
396
397 pub fn unwrap_wasm_to_builtin_trampoline(self) -> BuiltinFunctionIndex {
399 match self {
400 Self::WasmToBuiltinTrampoline(builtin) => builtin,
401 _ => panic!("`FuncKey::unwrap_wasm_to_builtin_trampoline` called on {self:?}"),
402 }
403 }
404
405 pub fn unwrap_pulley_host_call(self) -> HostCall {
407 match self {
408 Self::PulleyHostCall(host_call) => host_call,
409 _ => panic!("`FuncKey::unwrap_pulley_host_call` called on {self:?}"),
410 }
411 }
412
413 #[cfg(feature = "component-model")]
415 pub fn unwrap_component_trampoline(self) -> (crate::Abi, component::TrampolineIndex) {
416 match self {
417 Self::ComponentTrampoline(abi, trampoline) => (abi, trampoline),
418 _ => panic!("`FuncKey::unwrap_component_trampoline` called on {self:?}"),
419 }
420 }
421
422 #[cfg(feature = "component-model")]
424 pub fn unwrap_resource_drop_trampoline(self) {
425 match self {
426 Self::ResourceDropTrampoline => {}
427 _ => panic!("`FuncKey::unwrap_resource_drop_trampoline` called on {self:?}"),
428 }
429 }
430}