summary refs log tree commit diff
path: root/enumn/Cargo.toml
diff options
context:
space:
mode:
authorDavid Tolnay <dtolnay@chromium.org>2018-12-06 01:58:21 -0800
committerchrome-bot <chrome-bot@chromium.org>2018-12-07 17:35:43 -0800
commitf97991985d6921375eb5a533c49fd7df5a75d2cd (patch)
tree52278731797f91cb0d42b5c81ba545acaaae9b53 /enumn/Cargo.toml
parent1d4d44a8e229d63aa16d05615ed33100f949863e (diff)
downloadcrosvm-f97991985d6921375eb5a533c49fd7df5a75d2cd.tar
crosvm-f97991985d6921375eb5a533c49fd7df5a75d2cd.tar.gz
crosvm-f97991985d6921375eb5a533c49fd7df5a75d2cd.tar.bz2
crosvm-f97991985d6921375eb5a533c49fd7df5a75d2cd.tar.lz
crosvm-f97991985d6921375eb5a533c49fd7df5a75d2cd.tar.xz
crosvm-f97991985d6921375eb5a533c49fd7df5a75d2cd.tar.zst
crosvm-f97991985d6921375eb5a533c49fd7df5a75d2cd.zip
macros: Derive macro to generate integer to enum conversion
This CL adds a procedural macro to generate functions for converting a
primitive integer into the corresponding variant of an enum.

Loosely based on https://docs.rs/enum-primitive-derive but implemented
against a newer version of Syn and without the dependency on num-traits.

The generated function is named `n` and has the following signature:

    impl YourEnum {
        pub fn n(value: Repr) -> Option<Self>;
    }

where `Repr` is an integer type of the right size as described in more
detail below.

EXAMPLE

    extern crate enumn;

    #[derive(PartialEq, Debug, enumn::N)]
    enum Status {
        LegendaryTriumph,
        QualifiedSuccess,
        FortuitousRevival,
        IndeterminateStalemate,
        RecoverableSetback,
        DireMisadventure,
        AbjectFailure,
    }

    fn main() {
        let s = Status::n(1);
        assert_eq!(s, Some(Status::QualifiedSuccess));

        let s = Status::n(9);
        assert_eq!(s, None);
    }

SIGNATURE

The generated signature depends on whether the enum has a `#[repr(..)]`
attribute. If a `repr` is specified, the input to `n` will be required
to be of that type.

    #[derive(enumn::N)]
    #[repr(u8)]
    enum E {
        /* ... */
    }

    // expands to:
    impl E {
        pub fn n(value: u8) -> Option<Self> {
            /* ... */
        }
    }

On the other hand if no `repr` is specified then we get a signature that
is generic over a variety of possible types.

    impl E {
        pub fn n<REPR: Into<i64>>(value: REPR) -> Option<Self> {
            /* ... */
        }
    }

DISCRIMINANTS

The conversion respects explictly specified enum discriminants. Consider
this enum:

    #[derive(enumn::N)]
    enum Letter {
        A = 65,
        B = 66,
    }

Here `Letter::n(65)` would return `Some(Letter::A)`.

TEST=`cargo test` against the new crate

Change-Id: I4286a816828c83507b35185fe497455ee30ae9e8
Reviewed-on: https://chromium-review.googlesource.com/1365114
Commit-Ready: David Tolnay <dtolnay@chromium.org>
Tested-by: David Tolnay <dtolnay@chromium.org>
Reviewed-by: Chirantan Ekbote <chirantan@chromium.org>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
Diffstat (limited to 'enumn/Cargo.toml')
-rw-r--r--enumn/Cargo.toml12
1 files changed, 12 insertions, 0 deletions
diff --git a/enumn/Cargo.toml b/enumn/Cargo.toml
new file mode 100644
index 0000000..84649ca
--- /dev/null
+++ b/enumn/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "enumn"
+version = "0.1.0"
+authors = ["The Chromium OS Authors"]
+
+[lib]
+proc-macro = true
+
+[dependencies]
+proc-macro2 = "0.4"
+quote = "0.6"
+syn = "0.15"