#编译时间 #构建 #常量 #const #宏推导 #构建时间

无 std const-gen

用于在 Rust 中生成(相对)复杂的编译时常量的 crate

39 个版本 (12 个稳定版)

1.6.4 2023年11月1日
1.5.1 2023年9月22日
1.4.1 2023年7月4日
1.3.0 2022年8月21日
0.3.0 2021年6月11日

#132 in Rust 模式

Download history 208/week @ 2024-04-21 341/week @ 2024-04-28 378/week @ 2024-05-05 391/week @ 2024-05-12 457/week @ 2024-05-19 317/week @ 2024-05-26 505/week @ 2024-06-02 392/week @ 2024-06-09 574/week @ 2024-06-16 596/week @ 2024-06-23 294/week @ 2024-06-30 353/week @ 2024-07-07 483/week @ 2024-07-14 343/week @ 2024-07-21 397/week @ 2024-07-28 474/week @ 2024-08-04

1,714 每月下载量
3 crate 中使用

MIT/Apache

38KB
693

const-gen

这是一个用于在您的 build.rs 文件中生成编译时常量的 crate。此 crate 支持将通常堆分配的类型转换为固定大小常量。它包括对基本类型、字符串、向量、映射、集合的支持,并附带一个 derive 宏,允许使用结构和枚举进行实现。

查看此示例

// build.rs

use const_gen::*;
use std::{env, fs, path::Path};

// First, let's dummy up some structs. Enabling the "derive" 
// feature allows us to do this simply, but implementing the
// CompileConst trait by hand is straightforward.

#[derive(CompileConst)]
#[inherit_doc]
/// Example inherited documentation
struct TestStruct
{
    test_u8: u8,
    /// Example uninherited field documentation
    test_vec: Vec<String>,
}

#[derive(CompileConst)]
#[inherit_docs]
/// Example inherited documentation
enum TestEnum
{
    Variant1,
    Variant2(u8),
    #[inherit_doc]
    /// Example inherited variant documentation
    Variant3 { named: u8 }
}

#[derive(CompileConst)]
struct TestTup(u8, u16);

