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