Macro exemplar::sql_enum

source ·
macro_rules! sql_enum {
    ($(#[$enum_doc:meta])* Name => $name:ident, $($(#[$variant_doc:meta])* $vname:ident),* $(,)?) => { ... };
}
Expand description

Generate an SQL-compatible field-less enum.

SQL compatible means:

(Additionally, the standard constellation of Debug/Clone/Copy/Eq/Hash are derived.)

An enum generated by this macro can be used in any Model implementor.

Usage

sql_enum! {
    Name => Color,
    Red,
    Green,
    Blue,
};

Notes

Explicit discriminants are not supported. Variants will always be implicitly numbered, in order of definition, from zero.

Concretely, this means that:

sql_enum! {
    Name => Color,
    Red = 1,
    Green = 2,
    Blue = 3
}

…will not compile.

This is because the TryFrom<i64> implementation generated by the macro looks something like this:

fn try_from(value: i64) -> Result<Self, Self::Error> {
    // This gets constant folded, even in debug.
    let len = [/* generated array of all possible variants */].len() as i64;
     
    if (0..len).contains(&value) {
        // SAFETY: the sql_enum macro does not support explicit discriminants,
        // so we know that the enum must be represented by the range 0..len
        //
        // https://doc.rust-lang.org/reference/items/enumerations.html#implicit-discriminants
        Ok(unsafe {
            std::mem::transmute(value) 
        })
    }
    else {
        // Throw error
    }
}

TL;DR - macro limitations.


Doc comments (and other attributes, like derives) are supported:

sql_enum! {
    /// An RGB color tag.
    Name => Color,
    /// Red
    Red,
    /// Green
    Green,
    /// Blue
    Blue,
}