From 5a152897f2a72a6a169c12114482dd3422e5c05a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 10 Nov 2017 16:24:04 +0100 Subject: [PATCH 1/2] Generate Debug for sys types --- src/codegen/sys/lib_.rs | 106 ++++++++++++++++++++++++++++++++++--- src/codegen/sys/statics.rs | 1 + 2 files changed, 100 insertions(+), 7 deletions(-) diff --git a/src/codegen/sys/lib_.rs b/src/codegen/sys/lib_.rs index bc01381df..20c517a35 100644 --- a/src/codegen/sys/lib_.rs +++ b/src/codegen/sys/lib_.rs @@ -342,6 +342,9 @@ fn generate_unions(w: &mut Write, env: &Env, items: &[&Union]) -> Result<()> { } try!(writeln!(w, "{}}}\n", comment)); } + if comment.is_empty() { + try!(generate_fields_with_debug(w, name, &lines)); + } } #[cfg(not(feature = "use_unions"))] { @@ -354,9 +357,11 @@ fn generate_unions(w: &mut Write, env: &Env, items: &[&Union]) -> Result<()> { w, "#[cfg(target_pointer_width = \"32\")]\n\ #[repr(C)]\n\ + #[derive(Debug)]\n\ pub struct {0}([u32; 2]);\n\ #[cfg(target_pointer_width = \"64\")]\n\ #[repr(C)]\n\ + #[derive(Debug)]\n\ pub struct {0}(*mut c_void);", c_type )); @@ -376,6 +381,57 @@ fn generate_unions(w: &mut Write, env: &Env, items: &[&Union]) -> Result<()> { Ok(()) } +fn generate_debug_impl(w: &mut Write, name: &str, impl_content: &str) -> Result<()> { + writeln!( + w, + "impl ::std::fmt::Debug for {} {{\n\ + \tfn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {{\n\ + \t\t{}\n\ + \t}}\n\ + }}\n", + name, + impl_content) +} + +fn generate_fields_with_debug(w: &mut Write, name: &str, lines: &[String]) -> Result<()> { + let non_commented_fields = lines.iter() + .filter(|f| !f.contains("//")) + .count(); + let fields_formatters = ::std::iter::repeat("{:?}".to_owned()) + .take(non_commented_fields) + .collect::>() + .join(", "); + let fields_arguments = + lines.iter() + .filter_map(|field| { + if field.contains("//") { + None + } else { + Some(if field.replace(",", "").trim().ends_with("c_void") { + format!("\t\t \"c_void\"") + } else { + format!("\t\t self.{}", + field.split(":").next().unwrap().trim().replace("pub ", "")) + }) + } + }) + .collect::>() + .join(",\n"); + + generate_debug_impl( + w, + name, + &format!( + "write!(f, \"{name} @ {{:?}} {{{{ {fields}}}}}\",\n\ + \t\t self as *const _,\n\ + {fields_name})", + name=name, + fields=fields_formatters, + fields_name=fields_arguments, + ) + ) +} + fn generate_classes_structs(w: &mut Write, env: &Env, classes: &[&Class]) -> Result<()> { if !classes.is_empty() { try!(writeln!(w, "// Classes")); @@ -389,20 +445,32 @@ fn generate_classes_structs(w: &mut Write, env: &Env, classes: &[&Class]) -> Res w, "{comment}#[repr(C)]\n{comment}pub struct {name}(c_void);\n", comment = comment, - name = klass.c_type + name = klass.c_type, + )); + try!(generate_debug_impl( + w, + &klass.c_type, + &format!("write!(f, \"{name} @ {{:?}}\", self as *const _)", + name=klass.c_type) )); } else { + let can_generate_fields_debug = can_generate_fields_debug(&klass.fields); try!(writeln!( w, - "{comment}#[repr(C)]\n{comment}pub struct {name} {{", + "{comment}#[repr(C)]\n{debug}{comment}pub struct {name} {{", comment = comment, - name = klass.c_type + debug = if can_generate_fields_debug { "#[derive(Debug)]\n" } else { "" }, + name = klass.c_type, )); - for line in lines { + for line in &lines { try!(writeln!(w, "{}{}", comment, line)); } try!(writeln!(w, "{}}}\n", comment)); + + if !can_generate_fields_debug && comment.is_empty() { + try!(generate_fields_with_debug(w, &klass.c_type, &lines)); + } } } @@ -416,9 +484,15 @@ fn generate_interfaces_structs(w: &mut Write, interfaces: &[&Interface]) -> Resu for interface in interfaces { try!(writeln!( w, - "#[repr(C)]\npub struct {}(c_void);", + "#[repr(C)]\npub struct {}(c_void);\n", interface.c_type )); + try!(generate_debug_impl( + w, + &interface.c_type, + &format!("write!(f, \"{name} @ {{:?}}\", self as *const _)", + name=interface.c_type) + )); } if !interfaces.is_empty() { try!(writeln!(w, "")); @@ -427,6 +501,15 @@ fn generate_interfaces_structs(w: &mut Write, interfaces: &[&Interface]) -> Resu Ok(()) } +fn can_generate_fields_debug(f: &[Field]) -> bool { + !f.iter().any(|f| { + match f.c_type { + Some(ref s) if s.as_str() == "c_void" => false, + _ => true, + } + }) +} + fn generate_records(w: &mut Write, env: &Env, records: &[&Record]) -> Result<()> { if !records.is_empty() { try!(writeln!(w, "// Records")); @@ -456,15 +539,24 @@ fn generate_records(w: &mut Write, env: &Env, records: &[&Record]) -> Result<()> } try!(writeln!( w, - "{}#[repr(C)]\n{0}pub struct {} {{", + "{}#[repr(C)]\n{}{0}pub struct {} {{", comment, + if can_generate_fields_debug(&record.fields) { "#[derive(Debug)]\n" } else { "" }, record.c_type )); - for line in lines { + for line in &lines { try!(writeln!(w, "{}{}", comment, line)); } try!(writeln!(w, "{}}}\n", comment)); } + if lines.is_empty() || !can_generate_fields_debug(&record.fields) { + try!(generate_debug_impl( + w, + &record.c_type, + &format!("write!(f, \"{name} @ {{:?}}\", self as *const _)", + name=record.c_type) + )); + } } Ok(()) } diff --git a/src/codegen/sys/statics.rs b/src/codegen/sys/statics.rs index f8bbe9a1e..14931ec9d 100644 --- a/src/codegen/sys/statics.rs +++ b/src/codegen/sys/statics.rs @@ -52,6 +52,7 @@ pub fn only_for_glib(w: &mut Write) -> Result<()> { "pub type gpointer = *mut c_void;", "", "#[repr(C)]", + "#[derive(Debug)]", "pub struct Volatile(T);", "", ]; From 54a102e0efcadf16e32c55a8b6cdb0e92ca65fc1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 11 Nov 2017 13:22:28 +0100 Subject: [PATCH 2/2] Use debug_struct instead --- src/codegen/sys/lib_.rs | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/src/codegen/sys/lib_.rs b/src/codegen/sys/lib_.rs index 20c517a35..d32722b15 100644 --- a/src/codegen/sys/lib_.rs +++ b/src/codegen/sys/lib_.rs @@ -343,7 +343,7 @@ fn generate_unions(w: &mut Write, env: &Env, items: &[&Union]) -> Result<()> { try!(writeln!(w, "{}}}\n", comment)); } if comment.is_empty() { - try!(generate_fields_with_debug(w, name, &lines)); + try!(generate_debug_with_fields(w, name, &lines)); } } #[cfg(not(feature = "use_unions"))] @@ -393,41 +393,31 @@ fn generate_debug_impl(w: &mut Write, name: &str, impl_content: &str) -> Result< impl_content) } -fn generate_fields_with_debug(w: &mut Write, name: &str, lines: &[String]) -> Result<()> { - let non_commented_fields = lines.iter() - .filter(|f| !f.contains("//")) - .count(); - let fields_formatters = ::std::iter::repeat("{:?}".to_owned()) - .take(non_commented_fields) - .collect::>() - .join(", "); - let fields_arguments = +fn generate_debug_with_fields(w: &mut Write, name: &str, lines: &[String]) -> Result<()> { + let fields = lines.iter() .filter_map(|field| { if field.contains("//") { None } else { + let field_name = field.split(":").next().unwrap().trim().replace("pub ", ""); Some(if field.replace(",", "").trim().ends_with("c_void") { - format!("\t\t \"c_void\"") + format!("\t\t .field(\"{name}\", &\"c_void\")\n", name=field_name) } else { - format!("\t\t self.{}", - field.split(":").next().unwrap().trim().replace("pub ", "")) + format!("\t\t .field(\"{name}\", &self.{name})\n", name=field_name) }) } }) - .collect::>() - .join(",\n"); + .collect::(); generate_debug_impl( w, name, - &format!( - "write!(f, \"{name} @ {{:?}} {{{{ {fields}}}}}\",\n\ - \t\t self as *const _,\n\ - {fields_name})", - name=name, - fields=fields_formatters, - fields_name=fields_arguments, + &format!("f.debug_struct(&format!(\"{name} @ {{:?}}\", self as *const _))\n\ + {fields}\ + \t\t .finish()", + name=name, + fields=fields, ) ) } @@ -469,7 +459,7 @@ fn generate_classes_structs(w: &mut Write, env: &Env, classes: &[&Class]) -> Res try!(writeln!(w, "{}}}\n", comment)); if !can_generate_fields_debug && comment.is_empty() { - try!(generate_fields_with_debug(w, &klass.c_type, &lines)); + try!(generate_debug_with_fields(w, &klass.c_type, &lines)); } } }