summaryrefslogtreecommitdiffstats
path: root/src/bindgen/ir/field.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bindgen/ir/field.rs')
-rw-r--r--src/bindgen/ir/field.rs80
1 files changed, 80 insertions, 0 deletions
diff --git a/src/bindgen/ir/field.rs b/src/bindgen/ir/field.rs
new file mode 100644
index 0000000..6e132bf
--- /dev/null
+++ b/src/bindgen/ir/field.rs
@@ -0,0 +1,80 @@
+use std::io::Write;
+
+use syn::ext::IdentExt;
+
+use crate::bindgen::cdecl;
+use crate::bindgen::config::{Config, Language};
+use crate::bindgen::ir::{AnnotationSet, Cfg, ConditionWrite};
+use crate::bindgen::ir::{Documentation, Path, ToCondition, Type};
+use crate::bindgen::writer::{Source, SourceWriter};
+
+#[derive(Debug, Clone)]
+pub struct Field {
+ pub name: String,
+ pub ty: Type,
+ pub cfg: Option<Cfg>,
+ pub annotations: AnnotationSet,
+ pub documentation: Documentation,
+}
+
+impl Field {
+ pub fn from_name_and_type(name: String, ty: Type) -> Field {
+ Field {
+ name,
+ ty,
+ cfg: None,
+ annotations: AnnotationSet::new(),
+ documentation: Documentation::none(),
+ }
+ }
+
+ pub fn load(field: &syn::Field, self_path: &Path) -> Result<Option<Field>, String> {
+ Ok(if let Some(mut ty) = Type::load(&field.ty)? {
+ ty.replace_self_with(self_path);
+ Some(Field {
+ name: field
+ .ident
+ .as_ref()
+ .ok_or_else(|| "field is missing identifier".to_string())?
+ .unraw()
+ .to_string(),
+ ty,
+ cfg: Cfg::load(&field.attrs),
+ annotations: AnnotationSet::load(&field.attrs)?,
+ documentation: Documentation::load(&field.attrs),
+ })
+ } else {
+ None
+ })
+ }
+}
+
+impl Source for Field {
+ fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
+ // Cython doesn't support conditional fields.
+ let condition = self.cfg.to_condition(config);
+ if config.language != Language::Cython {
+ condition.write_before(config, out);
+ }
+
+ self.documentation.write(config, out);
+ cdecl::write_field(out, &self.ty, &self.name, config);
+ // Cython extern declarations don't manage layouts, layouts are defined entierly by the
+ // corresponding C code. So we can omit bitfield sizes which are not supported by Cython.
+ if config.language != Language::Cython {
+ if let Some(bitfield) = self.annotations.atom("bitfield") {
+ write!(out, ": {}", bitfield.unwrap_or_default());
+ }
+ }
+
+ if config.language != Language::Cython {
+ condition.write_after(config, out);
+ // FIXME(#634): `write_vertical_source_list` should support
+ // configuring list elements natively. For now we print a newline
+ // here to avoid printing `#endif;` with semicolon.
+ if condition.is_some() {
+ out.new_line();
+ }
+ }
+ }
+}