#[macro_export]
macro_rules! log {
(INTERNAL, $( $x:tt )*) => {
log!(@["INTERNAL: ", 1], $( $x )*);
};
(DEBUG, $( $x:tt )*) => {
log!(@["DEBUG: ", 2], $( $x )*);
};
(CALL, $( $x:tt )*) => {
log!(@["CALL: ", 3], $( $x )*);
};
(NOTE, $( $x:tt )*) => {
log!(@["NOTE: ", 5], $( $x )*);
};
(WARNING, $( $x:tt )*) => {
log!(@["WARNING: ", 5], $( $x )*);
};
(ERROR, $( $x:tt )*) => {
log!(@["ERROR: ", 6], $( $x )*);
};
(@[$kind:expr, $lv:expr], $( $arg:expr ),*) => {
#[cfg(feature = "log")]
{
use core::fmt::Write;
use log::internal::{LogWriter, level};
if level($lv) {
let mut log = LogWriter::new();
let _ = write!(log, $kind);
let _ = write!(log, $( $arg ),*);
let _ = writeln!(log, " (at {}:{})", file!(), line!());
}
}
};
}
#[macro_export]
macro_rules! bk_log {
($pool:expr, $( $arg:expr ),*) => {
bk_log!($pool;(), $( $arg ),*);
};
($bk:expr;$cur:expr, $( $arg:expr ),*) => {
#[cfg(feature = "log")]
{
use log::internal::{IntoCursor, BlockLogger};
log!(INTERNAL, "({:2}) {:10?} : {}", $bk.id, BlockLogger {
cur: $cur.clone().into_cursor(),
blocks: &$bk.pool,
}, format_args!($( $arg ),*));
}
};
}
#[macro_export]
#[cfg(feature = "write")]
macro_rules! assert {
($e:expr) => {
assert!($e, "No description.");
};
($e:expr, $( $arg:expr ),*) => {{
use core::intrinsics;
if !$e {
log!(ERROR, $( $arg ),*);
#[allow(unused_unsafe)]
unsafe {
intrinsics::abort();
}
}
}}
}
#[cfg(feature = "write")]
#[macro_export]
macro_rules! debug_assert {
($first:expr, $( $arg:tt )*) => {{
if cfg!(debug_assertions) {
assert!($first, $( $arg )*);
}
}}
}
#[cfg(feature = "write")]
#[macro_export]
macro_rules! assert_eq {
($left:expr, $right:expr) => ({
let left = &$left;
let right = &$right;
assert!(left == right, "(left: '{:?}', right: '{:?}')", left, right)
})
}
#[cfg(feature = "log")]
pub mod internal {
use prelude::*;
use core::fmt;
use core::cell::Cell;
use core::ops::Range;
use shim::config;
use sync;
#[cfg(not(feature = "no_log_lock"))]
pub static LOG_LOCK: Mutex<()> = Mutex::new(());
pub struct LogWriter {
#[cfg(not(feature = "no_log_lock"))]
_lock: sync::MutexGuard<'static, ()>,
}
impl LogWriter {
pub fn new() -> LogWriter {
#[cfg(feature = "no_log_lock")]
{
LogWriter {}
}
#[cfg(not(feature = "no_log_lock"))]
LogWriter {
_lock: LOG_LOCK.lock(),
}
}
}
impl fmt::Write for LogWriter {
fn write_str(&mut self, s: &str) -> fmt::Result {
if config::log(s) == !0 { Err(fmt::Error) } else { Ok(()) }
}
}
pub trait Cursor {
fn at(&self, f: &mut fmt::Formatter, n: usize) -> fmt::Result;
fn after(&self, f: &mut fmt::Formatter) -> fmt::Result;
}
pub trait IntoCursor {
type Cursor: Cursor;
fn into_cursor(self) -> Self::Cursor;
}
pub struct UniCursor {
pos: usize,
is_printed: Cell<bool>,
}
impl Cursor for UniCursor {
fn at(&self, f: &mut fmt::Formatter, n: usize) -> fmt::Result {
if self.pos == n {
self.is_printed.set(true);
write!(f, "|")?;
}
Ok(())
}
fn after(&self, f: &mut fmt::Formatter) -> fmt::Result {
if !self.is_printed.get() {
write!(f, "…|")?;
}
Ok(())
}
}
impl IntoCursor for usize {
type Cursor = UniCursor;
fn into_cursor(self) -> UniCursor {
UniCursor {
pos: self,
is_printed: Cell::new(false),
}
}
}
impl Cursor for () {
fn at(&self, _: &mut fmt::Formatter, _: usize) -> fmt::Result { Ok(()) }
fn after(&self, _: &mut fmt::Formatter) -> fmt::Result { Ok(()) }
}
impl IntoCursor for () {
type Cursor = ();
fn into_cursor(self) -> () {
()
}
}
pub struct RangeCursor {
range: Range<usize>,
}
impl Cursor for RangeCursor {
fn at(&self, f: &mut fmt::Formatter, n: usize) -> fmt::Result {
if self.range.start == n {
write!(f, "[")?;
} else if self.range.end == n {
write!(f, "]")?;
}
Ok(())
}
fn after(&self, _: &mut fmt::Formatter) -> fmt::Result { Ok(()) }
}
impl IntoCursor for Range<usize> {
type Cursor = RangeCursor;
fn into_cursor(self) -> RangeCursor {
RangeCursor {
range: self,
}
}
}
pub struct BlockLogger<'a, T> {
pub cur: T,
pub blocks: &'a [Block],
}
impl<'a, T: Cursor> fmt::Debug for BlockLogger<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for (n, i) in self.blocks.iter().enumerate() {
self.cur.at(f, n)?;
if i.is_empty() {
write!(f, "_")?;
} else {
write!(f, "x")?;
}
}
self.cur.after(f)?;
Ok(())
}
}
#[allow(absurd_extreme_comparisons)]
#[inline]
pub fn level(lv: u8) -> bool {
lv >= config::MIN_LOG_LEVEL
}
}