#[derive(Columns)]
{
    // Attributes available to this derive:
    #[column]
}
Expand description

Proc macro for deriving the Columns trait.

Custom column names

If the column name is different from the name of the field, you can use

#[column(name = "Type")]`
ty: i32,

to explicitly specify a name. The name must be a string literal.

Explicit indices

If you already know the index a field maps to, you can use

#[column(idx = 123)]`
ty: i32,

to specify it.

Implementation

The critical section in the expansion of

#[derive(Columns)]
struct Account {
    account_id: i32,
    account_name: String,
    account_role: i64,
}

is

for column in row.columns().iter() {
    let name = column.name();
    let idx = match name.len() {
        10 => match name {
            "account_id" => 0,
            _ => continue,
        },
        12 => {
            let b = name.as_bytes();
            let disc = b[8];
            match disc {
                110 => match name {
                    "account_name" => 1,
                    _ => continue,
                },
                114 => match name {
                    "account_role" => 2,
                    _ => continue,
                },
                _ => continue,
            }
        }
        _ => continue,
    };
    // ...
}

meaning that for each column the code

  1. uses a jump table indexed with the length of the column name,
  2. extracts an integer of size 1, 2, 4, or 8 from the column name,
  3. compares this integer to a number of candidates,
  4. compares the column name to the candidate.

This is very fast on current hardware. If the name of the candidate is no more than 16 bytes, then the final comparison will compile to a number of assembly instructions on x86_64. Otherwise it compiles to a call to bcmp. If you compile with -C target-cpu=native, then even these calls to bcmp will be inlined.

In practice, this means that the implementation of Columns is usually O(N) in the number of columns with a “small” constant. In some degenerate cases the construction above is not possible and the implementation will have to perform multiple string comparisons. Even this is still much faster than using the phf crate or similar.