/// Custom Diplomat attribute that can be placed on a struct definition. #[derive(Debug)] enum DiplomatStructAttribute { /// The `#[diplomat::out]` attribute, used for non-opaque structs that /// contain an owned opaque in the form of a `Box`.
Out, /// The `#[diplomat::opaque]` attribute, used for marking a struct as opaque. /// Note that opaque structs can be borrowed in return types, but cannot /// be passed into a function behind a mutable reference.
Opaque, /// The `#[diplomat::opaque_mut]` attribute, used for marking a struct as /// opaque and mutable. /// Note that mutable opaque structs can never be borrowed in return types /// (even immutably!), but can be passed into a function behind a mutable /// reference.
OpaqueMut,
}
impl DiplomatStructAttribute { /// Parses a [`DiplomatStructAttribute`] from an array of [`syn::Attribute`]s. /// If more than one kind is found, an error is returned containing all the /// ones encountered, since all the current attributes are disjoint. fn parse(attrs: &[syn::Attribute]) -> Result<Option<Self>, Vec<Self>> { letmut buf = String::with_capacity(32); letmut res = Ok(None); for attr in attrs {
buf.clear();
write!(&mut buf, "{}", attr.path().to_token_stream()).unwrap(); let parsed = match buf.as_str() { "diplomat :: out" => Some(Self::Out), "diplomat :: opaque" => Some(Self::Opaque), "diplomat :: opaque_mut" => Some(Self::OpaqueMut),
_ => None,
};
iflet Some(parsed) = parsed { match res {
Ok(None) => res = Ok(Some(parsed)),
Ok(Some(first)) => res = Err(vec![first, parsed]),
Err(refmut errors) => errors.push(parsed),
}
}
}
self.declared_types.iter().for_each(|(k, v)| { if mod_symbols
.insert(k.clone(), ModSymbol::CustomType(v.clone()))
.is_some()
{
panic!("Two types were declared with the same name, this needs to be implemented");
}
});
let impl_parent_attrs: Attrs =
mod_attrs.attrs_for_inheritance(AttrInheritContext::MethodOrImplFromModule); let type_parent_attrs: Attrs = mod_attrs.attrs_for_inheritance(AttrInheritContext::Type);
input
.content
.as_ref()
.map(|t| &t.1[..])
.unwrap_or_default()
.iter()
.for_each(|a| match a {
Item::Use(u) => { if analyze_types {
extract_imports(&Path::empty(), &u.tree, &mut imports);
}
}
Item::Struct(strct) => { if analyze_types { let custom_type = match DiplomatStructAttribute::parse(&strct.attrs[..]) {
Ok(None) => CustomType::Struct(Struct::new(strct, false, &type_parent_attrs)),
Ok(Some(DiplomatStructAttribute::Out)) => {
CustomType::Struct(Struct::new(strct, true, &type_parent_attrs))
}
Ok(Some(DiplomatStructAttribute::Opaque)) => {
CustomType::Opaque(OpaqueStruct::new(strct, Mutability::Immutable, &type_parent_attrs))
}
Ok(Some(DiplomatStructAttribute::OpaqueMut)) => {
CustomType::Opaque(OpaqueStruct::new(strct, Mutability::Mutable, &type_parent_attrs))
}
Err(errors) => {
panic!("Multiple conflicting Diplomat struct attributes, there can be at most one: {errors:?}");
}
};
impl From<&syn::File> for File { /// Get all custom types across all modules defined in a given file. fn from(file: &syn::File) -> File { letmut out = BTreeMap::new();
file.items.iter().for_each(|i| { iflet Item::Mod(item_mod) = i {
out.insert(
item_mod.ident.to_string(),
Module::from_syn(item_mod, false),
);
}
});
File { modules: out }
}
}
#[cfg(test)] mod tests { use insta::{self, Settings};
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.20Bemerkung:
(vorverarbeitet am 2026-06-23)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.