Skip to content

Instantly share code, notes, and snippets.

@sheb-gregor
Last active June 17, 2019 23:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sheb-gregor/c853e5f2436796e6ac05a6e4576b529b to your computer and use it in GitHub Desktop.
Save sheb-gregor/c853e5f2436796e6ac05a6e4576b529b to your computer and use it in GitHub Desktop.
Macro for protobuf enums for Exonum

Protobuf enums for Exonum

proto_enum macro:

  • First arg — name of the protobuf file with enum;

  • Second arg — enum defenition


Protobuf enum defenition:

//types.proto

enum AccountType {
    AccountTypeNull = 0;
    SYSTEM = 1;
    GENERAL = 2;
    MERCHANT = 3;
}

Rust representation of enum:

proto_enum! {
    types;
    enum AccountType {
        AccountTypeNull = 0,
        SYSTEM = 1,
        GENERAL = 2,
        MERCHANT = 3,
    }
}
#[macro_export]
macro_rules! proto_enum {
(
$proto_mod:tt;
enum $name:ident {
$($variant:ident = $val:expr),*,
}) => {
#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Debug, Hash)]
pub enum $name {
$($variant = $val),+
}
impl protobuf::ProtobufEnum for $name {
fn value(&self) -> i32 {
*self as i32
}
fn from_i32(value: i32) -> Option<$name> {
match value {
$($val => Some($name::$variant)),+,
_ => None
}
}
fn values() -> &'static [Self] {
static VALUES: &'static [$name] = &[
$($name::$variant),*
];
VALUES
}
}
impl $name {
pub fn as_str(&self) -> &str {
match *self {
$($name::$variant => stringify!($variant)),+,
}
}
/// }
// impl std::str::FromStr for $name {
pub fn set_from_str(val: &str) -> Option<$name> {
match val {
$( stringify!($variant) => Some($name::$variant)),+,
_ => None
}
}
}
impl ::std::default::Default for $name {
fn default() -> Self {
use protobuf::ProtobufEnum;
$name::values()[0].clone()
}
}
impl ::std::fmt::Display for $name {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
$($name::$variant => f.write_str(stringify!($variant)) ),+,
}
}
}
impl From<proto::$proto_mod::$name> for i32 {
fn from(v: proto::$proto_mod::$name) -> Self {
use protobuf::ProtobufEnum;
v.value()
}
}
impl exonum::proto::ProtobufConvert for $name {
/// Type of the protobuf clone of Self
type ProtoStruct = proto::$proto_mod::$name;
/// Struct -> ProtoStruct
fn to_pb(&self) -> Self::ProtoStruct {
use protobuf::ProtobufEnum;
let x = self.clone();
match proto::$proto_mod::$name::from_i32(x.value()){
Some(v) => v,
None => proto::$proto_mod::$name::default()
}
}
/// ProtoStruct -> Struct
fn from_pb(pb: Self::ProtoStruct) -> Result<Self, failure::Error> {
use protobuf::ProtobufEnum;
match $name::from_i32(pb.value()) {
Some(v) => Ok(v),
None => Ok($name::default())
}
}
}
};
}
@orthecreedence
Copy link

Thanks for posting this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment