From acb67e3d7fef9e83e0be3150d42af3dd02e33fa6 Mon Sep 17 00:00:00 2001 From: "C. Morgan Hamill" Date: Thu, 19 Mar 2015 11:43:51 -0400 Subject: Add `NotmuchEnum` trait and `notmuch_enum!` macro. Implements enum types in pairs, specifying the type and variant names of each, like so: notmuch_enum! { pub enum enum_name => EnumName { variant_one => VariantOne, variant_two => VariantTwo } } Which expands to: pub enum enum_name { variant_one, variant_two } pub enum EnumName { VariantOne, VariantTwo } The `NotmuchEnum` trait also entails two functions to convert between the defined pairs, `from_notmuch_t()` and `to_notmuch_t()`. The macro takes care of their implementation, also. Yes, this is purely aesthetic whimsy: I wanted the types in the `ffi` module to match the types from the `notmuch.h` file, and I wanted the types I used within (and exported by) this crate to match the expected Rust convention. --- src/ffi.rs | 101 +++++++++++++++++++++++++++++++++------------------------- src/lib.rs | 4 +++ src/macros.rs | 35 ++++++++++++++++++++ src/utils.rs | 6 ++++ 4 files changed, 102 insertions(+), 44 deletions(-) create mode 100644 src/macros.rs create mode 100644 src/utils.rs diff --git a/src/ffi.rs b/src/ffi.rs index dba98b5..9cc6f47 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -11,62 +11,75 @@ use libc::{ time_t, }; +use utils::NotmuchEnum; + pub type notmuch_bool_t = c_int; pub type notmuch_compact_status_cb_t = extern fn(*const c_char, *mut c_void); -#[repr(C)] -#[derive(Copy, Debug)] -pub enum notmuch_status_t { - NOTMUCH_STATUS_SUCCESS = 0, - NOTMUCH_STATUS_OUT_OF_MEMORY, - NOTMUCH_STATUS_READ_ONLY_DATABASE, - NOTMUCH_STATUS_XAPIAN_EXCEPTION, - NOTMUCH_STATUS_FILE_ERROR, - NOTMUCH_STATUS_FILE_NOT_EMAIL, - NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID, - NOTMUCH_STATUS_NULL_POINTER, - NOTMUCH_STATUS_TAG_TOO_LONG, - NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW, - NOTMUCH_STATUS_UNBALANCED_ATOMIC, - NOTMUCH_STATUS_UNSUPPORTED_OPERATION, - NOTMUCH_STATUS_UPGRADE_REQUIRED, - // Not an actual status value. Just a way to find out how many - // valid status values there are. - NOTMUCH_STATUS_LAST_STATUS, +notmuch_enum! { + #[repr(C)] + #[derive(Copy, Debug)] + pub enum notmuch_status_t => NotmuchStatus { + NOTMUCH_STATUS_SUCCESS => Success, + NOTMUCH_STATUS_OUT_OF_MEMORY => OutOfMemory, + NOTMUCH_STATUS_READ_ONLY_DATABASE => ReadOnlyDatabase, + NOTMUCH_STATUS_XAPIAN_EXCEPTION => XapianException, + NOTMUCH_STATUS_FILE_ERROR => FileError, + NOTMUCH_STATUS_FILE_NOT_EMAIL => FileNotEmail, + NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID => DuplicateMessageID, + NOTMUCH_STATUS_NULL_POINTER => NullPointer, + NOTMUCH_STATUS_TAG_TOO_LONG => TagTooLong, + NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW => UnbalancedFreezeThaw, + NOTMUCH_STATUS_UNBALANCED_ATOMIC => UnbalancedAtomic, + NOTMUCH_STATUS_UNSUPPORTED_OPERATION => UnsupportedOperation, + NOTMUCH_STATUS_UPGRADE_REQUIRED => UpgradeRequired, + // Not an actual status value. Just a way to find out how many + // valid status values there are. + NOTMUCH_STATUS_LAST_STATUS => LastStatus + } +} } -#[repr(C)] -#[derive(Copy, Debug)] -pub enum notmuch_database_mode_t { - NOTMUCH_DATABASE_MODE_READ_ONLY = 0, - NOTMUCH_DATABASE_MODE_READ_WRITE, +notmuch_enum! { + #[repr(C)] + #[derive(Copy, Debug)] + pub enum notmuch_database_mode_t => NotmuchDatabaseMode { + NOTMUCH_DATABASE_MODE_READ_ONLY => ReadOnly, + NOTMUCH_DATABASE_MODE_READ_WRITE => ReadWrite + } } -#[repr(C)] -#[derive(Copy, Debug)] -pub enum notmuch_sort_t { - NOTMUCH_SORT_OLDEST_FIRST = 0, - NOTMUCH_SORT_NEWEST_FIRST, - NOTMUCH_SORT_MESSAGE_ID, - NOTMUCH_SORT_UNSORTED, +notmuch_enum! { + #[repr(C)] + #[derive(Copy, Debug)] + pub enum notmuch_sort_t => NotmuchSort { + NOTMUCH_SORT_OLDEST_FIRST => OldestFirst, + NOTMUCH_SORT_NEWEST_FIRST => NewestFirst, + NOTMUCH_SORT_MESSAGE_ID => MessageID, + NOTMUCH_SORT_UNSORTED => ReadWrite + } } -#[repr(C)] -#[derive(Copy, Debug)] -pub enum notmuch_exclude_t { - NOTMUCH_EXCLUDE_FLAG = 0, - NOTMUCH_EXCLUDE_TRUE, - NOTMUCH_EXCLUDE_FALSE, - NOTMUCH_EXCLUDE_ALL, +notmuch_enum! { + #[repr(C)] + #[derive(Copy, Debug)] + pub enum notmuch_exclude_t => NotmuchExclude { + NOTMUCH_EXCLUDE_FLAG => Flag, + NOTMUCH_EXCLUDE_TRUE => True, + NOTMUCH_EXCLUDE_FALSE => False, + NOTMUCH_EXCLUDE_ALL => All + } } -#[repr(C)] -#[derive(Copy, Debug)] -pub enum notmuch_message_flag_t { - NOTMUCH_MESSAGE_FLAG_MATCH = 0, - NOTMUCH_MESSAGE_FLAG_EXCLUDED, - NOTMUCH_MESSAGE_FLAG_GHOST, +notmuch_enum! { + #[repr(C)] + #[derive(Copy, Debug)] + pub enum notmuch_message_flag_t => NotmuchMessageFlag { + NOTMUCH_MESSAGE_FLAG_MATCH => Match, + NOTMUCH_MESSAGE_FLAG_EXCLUDED => Excluded, + NOTMUCH_MESSAGE_FLAG_GHOST => Ghost + } } #[repr(C)] pub struct notmuch_database_t; diff --git a/src/lib.rs b/src/lib.rs index 5c2fbd6..0f88f60 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,8 @@ #![feature(libc)] extern crate libc; +#[macro_use] +mod macros; + mod ffi; +mod utils; diff --git a/src/macros.rs b/src/macros.rs new file mode 100644 index 0000000..836be63 --- /dev/null +++ b/src/macros.rs @@ -0,0 +1,35 @@ +#[macro_escape] +macro_rules! notmuch_enum { + ( + $(#[$enum_attr:meta])* + pub enum $name:ident => $name_alias:ident { + $($variant:ident => $variant_alias:ident),* + } + ) => { + $(#[$enum_attr])* + pub enum $name { + $($variant),* + } + + $(#[$enum_attr])* + pub enum $name_alias { + $($variant_alias),* + } + + impl NotmuchEnum for $name_alias { + type NotmuchT = $name; + + fn from_notmuch_t(notmuch_t: $name) -> Self { + match notmuch_t { + $($name::$variant => $name_alias::$variant_alias),* + } + } + + fn to_notmuch_t(self) -> $name { + match self { + $($name_alias::$variant_alias => $name::$variant),* + } + } + } + } +} diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..77e6e5e --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,6 @@ +pub trait NotmuchEnum { + type NotmuchT; + + fn from_notmuch_t(notmuch_t: Self::NotmuchT) -> Self; + fn to_notmuch_t(self) -> Self::NotmuchT; +} -- cgit v1.2.1