Skip to content

Commit

Permalink
Merge pull request #5 from kmcallister/h5e-macros
Browse files Browse the repository at this point in the history
Add some macros from html5ever
  • Loading branch information
reem committed Feb 27, 2015
2 parents 6b35d27 + 749b7d9 commit 63084a5
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 0 deletions.
45 changes: 45 additions & 0 deletions src/format.rs
@@ -0,0 +1,45 @@
//! Macros for string formatting.

/// Conditionally perform string formatting.
///
/// If `$enabled` is true, then do the formatting and return a `Cow::Owned`.
///
/// Otherwise, just return the borrowed (often `'static`) string
/// `$borrowed`.
///
/// When `$enabled` is false, this avoids the overhead of allocating
/// and writing to a buffer, as well as any overhead or side effects
/// of the format arguments.
///
/// # Example
///
/// You can use `format_if` to implement a detailed error logging facility
/// that can be enabled at runtime.
///
/// ```
/// # #[macro_use] extern crate mac;
/// # fn main() {
/// let formatted = format_if!(true, "Vague error", "Error code {:?}", 3);
///
/// assert_eq!(&formatted[..], "Error code 3");
/// assert!(formatted.is_owned());
///
/// let not_formatted = format_if!(false, "Vague error", "Error code {:?}", {
/// // Note that the argument is not evaluated.
/// panic!("oops");
/// });
///
/// assert_eq!(&not_formatted[..], "Vague error");
/// assert!(not_formatted.is_borrowed())
/// # }
/// ```
#[macro_export]
macro_rules! format_if {
($enabled:expr, $borrowed:expr, $fmt:expr, $($args:expr),*) => {
if $enabled {
::std::borrow::Cow::Owned(format!($fmt, $($args),*))
} else {
::std::borrow::Cow::Borrowed($borrowed)
}
}
}
4 changes: 4 additions & 0 deletions src/lib.rs
Expand Up @@ -6,3 +6,7 @@
//! A collection of great and ubiqutitous macros.
//!

pub mod test;
pub mod mem;
pub mod format;
pub mod syntax_ext;
44 changes: 44 additions & 0 deletions src/mem.rs
@@ -0,0 +1,44 @@
//! Macros for low-level memory manipulation.

/// Make a tuple of the addresses of some of a struct's fields.
///
/// This is useful when you are transmuting between struct types
/// and would like an additional dynamic check that the layouts
/// match. It's difficult to make such an assertion statically
/// in Rust at present.
///
/// # Example
///
/// ```
/// # #[macro_use] extern crate mac;
/// use std::mem;
///
/// # fn main() {
/// struct Foo { x: i32, y: i32 }
/// struct Bar { x: u32, y: u32 }
///
/// let foo = Foo { x: 3, y: 4 };
/// let old_addrs = addrs_of!(foo => x, y);
///
/// let bar = unsafe {
/// mem::transmute::<&Foo, &Bar>(&foo)
/// };
/// let new_addrs = addrs_of!(bar => x, y);
/// assert_eq!(old_addrs, new_addrs);
///
/// assert_eq!(bar.x, 3);
/// assert_eq!(bar.y, 4);
/// # }
/// ```
#[macro_export]
macro_rules! addrs_of {
($obj:expr => $($field:ident),+) => {
( // make a tuple
$(
unsafe {
::std::mem::transmute::<_, usize>(&$obj.$field)
}
),+
)
}
}
31 changes: 31 additions & 0 deletions src/syntax_ext.rs
@@ -0,0 +1,31 @@
//! Macros useful when writing procedural syntax extensions.
//!
//! The macros themselves are ordinary `macro_rules!` macros.

/// Call `span_err` on an `ExtCtxt` and return `DummyResult::any`.
#[macro_export]
macro_rules! ext_bail {
($cx:expr, $sp:expr, $msg:expr) => {{
$cx.span_err($sp, $msg);
return ::syntax::ext::base::DummyResult::any($sp);
}}
}

/// `ext_bail!` if the condition `$e` is true.
#[macro_export]
macro_rules! ext_bail_if {
($e:expr, $cx:expr, $sp:expr, $msg:expr) => {{
if $e { ext_bail!($cx, $sp, $msg) }
}}
}

/// Unwrap the `Option` `$e`, or `ext_bail!`.
#[macro_export]
macro_rules! ext_expect {
($cx:expr, $sp:expr, $e:expr, $msg:expr) => {{
match $e {
Some(x) => x,
None => ext_bail!($cx, $sp, $msg),
}
}}
}
24 changes: 24 additions & 0 deletions src/test.rs
@@ -0,0 +1,24 @@
//! Macros for writing test suites.

/// Generate a test function `$name` which asserts that `$left` and `$right`
/// are equal.
///
/// # Example
///
/// ```
/// # #[macro_use] extern crate mac;
/// mod test {
/// # // doesn't actually run the test :/
/// test_eq!(two_and_two_is_four, 2 + 2, 4);
/// }
/// # fn main() { }
/// ```
#[macro_export]
macro_rules! test_eq {
($name:ident, $left:expr, $right:expr) => {
#[test]
fn $name() {
assert_eq!($left, $right);
}
}
}

0 comments on commit 63084a5

Please sign in to comment.