/// a concrete Deref to the Rust trait.
fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, types: &mut TypeResolver<'b, 'a>, extra_headers: &mut File, cpp_headers: &mut File) {
let trait_name = format!("{}", t.ident);
+ let implementable;
match export_status(&t.attrs) {
- ExportStatus::Export => {},
+ ExportStatus::Export => { implementable = true; }
+ ExportStatus::NotImplementable => { implementable = false; },
ExportStatus::NoExport|ExportStatus::TestOnly => return,
}
writeln_docs(w, &t.attrs, "");
},
ExportStatus::Export => {},
ExportStatus::TestOnly => continue,
+ ExportStatus::NotImplementable => panic!("(C-not implementable) must only appear on traits"),
}
if m.default.is_some() { unimplemented!(); }
// Finally, implement the original Rust trait for the newly created mapped trait.
writeln!(w, "\nuse {}::{} as rust{};", types.module_path, t.ident, trait_name).unwrap();
- write!(w, "impl rust{}", t.ident).unwrap();
- maybe_write_generics(w, &t.generics, types, false);
- writeln!(w, " for {} {{", trait_name).unwrap();
- impl_trait_for_c!(t, "", types);
- writeln!(w, "}}\n").unwrap();
- writeln!(w, "// We're essentially a pointer already, or at least a set of pointers, so allow us to be used").unwrap();
- writeln!(w, "// directly as a Deref trait in higher-level structs:").unwrap();
- writeln!(w, "impl std::ops::Deref for {} {{\n\ttype Target = Self;", trait_name).unwrap();
- writeln!(w, "\tfn deref(&self) -> &Self {{\n\t\tself\n\t}}\n}}").unwrap();
+ if implementable {
+ write!(w, "impl rust{}", t.ident).unwrap();
+ maybe_write_generics(w, &t.generics, types, false);
+ writeln!(w, " for {} {{", trait_name).unwrap();
+ impl_trait_for_c!(t, "", types);
+ writeln!(w, "}}\n").unwrap();
+ writeln!(w, "// We're essentially a pointer already, or at least a set of pointers, so allow us to be used").unwrap();
+ writeln!(w, "// directly as a Deref trait in higher-level structs:").unwrap();
+ writeln!(w, "impl std::ops::Deref for {} {{\n\ttype Target = Self;", trait_name).unwrap();
+ writeln!(w, "\tfn deref(&self) -> &Self {{\n\t\tself\n\t}}\n}}").unwrap();
+ }
writeln!(w, "/// Calls the free function if one is set").unwrap();
writeln!(w, "#[no_mangle]\npub extern \"C\" fn {}_free(this_ptr: {}) {{ }}", trait_name, trait_name).unwrap();
all_fields_settable = false;
continue
},
+ ExportStatus::NotImplementable => panic!("(C-not implementable) must only appear on traits"),
}
if let Some(ident) = &field.ident {
match export_status(&i.attrs) {
ExportStatus::Export => {},
ExportStatus::NoExport|ExportStatus::TestOnly => return,
+ ExportStatus::NotImplementable => panic!("(C-not implementable) must only appear on traits"),
}
if let syn::Type::Tuple(_) = &*i.self_ty {
let export = export_status(&trait_obj.attrs);
match export {
- ExportStatus::Export => {},
+ ExportStatus::Export|ExportStatus::NotImplementable => {},
ExportStatus::NoExport|ExportStatus::TestOnly => return,
}
continue;
},
ExportStatus::TestOnly => continue,
+ ExportStatus::NotImplementable => panic!("(C-not implementable) must only appear on traits"),
}
let mut printed = false;
match export_status(&trait_method.attrs) {
ExportStatus::Export => {},
ExportStatus::NoExport|ExportStatus::TestOnly => continue,
+ ExportStatus::NotImplementable => panic!("(C-not implementable) must only appear on traits"),
}
if let syn::ReturnType::Type(_, _) = &$m.sig.output {
match export_status(&m.attrs) {
ExportStatus::Export => {},
ExportStatus::NoExport|ExportStatus::TestOnly => continue,
+ ExportStatus::NotImplementable => panic!("(C-not implementable) must only appear on traits"),
}
if m.defaultness.is_some() { unimplemented!(); }
writeln_docs(w, &m.attrs, "");
match export_status(&e.attrs) {
ExportStatus::Export => {},
ExportStatus::NoExport|ExportStatus::TestOnly => return,
+ ExportStatus::NotImplementable => panic!("(C-not implementable) must only appear on traits"),
}
if is_enum_opaque(e) {
match export_status(&f.attrs) {
ExportStatus::Export => {},
ExportStatus::NoExport|ExportStatus::TestOnly => return,
+ ExportStatus::NotImplementable => panic!("(C-not implementable) must only appear on traits"),
}
writeln_docs(w, &f.attrs, "");
match export_status(&t.attrs) {
ExportStatus::Export => {},
ExportStatus::NoExport|ExportStatus::TestOnly => continue,
+ ExportStatus::NotImplementable => panic!("(C-not implementable) must only appear on traits"),
}
let mut process_alias = true;
match export_status(&s.attrs) {
ExportStatus::Export => {},
ExportStatus::NoExport|ExportStatus::TestOnly => continue,
+ ExportStatus::NotImplementable => panic!("(C-not implementable) must only appear on traits"),
}
let struct_path = format!("{}::{}", module, s.ident);
crate_types.opaques.insert(struct_path, &s.ident);
syn::Item::Trait(t) => {
if let syn::Visibility::Public(_) = t.vis {
match export_status(&t.attrs) {
- ExportStatus::Export => {},
+ ExportStatus::Export|ExportStatus::NotImplementable => {},
ExportStatus::NoExport|ExportStatus::TestOnly => continue,
}
let trait_path = format!("{}::{}", module, t.ident);
match export_status(&t.attrs) {
ExportStatus::Export => {},
ExportStatus::NoExport|ExportStatus::TestOnly => continue,
+ ExportStatus::NotImplementable => panic!("(C-not implementable) must only appear on traits"),
}
let type_path = format!("{}::{}", module, t.ident);
let mut process_alias = true;
match export_status(&e.attrs) {
ExportStatus::Export => {},
ExportStatus::NoExport|ExportStatus::TestOnly => continue,
+ ExportStatus::NotImplementable => panic!("(C-not implementable) must only appear on traits"),
}
let enum_path = format!("{}::{}", module, e.ident);
crate_types.opaques.insert(enum_path, &e.ident);
match export_status(&e.attrs) {
ExportStatus::Export => {},
ExportStatus::NoExport|ExportStatus::TestOnly => continue,
+ ExportStatus::NotImplementable => panic!("(C-not implementable) must only appear on traits"),
}
let enum_path = format!("{}::{}", module, e.ident);
crate_types.mirrored_enums.insert(enum_path, &e);
Export,
NoExport,
TestOnly,
+ /// This is used only for traits to indicate that users should not be able to implement their
+ /// own version of a trait, but we should export Rust implementations of the trait (and the
+ /// trait itself).
+ /// Concretly, this means that we do not implement the Rust trait for the C trait struct.
+ NotImplementable,
}
/// Gets the ExportStatus of an object (struct, fn, etc) given its attributes.
pub fn export_status(attrs: &[syn::Attribute]) -> ExportStatus {
let line = format!("{}", lit);
if line.contains("(C-not exported)") {
return ExportStatus::NoExport;
+ } else if line.contains("(C-not implementable)") {
+ return ExportStatus::NotImplementable;
}
},
_ => unimplemented!(),
for field in fields.named.iter() {
match export_status(&field.attrs) {
ExportStatus::Export|ExportStatus::TestOnly => {},
+ ExportStatus::NotImplementable => panic!("(C-not implementable) should only appear on traits!"),
ExportStatus::NoExport => return true,
}
}
for field in fields.unnamed.iter() {
match export_status(&field.attrs) {
ExportStatus::Export|ExportStatus::TestOnly => {},
+ ExportStatus::NotImplementable => panic!("(C-not implementable) should only appear on traits!"),
ExportStatus::NoExport => return true,
}
}
ExportStatus::Export => { declared.insert(s.ident.clone(), DeclType::StructImported); },
ExportStatus::NoExport => { declared.insert(s.ident.clone(), DeclType::StructIgnored); },
ExportStatus::TestOnly => continue,
+ ExportStatus::NotImplementable => panic!("(C-not implementable) should only appear on traits!"),
}
}
},
match export_status(&e.attrs) {
ExportStatus::Export if is_enum_opaque(e) => { declared.insert(e.ident.clone(), DeclType::EnumIgnored); },
ExportStatus::Export => { declared.insert(e.ident.clone(), DeclType::MirroredEnum); },
+ ExportStatus::NotImplementable => panic!("(C-not implementable) should only appear on traits!"),
_ => continue,
}
}
},
- syn::Item::Trait(t) if export_status(&t.attrs) == ExportStatus::Export => {
- if let syn::Visibility::Public(_) = t.vis {
- declared.insert(t.ident.clone(), DeclType::Trait(t));
+ syn::Item::Trait(t) => {
+ match export_status(&t.attrs) {
+ ExportStatus::Export|ExportStatus::NotImplementable => {
+ if let syn::Visibility::Public(_) = t.vis {
+ declared.insert(t.ident.clone(), DeclType::Trait(t));
+ }
+ },
+ _ => continue,
}
},
syn::Item::Mod(m) => {