1 //! Limits for the `gc` operations.
2 
3 use serde::{Deserialize, Serialize};
4 use std::ops::RangeInclusive;
5 
6 /// Range for the number of parameters.
7 pub const NUM_PARAMS_RANGE: RangeInclusive<u32> = 0..=10;
8 /// Range for the maximum number of types.
9 pub const MAX_TYPES_RANGE: RangeInclusive<u32> = 0..=32;
10 /// Range for the number of globals.
11 pub const NUM_GLOBALS_RANGE: RangeInclusive<u32> = 0..=10;
12 /// Range for the table size.
13 pub const TABLE_SIZE_RANGE: RangeInclusive<u32> = 0..=100;
14 /// Range for the maximum number of rec groups.
15 pub const MAX_REC_GROUPS_RANGE: RangeInclusive<u32> = 0..=10;
16 /// Maximum number of operations.
17 pub const MAX_OPS: usize = 100;
18 
19 /// Limits controlling the structure of a generated Wasm module.
20 #[derive(Debug, Default, Serialize, Deserialize)]
21 pub struct GcOpsLimits {
22     pub(crate) num_params: u32,
23     pub(crate) num_globals: u32,
24     pub(crate) table_size: u32,
25     pub(crate) max_rec_groups: u32,
26     pub(crate) max_types: u32,
27 }
28 impl GcOpsLimits {
29     /// Fixup the limits to ensure they are within the valid range.
fixup(&mut self)30     pub(crate) fn fixup(&mut self) {
31         // NB: Exhaustively match so that we remember to fixup any other new
32         // limits we add in the future.
33         let Self {
34             num_params,
35             num_globals,
36             table_size,
37             max_rec_groups,
38             max_types,
39         } = self;
40 
41         let clamp = |limit: &mut u32, range: RangeInclusive<u32>| {
42             *limit = (*limit).clamp(*range.start(), *range.end())
43         };
44         clamp(table_size, TABLE_SIZE_RANGE);
45         clamp(num_params, NUM_PARAMS_RANGE);
46         clamp(num_globals, NUM_GLOBALS_RANGE);
47         clamp(max_rec_groups, MAX_REC_GROUPS_RANGE);
48         clamp(max_types, MAX_TYPES_RANGE);
49     }
50 }
51