Skip to content

Commit

Permalink
libbpf-cargo: Generate C enums as custom types with const fields
Browse files Browse the repository at this point in the history
Rather than generating Rust enums from C enums, which might not be
correct, as for example, C allows enum variants to share a value while
Rust does not.

This fixes #982.

Test Plan
=========

Verified that tests pass in CI in my fork and that my project compiles
fine and works well with this change.
  • Loading branch information
javierhonduco committed Nov 4, 2024
1 parent d65d1a5 commit 9f0de1c
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 30 deletions.
1 change: 1 addition & 0 deletions libbpf-cargo/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Unreleased
----------
- Fixed handling of empty unions in BPF types
- Represent C enums with custom types and const fields


0.24.6
Expand Down
26 changes: 10 additions & 16 deletions libbpf-cargo/src/gen/btf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,8 @@ impl<'s> GenBtf<'s> {
_ => bail!("Invalid enum size: {}", t.size()),
};

let enum_name = self.anon_types.type_name_or_anon(&t);

let mut signed = "u";
for value in t.iter() {
if value.value < 0 {
Expand All @@ -805,30 +807,22 @@ impl<'s> GenBtf<'s> {
}
}

writeln!(
def,
r#"#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]"#
)?;
writeln!(def, r#"#[repr({signed}{repr_size})]"#)?;
writeln!(
def,
r#"pub enum {name} {{"#,
name = self.anon_types.type_name_or_anon(&t),
)?;
writeln!(def, r#"#[derive(Debug, Copy, Clone, Default)]"#)?;
writeln!(def, r#"pub struct {enum_name}({signed}{repr_size});"#,)?;

for (i, value) in t.iter().enumerate() {
if i == 0 {
writeln!(def, r#" #[default]"#)?;
}
writeln!(def, r#"impl {enum_name} {{"#,)?;

for value in t.iter() {
writeln!(def, " #[allow(non_upper_case_globals)]")?;
writeln!(
def,
r#" {name} = {value},"#,
r#" pub const {name}: {enum_name} = {enum_name}({value});"#,
name = value.name.unwrap().to_string_lossy(),
value = value.value,
)?;
}

writeln!(def, "}}")?;
writeln!(def, r#"}}"#,)?;
Ok(())
}

Expand Down
29 changes: 15 additions & 14 deletions libbpf-cargo/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1824,13 +1824,15 @@ enum Foo foo;
"#;

let expected_output = r#"
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
#[repr(u32)]
pub enum Foo {
#[default]
Zero = 0,
One = 1,
seven = 7,
#[derive(Debug, Copy, Clone, Default)]
pub struct Foo(u32);
impl Foo {
#[allow(non_upper_case_globals)]
pub const Zero: Foo = Foo(0);
#[allow(non_upper_case_globals)]
pub const One: Foo = Foo(1);
#[allow(non_upper_case_globals)]
pub const seven: Foo = Foo(7);
}
"#;

Expand Down Expand Up @@ -2565,13 +2567,12 @@ impl Default for Foo {
}
}
}
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
#[repr(u32)]
pub enum __anon_1 {
#[default]
FOO = 1,
}
"#;
#[derive(Debug, Copy, Clone, Default)]
pub struct __anon_1(u32);
impl __anon_1 {
#[allow(non_upper_case_globals)]
pub const FOO: __anon_1 = __anon_1(1);
}"#;

let mmap = build_btf_mmap(prog_text);
let btf = btf_from_mmap(&mmap);
Expand Down

0 comments on commit 9f0de1c

Please sign in to comment.