summaryrefslogtreecommitdiff
path: root/src/codegen/mod.rs
diff options
context:
space:
mode:
authorSebastian Imlay <sebastian.imlay@gmail.com>2020-08-28 16:30:47 -0700
committerEmilio Cobos Álvarez <emilio@crisal.io>2020-09-16 12:26:24 +0200
commit81d323d8b1f81f298e59cd72eff5e57e381f55ac (patch)
tree785d708341b2513eb0e4091ca95e16adec98d489 /src/codegen/mod.rs
parent840b738ecfeefbd31d8676c60e2eca7ad6d0f424 (diff)
Updates base on comments
* Added TryInto trait implementation from parent to child interfaces. * Added HashSet for protocols so that the protocol inheritance works as well.
Diffstat (limited to 'src/codegen/mod.rs')
-rw-r--r--src/codegen/mod.rs47
1 files changed, 41 insertions, 6 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index 7ae202bf..de4721f6 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -49,6 +49,7 @@ use crate::{Entry, HashMap, HashSet};
use std;
use std::borrow::Cow;
use std::cell::Cell;
+use std::collections::HashSet as CollectionHashSet;
use std::collections::VecDeque;
use std::fmt::Write;
use std::iter;
@@ -3921,11 +3922,13 @@ impl CodeGenerator for ObjCInterface {
}
};
result.push(struct_block);
+ let mut protocol_set : CollectionHashSet<ItemId> = CollectionHashSet::new();
for protocol_id in self.conforms_to.iter() {
+ protocol_set.insert(*protocol_id);
let protocol_name = ctx.rust_ident(
ctx.resolve_type(protocol_id.expect_type_id(ctx))
- .name()
- .unwrap(),
+ .name()
+ .unwrap(),
);
let impl_trait = quote! {
impl #protocol_name for #class_name { }
@@ -3962,16 +3965,48 @@ impl CodeGenerator for ObjCInterface {
}
};
result.push(impl_trait);
+ for protocol_id in parent.conforms_to.iter() {
+ if !protocol_set.contains(protocol_id) {
+
+ protocol_set.insert(*protocol_id);
+ let protocol_name = ctx.rust_ident(
+ ctx.resolve_type(protocol_id.expect_type_id(ctx))
+ .name()
+ .unwrap(),
+ );
+ let impl_trait = quote! {
+ impl #protocol_name for #class_name { }
+ };
+ result.push(impl_trait);
+ }
+ }
if !parent.is_template() {
- let parent_struct_name = ctx.rust_ident(parent.name());
+ let parent_struct_name = parent.name();
+ let child_struct_name = self.name();
+ let parent_struct = ctx.rust_ident(parent_struct_name);
let from_block = quote! {
- impl From<#class_name> for #parent_struct_name {
- fn from(child: #class_name) -> #parent_struct_name {
- #parent_struct_name(child.0)
+ impl From<#class_name> for #parent_struct {
+ fn from(child: #class_name) -> #parent_struct {
+ #parent_struct(child.0)
}
}
};
result.push(from_block);
+
+ let try_into_block = quote! {
+ impl std::convert::TryFrom<#parent_struct> for #class_name {
+ type Error = String;
+ fn try_from(parent: #parent_struct) -> Result<#class_name, Self::Error> {
+ let is_kind_of : bool = unsafe { msg_send!(parent, isKindOfClass:class!(#class_name))};
+ if is_kind_of {
+ Ok(#class_name(parent.0))
+ } else {
+ Err(format!("This {} is not an cannot be downcasted to {}", #parent_struct_name, #child_struct_name))
+ }
+ }
+ }
+ };
+ result.push(try_into_block);
}
parent.parent_class
} else {