in uniffi_bindgen/src/interface/enum_.rs [383:526]
fn test_associated_data() {
const UDL: &str = r#"
namespace test {
void takes_an_enum(TestEnum e);
void takes_an_enum_with_data(TestEnumWithData ed);
TestEnum returns_an_enum();
TestEnumWithData returns_an_enum_with_data();
};
enum TestEnum { "one", "two" };
[Enum]
interface TestEnumWithData {
Zero();
One(u32 first);
Two(u32 first, string second);
};
[Enum]
interface TestEnumWithoutData {
One();
Two();
};
"#;
let ci = ComponentInterface::from_webidl(UDL, "crate_name").unwrap();
assert_eq!(ci.enum_definitions().count(), 3);
assert_eq!(ci.function_definitions().len(), 4);
// The "flat" enum with no associated data.
let e = ci.get_enum_definition("TestEnum").unwrap();
assert!(e.is_flat());
assert_eq!(e.variants().len(), 2);
assert_eq!(
e.variants().iter().map(|v| v.name()).collect::<Vec<_>>(),
vec!["one", "two"]
);
assert_eq!(e.variants()[0].fields().len(), 0);
assert_eq!(e.variants()[1].fields().len(), 0);
// The enum with associated data.
let ed = ci.get_enum_definition("TestEnumWithData").unwrap();
assert!(!ed.is_flat());
assert_eq!(ed.shape, EnumShape::Enum);
assert_eq!(ed.variants().len(), 3);
assert_eq!(
ed.variants().iter().map(|v| v.name()).collect::<Vec<_>>(),
vec!["Zero", "One", "Two"]
);
assert_eq!(ed.variants()[0].fields().len(), 0);
assert_eq!(
ed.variants()[1]
.fields()
.iter()
.map(|f| f.name())
.collect::<Vec<_>>(),
vec!["first"]
);
assert_eq!(
ed.variants()[1]
.fields()
.iter()
.map(|f| f.as_type())
.collect::<Vec<_>>(),
vec![Type::UInt32]
);
assert_eq!(
ed.variants()[2]
.fields()
.iter()
.map(|f| f.name())
.collect::<Vec<_>>(),
vec!["first", "second"]
);
assert_eq!(
ed.variants()[2]
.fields()
.iter()
.map(|f| f.as_type())
.collect::<Vec<_>>(),
vec![Type::UInt32, Type::String]
);
// The enum declared via interface, but with no associated data.
let ewd = ci.get_enum_definition("TestEnumWithoutData").unwrap();
assert_eq!(ewd.variants().len(), 2);
assert_eq!(
ewd.variants().iter().map(|v| v.name()).collect::<Vec<_>>(),
vec!["One", "Two"]
);
assert_eq!(ewd.variants()[0].fields().len(), 0);
assert_eq!(ewd.variants()[1].fields().len(), 0);
assert!(ewd.is_flat());
assert_eq!(ewd.shape, EnumShape::Enum);
// Flat enums pass over the FFI as bytebuffers.
// (It might be nice to optimize these to pass as plain integers, but that's
// difficult atop the current factoring of `ComponentInterface` and friends).
let farg = ci.get_function_definition("takes_an_enum").unwrap();
assert_eq!(
farg.arguments()[0].as_type(),
Type::Enum {
name: "TestEnum".into(),
module_path: "crate_name".into()
}
);
assert!(matches!(
farg.ffi_func().arguments()[0].type_(),
FfiType::RustBuffer(_)
));
let fret = ci.get_function_definition("returns_an_enum").unwrap();
assert!(
matches!(fret.return_type(), Some(Type::Enum { name, .. }) if name == "TestEnum" && !ci.is_name_used_as_error(name))
);
assert!(matches!(
fret.ffi_func().return_type(),
Some(FfiType::RustBuffer(_))
));
// Enums with associated data pass over the FFI as bytebuffers.
let farg = ci
.get_function_definition("takes_an_enum_with_data")
.unwrap();
assert_eq!(
farg.arguments()[0].as_type(),
Type::Enum {
name: "TestEnumWithData".into(),
module_path: "crate_name".into()
}
);
assert!(matches!(
farg.ffi_func().arguments()[0].type_(),
FfiType::RustBuffer(_)
));
let fret = ci
.get_function_definition("returns_an_enum_with_data")
.unwrap();
assert!(
matches!(fret.return_type(), Some(Type::Enum { name, .. }) if name == "TestEnumWithData" && !ci.is_name_used_as_error(name))
);
assert!(matches!(
fret.ffi_func().return_type(),
Some(FfiType::RustBuffer(_))
));
}