GithubHelp home page GithubHelp logo

Evaluate `const`s via evaluation about cbindgen HOT 2 OPEN

tgross35 avatar tgross35 commented on August 27, 2024 1
Evaluate `const`s via evaluation

from cbindgen.

Comments (2)

tgross35 avatar tgross35 commented on August 27, 2024

Actually, maybe we could use the rustdoc JSON output? It is unstable, but it includes the following:

    "0:3:1735": {
      "id": "0:3:1735",
      "crate_id": 0,
      "name": "I_AM_A_CONST",
      "span": {
        "filename": "rcrypto/src/lib.rs",
        "begin": [
          1,
          0
        ],
        "end": [
          1,
          38
        ]
      },
      "visibility": "public",
      "docs": null,
      "links": {},
      "attrs": [],
      "deprecation": null,
      "inner": {
        "constant": {
          "type": {
            "primitive": "usize"
          },
          "expr": "_",
          "value": "63_737usize",
          "is_literal": false
        }
      }
    },

from this

pub const I_AM_A_CONST: usize = foo();

/// export thing
pub const fn foo() -> usize {
    63737
}

from cbindgen.

tgross35 avatar tgross35 commented on August 27, 2024

Yes, rustdoc can do it! I needed to move bindings generation to a new binary crate (Cargo deadlocks if you call cargo rustdoc from within build.rs...) and this only works for integers, but the recipe is here

My consts are a mess, generated in macros

        /// Length of the nonce (initialization vector) for
        #[doc = $name]
        pub const $noncebytes: usize = <$alg as aead::AeadCore>::NonceSize::USIZE;

        /// Length of the key for
        #[doc = $name]
        pub const $keybytes: usize = <$alg as aead::KeySizeUser>::KeySize::USIZE;

        /// Length of the MAC (tag) for
        #[doc = $name]
        pub const $macbytes: usize = <$alg as aead::AeadCore>::TagSize::USIZE;

But using this strategy I get the full correct thing:

#define RC_AEAD_AES128GCM_NONCEBYTES 12
#define RC_AEAD_AES128GCM_KEYBYTES 16
#define RC_AEAD_AES128GCM_MACBYTES 16
#define RC_AEAD_AES256GCM_NONCEBYTES 12
#define RC_AEAD_AES256GCM_KEYBYTES 32
#define RC_AEAD_AES256GCM_MACBYTES 16
#define RC_AEAD_CHACHA20POLY1305_NONCEBYTES 12
#define RC_AEAD_CHACHA20POLY1305_KEYBYTES 32
#define RC_AEAD_CHACHA20POLY1305_MACBYTES 16
#define RC_AEAD_XCHACHA20POLY1305_NONCEBYTES 24
#define RC_AEAD_XCHACHA20POLY1305_KEYBYTES 32
#define RC_AEAD_XCHACHA20POLY1305_MACBYTES 16
#define RC_SECRETBOX_KEYBYTES 24
#define RC_SECRETBOX_NONCEBYTES 32
#define RC_SECRETBOX_MACBYTES 16

main.rs for the crate that does this (requires serde_json and rustdoc_json):

use serde_json::Value;
use std::fmt::Write;
use std::fs::File;
use std::{env, path::Path};

const HEADER_BASE: &str = "/*
* This file is automatically generated upon running
* `cargo +nightly build`. Do not modify by hand.
*/";

fn main() {
    let this_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let target_lib_dir = Path::new(&this_dir).parent().unwrap().join("rcrypto-lib");

    let json_path = rustdoc_json::Builder::default()
        .toolchain("nightly")
        .manifest_path(target_lib_dir.join("Cargo.toml"))
        .build()
        .unwrap();

    let reader = File::open(json_path).unwrap();
    let json: Value = serde_json::from_reader(reader).unwrap();

    let index = json.as_object().unwrap()["index"].as_object().unwrap();
    let consts = index
        .values()
        .filter(|v| v.get("visibility").map(|v| v.as_str().unwrap()) == Some("public"))
        .filter_map(|v| {
            // Messy, but we first check if `entry.inner.constant` exists (indicating a constant)
            // then pair that constant's value with its name
            v.get("inner")
                .and_then(|v| v.as_object().unwrap().get("constant"))
                .map(|c| {
                    (
                        v.get("name").unwrap().as_str().unwrap(),
                        c.get("value").unwrap().as_str().unwrap(),
                    )
                })
        });

    let mut header = HEADER_BASE.to_owned();
    header.push('\n');

    for (cname, cval) in consts {
        // We only focus on integers, so trim the suffix from e.g. `0usize`;
        let new_cval = cval.trim_end_matches(char::is_alphabetic);

        writeln!(header, "#define {cname} {new_cval}").unwrap();
    }

    cbindgen::Builder::new()
        .with_crate(target_lib_dir)
        .with_no_includes()
        .with_sys_include("stdint.h")
        .with_parse_expand(&["rcrypto-lib"])
        .with_language(cbindgen::Language::C)
        .with_cpp_compat(true)
        .with_header(header)
        .generate()
        .expect("failed to generate C bindings")
        .write_to_file("../rcrypto.h");
}

from cbindgen.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.