The Principal Dev – Masterclass for Tech Leads

The Principal Dev – Masterclass for Tech Leads28-29 May

Join

Rust-PHF

CI Latest Version

Documentation

Rust-PHF is a library to generate efficient lookup tables at compile time using perfect hash functions.

It currently uses the CHD algorithm by default and also ships an experimental ptrhash feature for an alternative MPHF layout.

MSRV (minimum supported rust version) is Rust 1.71.

Usage

PHF data structures can be constructed via either the procedural macros in the phf_macros crate or code generation supported by the phf_codegen crate.

To compile the phf crate with a dependency on libcore instead of libstd, enabling use in environments where libstd will not work, set default-features = false for the dependency:

[dependencies]
# to use `phf` in `no_std` environments
phf = { version = "0.13.1", default-features = false }

phf_macros

use phf::phf_map;

#[derive(Clone)]
pub enum Keyword {
    Loop,
    Continue,
    Break,
    Fn,
    Extern,
}

static KEYWORDS: phf::Map<&'static str, Keyword> = phf_map! {
    "loop" => Keyword::Loop,
    "continue" => Keyword::Continue,
    "break" => Keyword::Break,
    "fn" => Keyword::Fn,
    "extern" => Keyword::Extern,
};

// You can also use OR (`|`) patterns to map multiple keys to the same value:
static OPERATORS: phf::Map<&'static str, &'static str> = phf_map! {
    "+" | "add" | "plus" => "addition",
    "-" | "sub" | "minus" => "subtraction",
    "*" | "mul" | "times" => "multiplication",
};

pub fn parse_keyword(keyword: &str) -> Option<Keyword> {
    KEYWORDS.get(keyword).cloned()
}

pub fn parse_operator(operator: &str) -> Option<&'static str> {
    OPERATORS.get(operator).copied()
}
[dependencies]
phf = { version = "0.13.1", features = ["macros"] }

To try the experimental alternative, enable ptrhash on both the generator and runtime crates you use:

[dependencies]
phf = { version = "0.13.1", features = ["macros", "ptrhash"] }

Note

Currently, the macro syntax has some limitations and may not work as you want. See #196 for example.

phf_codegen

To use phf_codegen on build.rs, you have to add dependencies under [build-dependencies]:

[build-dependencies]
phf = { version = "0.13.1", default-features = false }
phf_codegen = "0.13.1"

When using the experimental ptrhash layout, enable the ptrhash feature on both phf_codegen and the runtime phf dependency so the generated constants match the runtime struct layout.

Then put code on build.rs:

use std::env;
use std::fs::File;
use std::io::{BufWriter, Write};
use std::path::Path;

fn main() {
    let path = Path::new(&env::var("OUT_DIR").unwrap()).join("codegen.rs");
    let mut file = BufWriter::new(File::create(&path).unwrap());

    write!(
        &mut file,
        "static KEYWORDS: phf::Map<&'static str, Keyword> = {}",
        phf_codegen::Map::new()
            .entry("loop", "Keyword::Loop")
            .entry("continue", "Keyword::Continue")
            .entry("break", "Keyword::Break")
            .entry("fn", "Keyword::Fn")
            .entry("extern", "Keyword::Extern")
            .build()
    )
    .unwrap();
    write!(&mut file, ";\n").unwrap();

    // Example with OR patterns (note: phf_codegen doesn't support OR patterns directly)
    write!(
        &mut file,
        "static OPERATORS: phf::Map<&'static str, &'static str> = {}",
        phf_codegen::Map::new()
            .entry("+", "\"addition\"")
            .entry("add", "\"addition\"")
            .entry("plus", "\"addition\"")
            .entry("-", "\"subtraction\"")
            .entry("sub", "\"subtraction\"")
            .entry("minus", "\"subtraction\"")
            .build()
    )
    .unwrap();
    write!(&mut file, ";\n").unwrap();
}

and lib.rs:

#[derive(Clone)]
enum Keyword {
    Loop,
    Continue,
    Break,
    Fn,
    Extern,
}

include!(concat!(env!("OUT_DIR"), "/codegen.rs"));

pub fn parse_keyword(keyword: &str) -> Option<Keyword> {
    KEYWORDS.get(keyword).cloned()
}

pub fn parse_operator(operator: &str) -> Option<&'static str> {
    OPERATORS.get(operator).copied()
}

Join libs.tech

...and unlock some superpowers

GitHub

We won't share your data with anyone else.