Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bindgen-generated types conflict with other -sys crates #99

Open
bavshin-f5 opened this issue Nov 20, 2024 · 0 comments
Open

Bindgen-generated types conflict with other -sys crates #99

bavshin-f5 opened this issue Nov 20, 2024 · 0 comments

Comments

@bavshin-f5
Copy link
Collaborator

Our bindgen configuration does not filter the types and as a result we pollute nginx_sys with all the symbols from libc, pcre2 and OpenSSL.

At the very least, we should limit output to the nginx symbols and required dependencies:

    let bindings = bindgen::Builder::default()
        .allowlist_function("ngx_.*")
        .allowlist_type("ngx_.*")
        .allowlist_var("(NGX|NGINX|ngx|nginx)_.*")

but here's another annoying problem: nginx_sys::SSL is not the same type as openssl_sys::SSL and cannot be used interchangeably. Even though it's generated from the same header with the same layout, Rust compiler does not use structural typing and cannot infer the equivalence.
In practice that results in an extra noise and unsafety when using a high-level OpenSSL bindings. Whenever we need to call openssl::something, we'll have to cast nginx_sys:: types to openssl_sys:: and vice versa.

The same issue applies to pcre2, libc and likely windows-sys.
This could be solved by telling bindgen to skip the types and add imports from the correct crate:

        .blocklist_type("SSL|SSL_CTX|SESSION")
        .raw_line("use openssl_sys::{SSL,SSL_CTX,SSL_SESSION};")

The last remaining issue is that we lose all the automagically derived traits, as bindgen is no longer able to verify that the blocklisted struct field type implements Copy, Clone or Debug. This requires more advanced workarounds, such as providing our ParseCallbacks implementation:

use bindgen::callbacks::{DeriveTrait, ImplementsTrait};

struct NgxExternalTypes;

impl bindgen::callbacks::ParseCallbacks for NgxExternalTypes {
    fn blocklisted_type_implements_trait(&self, name: &str, derive_trait: DeriveTrait) -> Option<ImplementsTrait> {
        // name is not preprocessed and could be `struct x`, `const x`, `const struct x` etc.
        match name.split_ascii_whitespace().last()? {
            "in_addr" => Some(match derive_trait {
                DeriveTrait::Copy => ImplementsTrait::Yes,
                DeriveTrait::Debug => ImplementsTrait::Yes,
                DeriveTrait::Hash => ImplementsTrait::Yes,
                DeriveTrait::PartialEqOrPartialOrd => ImplementsTrait::Yes,
                _ => ImplementsTrait::No,
            }),
            "in6_addr" => Some(match derive_trait {
                DeriveTrait::Copy => ImplementsTrait::Yes,
                DeriveTrait::Hash => ImplementsTrait::Yes,
                DeriveTrait::PartialEqOrPartialOrd => ImplementsTrait::Yes,
                _ => ImplementsTrait::No,
            }),
            _ => None,
        }
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant