#enums #traits #text #associated #generating #directory #num-traits

bin+lib rust-enum-derive

A simple library (and program) for generating rust enums and associated traits from text files

6 releases

Uses old Rust 2015

0.4.0 Feb 19, 2016
0.3.3 Feb 6, 2016
0.3.1 Jan 17, 2016
0.2.1 Nov 26, 2015

#1690 in Rust patterns


Used in nl-dump

Apache-2.0/BSD-3-Clause-Clear/MIT

43KB
616 lines

rust-enum-derive

rust-enum-derive is a simple program for generating rust enums and associated traits from text files. To simplify converting C code these text files are allowed to look like C enums or C #defines.

Usage

Usage: ./rust-enum-derive <options>
A simple program for generating rust enums and associated traits from text files.
Options:
    -i, --input NAME    input file name (stdin if not specified)
        --input_dir NAME
                        input directory to traverse
    -o, --output NAME   output directory to traverse
        --output_dir NAME
                        output file name (stdout if not specified)
        --name NAME     the enum name (Name if not specified)
        --derive DERIVE Which traits to derive. Ex: "Debug, PartialEq"

    -h, --help          print this help menu
        --define        parse C #define input instead of enum
    -a, --all           implement all of the traits (equivalent to --display
                        --fromprimative --fromstr)
        --default       implement the Default trait with the first value
        --display       implement the std::fmt::Display trait
        --fromprimative
                        implement the num::traits::FromPrimitive trait
        --fromstr       implement the std::str::FromStr trait
        --hex           hexadecimal output
        --pretty_fmt    implement pretty_fmt()

Simple examples

All of the following examples produce the same code:

ZERO = 0,
ONE = 1,
TWO = 2,
ZERO,
ONE,
TWO,
#define ZERO 0
#define ONE 1
#define TWO 2

This is the rust enum that will result:

pub enum Name {
    ZERO = 0,
    ONE = 1,
    TWO = 2,
}

rust-enum-derive can take input from standard in, a file, or a directory full of files (and associated TOML configuration). In turn this output can be directed to standard out, a file, or a directory full of files.