fn main() 
{
    // Use the OUT_DIR environment variable to get an 
    // appropriate path.
    let out_dir = env::var_os("OUT_DIR").unwrap();
    let dest_path = Path::new(&out_dir).join("const_gen.rs");

    // Now let's dummy up some data to use in our const 
    // generation
    let test_vec: Vec<u8> = vec!(1,2,3,4,5,10,4);
    let test_struct = TestStruct
    { 
        test_u8: 12, 
        test_vec: vec!(String::from("Hello there.")) 
    };
    let test_tup_struct = TestTup(4, 55,);
    let test_enum = TestEnum::Variant1;
    let test_enum_tup = TestEnum::Variant2(23);
    let test_enum_structlike = TestEnum::Variant3{ named: 78 };

    // Now we'll generate the const declarations. We're also 
    // going to test with some primitive types. 
    let const_declarations = vec!
    {
        // Here are type definitions for our enums and structs 
        // above. Attributes from build.rs will not be preserved, 
        // so we need to pass any we want in.
        const_definition!(#[derive(Debug)] pub TestStruct),
        const_definition!(#[derive(Debug)] TestTup),
        const_definition!(#[derive(Debug)] TestEnum),

        // And here are constant definitions for particular 
        // values.
        const_declaration!(TEST_U8 = 27u8),
        const_declaration!(#[doc = "Example inherited documentation"] TEST_F32 = 33.5f32),
        const_declaration!(TEST_VEC = test_vec),
        const_declaration!(TEST_STRING = "I'm a string!"),
        const_declaration!(TEST_COW = 
            std::borrow::Cow::from("Cow!")),
        const_declaration!(pub TEST_STRUCT = test_struct),
        const_declaration!(TEST_TUP_STRUCT = test_tup_struct),
        const_declaration!(TEST_ENUM = test_enum),
        const_declaration!(TEST_ENUM_TUP = test_enum_tup),
        const_declaration!(TEST_ENUM_STRUCTLIKE = 
            test_enum_structlike),
       
       // or generate statics with the static_declaration macro
       static_declaration!(pub static TEST_U8_STATIC = 27u8),
    }.join("\n");

    // Note: The `const_definition!` and `const_declaration!` 
    // macros above are just simple wrappers for CompileConst 
    // trait methods of the same name. Using those methods
    // would entail the following sytax:
    // TestStruct::const_definition("#[derive(Debug)]")
    // test_struct.const_declaration("TEST_STRUCT")
    // These may be preferable in cases where const names
    // or type attributes have been procedurally generated
    // somehow and need to be treated as strings.

    // If the "phf" feature is enabled, this crate will also 
    // support converting HashMap and HashSet types into 
    // compile-time constant phf map and set types respectively.

    // Lastly, output to the destination file.
    fs::write(&dest_path, const_declarations).unwrap();
}

现在,在我们的 main.rs 文件中,我们可以这样做


// Include our constants
include!(concat!(env!("OUT_DIR"), "/const_gen.rs"));

// And that's it, we can access all of the const values below.
// It plays quite well with rust-analyzer, etc
fn main() 
{
    println!("{}", TEST_U8);
    println!("{}", TEST_F32);
    println!("{:?}", TEST_VEC);
    println!("{}", TEST_STRING);
    println!("{}", TEST_COW);
    println!("{:?}", TEST_STRUCT);
    println!("{:?}", TEST_TUP_STRUCT);
    println!("{:?}", TEST_ENUM);
    println!("{:?}", TEST_ENUM_TUP);
    println!("{:?}", TEST_ENUM_STRUCTLIKE);
}

实际的生成输出看起来像(此版本未格式化)这样

#[derive(Debug)]
struct TestStruct 
{
    test_u8: u8,
    test_vec: &'static [&'static str],
}
#[derive(Debug)]
struct TestTup(u8, u16);
#[derive(Debug)]
/// Example inherited documentation
enum TestEnum 
{
    Variant1,
    Variant2(u8),
    /// Example inherited variant documentation
    Variant3 { named: u8 },
}
const TEST_U8: u8 = 27u8;
/// Example inherited documentation
const TEST_F32: f32 = 33.5f32;
const TEST_VEC: &'static [u8] = 
    &[1u8, 2u8, 3u8, 4u8, 5u8, 10u8, 4u8];
const TEST_STRING: &'static str = "I'm a string!";
const TEST_COW: &'static str = "Cow!";
const TEST_STRUCT: TestStruct = TestStruct 
{
    test_u8: 12u8,
    test_vec: &["Hello there."],
};
const TEST_TUP_STRUCT: TestTup = TestTup(4u8, 55u16);
const TEST_ENUM: TestEnum = TestEnum::Variant1;
const TEST_ENUM_TUP: TestEnum = TestEnum::Variant2(23u8);
const TEST_ENUM_STRUCTLIKE: TestEnum = TestEnum::Variant3
{ 
    named: 78u8
};
static TEST_U8_STATIC: u8 = 27u8;

开箱即用的实现

下表显示了已经定义了 CompileConst 特征实现的类型

类型 常量表示
<所有数值基本类型> 无需转换
bool 无需转换
String, &str, str &'static str
Vec<T>, &[T] &'static [T]
[T; N where N is 0-256] [T's CompileConst representation; N]
Box<T>, Cow<T>, Rc<T>, Arc<T> T's CompileConst representation
Option<T> Option<T's CompileConst representation>
HashMap<K,V> phf::Map<K, V>, with K and V's CompileConst representation
HashSet<E> phf::Set<E>, with E's CompileConst representation
() 无需转换
<具有 2-16 个变体的元组> 包含每个变体的 CompileConst 表示的元组

还有一个 CompileConstArray 特征,它为以下内容生成固定大小的数组而不是静态切片

类型 常量数组表示
Vec<T>, &[T] [T; N]
String, &str, str [char; N]
Box<T>, Cow<T>, Rc<T>, Arc<T> T's CompileConstArray representation
() 无需转换
<具有 2-16 个变体的元组> 包含每个变体的 CompileConstArray 表示的元组。仅当每个变体实现 CompileConstArray 时才受支持。

属性

#[inherit_doc] 生成的定义将继承源项的文档。

#[inherit_docs] 生成的定义将继承源项的文档,以及内部项(字段和变体)的文档。

限制

这个包将使用宿主机的字节序、指针宽度等,而不是目标机的。例如,在整数上调用 to_ne_bytes 并将结果存储在常量中,可能会导致字节表示形式与目标机上相同的整数不等效。

特性

目前,所有特性都是默认的。

phf

phf 特性为 HashMap 和 HashSet 实现了 CompileConst 特性。它将为 HashMap 类型生成一个 phf::Map,为 HashSet 类型生成一个 phf::Set。请注意,phf 不需要包含在您的构建依赖项中,但为了使用常量,它应该包含在您的运行时依赖项中。

derive

derive 特性为结构和枚举添加了 #[derive(CompileConst)]。要求所有成员都实现 CompileConst。可以添加 #[inherit_docs] 属性,以便生成的定义继承 rustdocs。

std

可以禁用 std 默认特性,以使用 alloc 包代替 std 构造。

依赖项

~215KB