Skip to content

Commit ac798ee

Browse files
authored
Make the variant tag size match the Canonical ABI. (#1467)
The `discriminant_type` function in the [Canonical ABI] returns `u8` for a variant with 256 cases. Fix wit-parser's `tag()` function to match it. [Canonical ABI]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md
1 parent 7803d17 commit ac798ee

1 file changed

Lines changed: 30 additions & 12 deletions

File tree

crates/wit-parser/src/lib.rs

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -570,12 +570,7 @@ pub struct Case {
570570

571571
impl Variant {
572572
pub fn tag(&self) -> Int {
573-
match self.cases.len() {
574-
n if n <= u8::max_value() as usize => Int::U8,
575-
n if n <= u16::max_value() as usize => Int::U16,
576-
n if n <= u32::max_value() as usize => Int::U32,
577-
_ => panic!("too many cases to fit in a repr"),
578-
}
573+
discriminant_type(self.cases.len())
579574
}
580575
}
581576

@@ -595,12 +590,18 @@ pub struct EnumCase {
595590

596591
impl Enum {
597592
pub fn tag(&self) -> Int {
598-
match self.cases.len() {
599-
n if n <= u8::max_value() as usize => Int::U8,
600-
n if n <= u16::max_value() as usize => Int::U16,
601-
n if n <= u32::max_value() as usize => Int::U32,
602-
_ => panic!("too many cases to fit in a repr"),
603-
}
593+
discriminant_type(self.cases.len())
594+
}
595+
}
596+
597+
/// This corresponds to the `discriminant_type` function in the Canonical ABI.
598+
fn discriminant_type(num_cases: usize) -> Int {
599+
match num_cases.checked_sub(1) {
600+
None => Int::U8,
601+
Some(n) if n <= u8::max_value() as usize => Int::U8,
602+
Some(n) if n <= u16::max_value() as usize => Int::U16,
603+
Some(n) if n <= u32::max_value() as usize => Int::U32,
604+
_ => panic!("too many cases to fit in a repr"),
604605
}
605606
}
606607

@@ -745,3 +746,20 @@ impl Function {
745746
}
746747
}
747748
}
749+
750+
#[cfg(test)]
751+
mod test {
752+
use super::*;
753+
754+
#[test]
755+
fn test_discriminant_type() {
756+
assert_eq!(discriminant_type(1), Int::U8);
757+
assert_eq!(discriminant_type(0x100), Int::U8);
758+
assert_eq!(discriminant_type(0x101), Int::U16);
759+
assert_eq!(discriminant_type(0x10000), Int::U16);
760+
assert_eq!(discriminant_type(0x10001), Int::U32);
761+
if let Ok(num_cases) = usize::try_from(0x100000000_u64) {
762+
assert_eq!(discriminant_type(num_cases), Int::U32);
763+
}
764+
}
765+
}

0 commit comments

Comments
 (0)