In the case of input from a directory structure it will look for TOML files (with filenames ending in ".toml" with the following structure:

[rust-enum-derive]
name = "Name"
derive = "Debug, PartialEq"
define = false
default = false
display = false
fromprimative = false
fromstr = false
pretty_fmt = false

The meaning of these fields matches their meaning on the command-line. You don't need to include any fields if you don't mean to change them from their default (false) value, however you do need to include a [rust-enum-derive] table. You will also need to include a file with the same name as your .toml file except ending in ".in". Your directory structure in your --input_dir will be replicated in your --output_dir. For example:

$ rust-enum-derive --input_dir ./input/ --output_dir /tmp/output--input_dir ./input/ --output_dir /tmp/output
$ tree input/
input/
├── one.in
├── one.toml
└── sub
    ├── two.in
    └── two.toml

1 directory, 4 files
$ tree input/
input/
├── one.in
├── one.toml
└── sub
    ├── two.in
    └── two.toml

1 directory, 4 files
$ tree /tmp/output/
/tmp/output/
├── one.rs
└── sub
    └── two.rs

1 directory, 2 files
$ tree /tmp/output/
/tmp/output/
├── one.rs
└── sub
    └── two.rs

1 directory, 2 files

Complex example

For example, rust-enum-derive can take the following text file (linux/if.h):

enum net_device_flags {
	IFF_UP				= 1<<0,  /* sysfs */
	IFF_BROADCAST			= 1<<1,  /* __volatile__ */
	IFF_DEBUG			= 1<<2,  /* sysfs */
	IFF_LOOPBACK			= 1<<3,  /* __volatile__ */
	IFF_POINTOPOINT			= 1<<4,  /* __volatile__ */
	IFF_NOTRAILERS			= 1<<5,  /* sysfs */
	IFF_RUNNING			= 1<<6,  /* __volatile__ */
	IFF_NOARP			= 1<<7,  /* sysfs */
	IFF_PROMISC			= 1<<8,  /* sysfs */
	IFF_ALLMULTI			= 1<<9,  /* sysfs */
	IFF_MASTER			= 1<<10, /* __volatile__ */
	IFF_SLAVE			= 1<<11, /* __volatile__ */
	IFF_MULTICAST			= 1<<12, /* sysfs */
	IFF_PORTSEL			= 1<<13, /* sysfs */
	IFF_AUTOMEDIA			= 1<<14, /* sysfs */
	IFF_DYNAMIC			= 1<<15, /* sysfs */
	IFF_LOWER_UP			= 1<<16, /* __volatile__ */
	IFF_DORMANT			= 1<<17, /* __volatile__ */
	IFF_ECHO			= 1<<18, /* __volatile__ */
};

and generate the following code:

pub enum Name {
    IFF_UP = 0x1,
    IFF_BROADCAST = 0x2,
    IFF_DEBUG = 0x4,
    IFF_LOOPBACK = 0x8,
    IFF_POINTOPOINT = 0x10,
    IFF_NOTRAILERS = 0x20,
    IFF_RUNNING = 0x40,
    IFF_NOARP = 0x80,
    IFF_PROMISC = 0x100,
    IFF_ALLMULTI = 0x200,
    IFF_MASTER = 0x400,
    IFF_SLAVE = 0x800,
    IFF_MULTICAST = 0x1000,
    IFF_PORTSEL = 0x2000,
    IFF_AUTOMEDIA = 0x4000,
    IFF_DYNAMIC = 0x8000,
    IFF_LOWER_UP = 0x10000,
    IFF_DORMANT = 0x20000,
    IFF_ECHO = 0x40000,
}
impl ::std::str::FromStr for Name {
    type Err = ();
    #[allow(dead_code)]
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "IFF_UP" => Ok(Name::IFF_UP),
            "IFF_BROADCAST" => Ok(Name::IFF_BROADCAST),
            "IFF_DEBUG" => Ok(Name::IFF_DEBUG),
            "IFF_LOOPBACK" => Ok(Name::IFF_LOOPBACK),
            "IFF_POINTOPOINT" => Ok(Name::IFF_POINTOPOINT),
            "IFF_NOTRAILERS" => Ok(Name::IFF_NOTRAILERS),
            "IFF_RUNNING" => Ok(Name::IFF_RUNNING),
            "IFF_NOARP" => Ok(Name::IFF_NOARP),
            "IFF_PROMISC" => Ok(Name::IFF_PROMISC),
            "IFF_ALLMULTI" => Ok(Name::IFF_ALLMULTI),
            "IFF_MASTER" => Ok(Name::IFF_MASTER),
            "IFF_SLAVE" => Ok(Name::IFF_SLAVE),
            "IFF_MULTICAST" => Ok(Name::IFF_MULTICAST),
            "IFF_PORTSEL" => Ok(Name::IFF_PORTSEL),
            "IFF_AUTOMEDIA" => Ok(Name::IFF_AUTOMEDIA),
            "IFF_DYNAMIC" => Ok(Name::IFF_DYNAMIC),
            "IFF_LOWER_UP" => Ok(Name::IFF_LOWER_UP),
            "IFF_DORMANT" => Ok(Name::IFF_DORMANT),
            "IFF_ECHO" => Ok(Name::IFF_ECHO),
            _ => Err( () )
        }
    }
}
impl Default for Name {
    fn default() -> Name {
        Name::IFF_UP
    }
}
impl ::std::fmt::Display for Name {
    #[allow(dead_code)]
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match *self {
            Name::IFF_UP => write!(f, "IFF_UP"),
            Name::IFF_BROADCAST => write!(f, "IFF_BROADCAST"),
            Name::IFF_DEBUG => write!(f, "IFF_DEBUG"),
            Name::IFF_LOOPBACK => write!(f, "IFF_LOOPBACK"),
            Name::IFF_POINTOPOINT => write!(f, "IFF_POINTOPOINT"),
            Name::IFF_NOTRAILERS => write!(f, "IFF_NOTRAILERS"),
            Name::IFF_RUNNING => write!(f, "IFF_RUNNING"),
            Name::IFF_NOARP => write!(f, "IFF_NOARP"),
            Name::IFF_PROMISC => write!(f, "IFF_PROMISC"),
            Name::IFF_ALLMULTI => write!(f, "IFF_ALLMULTI"),
            Name::IFF_MASTER => write!(f, "IFF_MASTER"),
            Name::IFF_SLAVE => write!(f, "IFF_SLAVE"),
            Name::IFF_MULTICAST => write!(f, "IFF_MULTICAST"),
            Name::IFF_PORTSEL => write!(f, "IFF_PORTSEL"),
            Name::IFF_AUTOMEDIA => write!(f, "IFF_AUTOMEDIA"),
            Name::IFF_DYNAMIC => write!(f, "IFF_DYNAMIC"),
            Name::IFF_LOWER_UP => write!(f, "IFF_LOWER_UP"),
            Name::IFF_DORMANT => write!(f, "IFF_DORMANT"),
            Name::IFF_ECHO => write!(f, "IFF_ECHO"),
        }
    }
}
impl ::num::traits::FromPrimitive for Name {
    #[allow(dead_code)]
    fn from_i64(n: i64) -> Option<Self> {
        match n {
            0x1 => Some(Name::IFF_UP),
            0x2 => Some(Name::IFF_BROADCAST),
            0x4 => Some(Name::IFF_DEBUG),
            0x8 => Some(Name::IFF_LOOPBACK),
            0x10 => Some(Name::IFF_POINTOPOINT),
            0x20 => Some(Name::IFF_NOTRAILERS),
            0x40 => Some(Name::IFF_RUNNING),
            0x80 => Some(Name::IFF_NOARP),
            0x100 => Some(Name::IFF_PROMISC),
            0x200 => Some(Name::IFF_ALLMULTI),
            0x400 => Some(Name::IFF_MASTER),
            0x800 => Some(Name::IFF_SLAVE),
            0x1000 => Some(Name::IFF_MULTICAST),
            0x2000 => Some(Name::IFF_PORTSEL),
            0x4000 => Some(Name::IFF_AUTOMEDIA),
            0x8000 => Some(Name::IFF_DYNAMIC),
            0x10000 => Some(Name::IFF_LOWER_UP),
            0x20000 => Some(Name::IFF_DORMANT),
            0x40000 => Some(Name::IFF_ECHO),
            _ => None
        }
    }
    #[allow(dead_code)]
    fn from_u64(n: u64) -> Option<Self> {
        match n {
            0x1 => Some(Name::IFF_UP),
            0x2 => Some(Name::IFF_BROADCAST),
            0x4 => Some(Name::IFF_DEBUG),
            0x8 => Some(Name::IFF_LOOPBACK),
            0x10 => Some(Name::IFF_POINTOPOINT),
            0x20 => Some(Name::IFF_NOTRAILERS),
            0x40 => Some(Name::IFF_RUNNING),
            0x80 => Some(Name::IFF_NOARP),
            0x100 => Some(Name::IFF_PROMISC),
            0x200 => Some(Name::IFF_ALLMULTI),
            0x400 => Some(Name::IFF_MASTER),
            0x800 => Some(Name::IFF_SLAVE),
            0x1000 => Some(Name::IFF_MULTICAST),
            0x2000 => Some(Name::IFF_PORTSEL),
            0x4000 => Some(Name::IFF_AUTOMEDIA),
            0x8000 => Some(Name::IFF_DYNAMIC),
            0x10000 => Some(Name::IFF_LOWER_UP),
            0x20000 => Some(Name::IFF_DORMANT),
            0x40000 => Some(Name::IFF_ECHO),
            _ => None
        }
    }
}
impl Name {
    fn pretty_fmt(f: &mut ::std::fmt::Formatter, flags: u32) -> ::std::fmt::Result {
        let mut shift: u32 = 0;
        let mut result: u32 = 1<<shift;
        let mut found = false;
        while result <= Name::IFF_ECHO as u32 {
            let tmp = result & flags;
            if tmp > 0 {
                if found {
                    try!(write!(f, "|"));
                }
                let flag = Name::from_u32(tmp).unwrap();
                try!(write!(f, "{}", flag));
                found = true;
            }
            shift += 1;
            result = 1<<shift;
        }
        write!(f, "")
    }
}pub enum Name {
    IFF_UP = 0x1,
    IFF_BROADCAST = 0x2,
    IFF_DEBUG = 0x4,
    IFF_LOOPBACK = 0x8,
    IFF_POINTOPOINT = 0x10,
    IFF_NOTRAILERS = 0x20,
    IFF_RUNNING = 0x40,
    IFF_NOARP = 0x80,
    IFF_PROMISC = 0x100,
    IFF_ALLMULTI = 0x200,
    IFF_MASTER = 0x400,
    IFF_SLAVE = 0x800,
    IFF_MULTICAST = 0x1000,
    IFF_PORTSEL = 0x2000,
    IFF_AUTOMEDIA = 0x4000,
    IFF_DYNAMIC = 0x8000,
    IFF_LOWER_UP = 0x10000,
    IFF_DORMANT = 0x20000,
    IFF_ECHO = 0x40000,
}
impl ::std::str::FromStr for Name {
    type Err = ();
    #[allow(dead_code)]
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "IFF_UP" => Ok(Name::IFF_UP),
            "IFF_BROADCAST" => Ok(Name::IFF_BROADCAST),
            "IFF_DEBUG" => Ok(Name::IFF_DEBUG),
            "IFF_LOOPBACK" => Ok(Name::IFF_LOOPBACK),
            "IFF_POINTOPOINT" => Ok(Name::IFF_POINTOPOINT),
            "IFF_NOTRAILERS" => Ok(Name::IFF_NOTRAILERS),
            "IFF_RUNNING" => Ok(Name::IFF_RUNNING),
            "IFF_NOARP" => Ok(Name::IFF_NOARP),
            "IFF_PROMISC" => Ok(Name::IFF_PROMISC),
            "IFF_ALLMULTI" => Ok(Name::IFF_ALLMULTI),
            "IFF_MASTER" => Ok(Name::IFF_MASTER),
            "IFF_SLAVE" => Ok(Name::IFF_SLAVE),
            "IFF_MULTICAST" => Ok(Name::IFF_MULTICAST),
            "IFF_PORTSEL" => Ok(Name::IFF_PORTSEL),
            "IFF_AUTOMEDIA" => Ok(Name::IFF_AUTOMEDIA),
            "IFF_DYNAMIC" => Ok(Name::IFF_DYNAMIC),
            "IFF_LOWER_UP" => Ok(Name::IFF_LOWER_UP),
            "IFF_DORMANT" => Ok(Name::IFF_DORMANT),
            "IFF_ECHO" => Ok(Name::IFF_ECHO),
            _ => Err( () )
        }
    }
}
impl Default for Name {
    fn default() -> Name {
        Name::IFF_UP
    }
}
impl ::std::fmt::Display for Name {
    #[allow(dead_code)]
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match *self {
            Name::IFF_UP => write!(f, "IFF_UP"),
            Name::IFF_BROADCAST => write!(f, "IFF_BROADCAST"),
            Name::IFF_DEBUG => write!(f, "IFF_DEBUG"),
            Name::IFF_LOOPBACK => write!(f, "IFF_LOOPBACK"),
            Name::IFF_POINTOPOINT => write!(f, "IFF_POINTOPOINT"),
            Name::IFF_NOTRAILERS => write!(f, "IFF_NOTRAILERS"),
            Name::IFF_RUNNING => write!(f, "IFF_RUNNING"),
            Name::IFF_NOARP => write!(f, "IFF_NOARP"),
            Name::IFF_PROMISC => write!(f, "IFF_PROMISC"),
            Name::IFF_ALLMULTI => write!(f, "IFF_ALLMULTI"),
            Name::IFF_MASTER => write!(f, "IFF_MASTER"),
            Name::IFF_SLAVE => write!(f, "IFF_SLAVE"),
            Name::IFF_MULTICAST => write!(f, "IFF_MULTICAST"),
            Name::IFF_PORTSEL => write!(f, "IFF_PORTSEL"),
            Name::IFF_AUTOMEDIA => write!(f, "IFF_AUTOMEDIA"),
            Name::IFF_DYNAMIC => write!(f, "IFF_DYNAMIC"),
            Name::IFF_LOWER_UP => write!(f, "IFF_LOWER_UP"),
            Name::IFF_DORMANT => write!(f, "IFF_DORMANT"),
            Name::IFF_ECHO => write!(f, "IFF_ECHO"),
        }
    }
}
impl ::num::traits::FromPrimitive for Name {
    #[allow(dead_code)]
    fn from_i64(n: i64) -> Option<Self> {
        match n {
            0x1 => Some(Name::IFF_UP),
            0x2 => Some(Name::IFF_BROADCAST),
            0x4 => Some(Name::IFF_DEBUG),
            0x8 => Some(Name::IFF_LOOPBACK),
            0x10 => Some(Name::IFF_POINTOPOINT),
            0x20 => Some(Name::IFF_NOTRAILERS),
            0x40 => Some(Name::IFF_RUNNING),
            0x80 => Some(Name::IFF_NOARP),
            0x100 => Some(Name::IFF_PROMISC),
            0x200 => Some(Name::IFF_ALLMULTI),
            0x400 => Some(Name::IFF_MASTER),
            0x800 => Some(Name::IFF_SLAVE),
            0x1000 => Some(Name::IFF_MULTICAST),
            0x2000 => Some(Name::IFF_PORTSEL),
            0x4000 => Some(Name::IFF_AUTOMEDIA),
            0x8000 => Some(Name::IFF_DYNAMIC),
            0x10000 => Some(Name::IFF_LOWER_UP),
            0x20000 => Some(Name::IFF_DORMANT),
            0x40000 => Some(Name::IFF_ECHO),
            _ => None
        }
    }
    #[allow(dead_code)]
    fn from_u64(n: u64) -> Option<Self> {
        match n {
            0x1 => Some(Name::IFF_UP),
            0x2 => Some(Name::IFF_BROADCAST),
            0x4 => Some(Name::IFF_DEBUG),
            0x8 => Some(Name::IFF_LOOPBACK),
            0x10 => Some(Name::IFF_POINTOPOINT),
            0x20 => Some(Name::IFF_NOTRAILERS),
            0x40 => Some(Name::IFF_RUNNING),
            0x80 => Some(Name::IFF_NOARP),
            0x100 => Some(Name::IFF_PROMISC),
            0x200 => Some(Name::IFF_ALLMULTI),
            0x400 => Some(Name::IFF_MASTER),
            0x800 => Some(Name::IFF_SLAVE),
            0x1000 => Some(Name::IFF_MULTICAST),
            0x2000 => Some(Name::IFF_PORTSEL),
            0x4000 => Some(Name::IFF_AUTOMEDIA),
            0x8000 => Some(Name::IFF_DYNAMIC),
            0x10000 => Some(Name::IFF_LOWER_UP),
            0x20000 => Some(Name::IFF_DORMANT),
            0x40000 => Some(Name::IFF_ECHO),
            _ => None
        }
    }
}
impl Name {
    fn pretty_fmt(f: &mut ::std::fmt::Formatter, flags: u32) -> ::std::fmt::Result {
        let mut shift: u32 = 0;
        let mut result: u32 = 1<<shift;
        let mut found = false;
        while result <= Name::IFF_ECHO as u32 {
            let tmp = result & flags;
            if tmp > 0 {
                if found {
                    try!(write!(f, "|"));
                }
                let flag = Name::from_u32(tmp).unwrap();
                try!(write!(f, "{}", flag));
                found = true;
            }
            shift += 1;
            result = 1<<shift;
        }
        write!(f, "")
    }
}

You can choose to have rust-enum-derive implement all, some, or none of the methods/traits.

Dependencies

~4.5MB
~90K SLoC