#枚举 #特质 #文本 #关联 #生成 #目录 #数字特质

程序+库 rust-enum-derive

一个简单的库(和程序),用于从文本文件生成 Rust 枚举和相关特质

6 个版本

使用旧版 Rust 2015

0.4.0 2016 年 2 月 19 日
0.3.3 2016 年 2 月 6 日
0.3.1 2016 年 1 月 17 日
0.2.1 2015 年 11 月 26 日

#1690 in Rust 模式


用于 nl-dump

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

43KB
616

rust-enum-derive

rust-enum-derive 是一个简单的程序,可以从文本文件生成 Rust 枚举和相关特质。为了简化将 C 代码转换为 C 枚举或 C #define,允许这些文本文件看起来像 C 枚举或 C #define。

使用方法

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()

简单示例

以下所有示例都会生成相同的代码

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

这是生成的 Rust 枚举

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

rust-enum-derive 可以从标准输入、文件或包含文件的目录(和相关 TOML 配置)获取输入。然后可以将输出重定向到标准输出、文件或包含文件的目录。

在从目录结构获取输入的情况下,它将寻找以 ".toml" 结尾的 TOML 文件(具有以下结构

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

这些字段的含义与命令行上的含义匹配。如果您不打算更改默认(false)值,则不需要包含任何字段,但是您需要包含一个 [rust-enum-derive] 表。您还需要包含一个与您的 .toml 文件同名但以 ".in" 结尾的文件。您的 --input_dir 中的目录结构将在 --output_dir 中复制。例如

$ 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

复杂示例

例如,rust-enum-derive 可以从以下文本文件(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__ */
};

并生成以下代码

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, "")
    }
}

您可以选择让 rust-enum-derive 实现全部、部分或没有任何方法/特质。

依赖项

~4.5MB
~90K SLoC