use anyhow::Result;
use uniffi_meta::Checksum;
use super::enum_::{Enum, Variant};
use super::types::{Type, TypeIterator};
use super::{APIConverter, ComponentInterface};
#[derive(Debug, Clone, PartialEq, Eq, Checksum)]
pub struct Error {
pub name: String,
enum_: Enum,
}
impl Error {
pub fn from_enum(enum_: Enum) -> Self {
Self {
name: enum_.name.clone(),
enum_,
}
}
pub fn type_(&self) -> Type {
Type::Error(self.name.clone())
}
pub fn name(&self) -> &str {
&self.name
}
pub fn wrapped_enum(&self) -> &Enum {
&self.enum_
}
pub fn variants(&self) -> &[Variant] {
self.enum_.variants()
}
pub fn is_flat(&self) -> bool {
self.enum_.is_flat()
}
pub fn iter_types(&self) -> TypeIterator<'_> {
self.wrapped_enum().iter_types()
}
}
impl From<uniffi_meta::ErrorMetadata> for Error {
fn from(meta: uniffi_meta::ErrorMetadata) -> Self {
Self {
name: meta.name.clone(),
enum_: Enum {
name: meta.name,
variants: meta.variants.into_iter().map(Into::into).collect(),
flat: meta.flat,
},
}
}
}
impl APIConverter<Error> for weedle::EnumDefinition<'_> {
fn convert(&self, ci: &mut ComponentInterface) -> Result<Error> {
Ok(Error::from_enum(APIConverter::<Enum>::convert(self, ci)?))
}
}
impl APIConverter<Error> for weedle::InterfaceDefinition<'_> {
fn convert(&self, ci: &mut ComponentInterface) -> Result<Error> {
Ok(Error::from_enum(APIConverter::<Enum>::convert(self, ci)?))
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_variants() {
const UDL: &str = r#"
namespace test{};
[Error]
enum Testing { "one", "two", "three" };
"#;
let ci = ComponentInterface::from_webidl(UDL).unwrap();
assert_eq!(ci.error_definitions().count(), 1);
let error = ci.get_error_definition("Testing").unwrap();
assert_eq!(
error
.variants()
.iter()
.map(|v| v.name())
.collect::<Vec<&str>>(),
vec!("one", "two", "three")
);
assert!(error.is_flat());
}
#[test]
fn test_duplicate_variants() {
const UDL: &str = r#"
namespace test{};
// Weird, but currently allowed!
// We should probably disallow this...
[Error]
enum Testing { "one", "two", "one" };
"#;
let ci = ComponentInterface::from_webidl(UDL).unwrap();
assert_eq!(ci.error_definitions().count(), 1);
assert_eq!(
ci.get_error_definition("Testing").unwrap().variants().len(),
3
);
}
#[test]
fn test_variant_data() {
const UDL: &str = r#"
namespace test{};
[Error]
interface Testing {
One(string reason);
Two(u8 code);
};
"#;
let ci = ComponentInterface::from_webidl(UDL).unwrap();
assert_eq!(ci.error_definitions().count(), 1);
let error: &Error = ci.get_error_definition("Testing").unwrap();
assert_eq!(
error
.variants()
.iter()
.map(|v| v.name())
.collect::<Vec<&str>>(),
vec!("One", "Two")
);
assert!(!error.is_flat());
}
}