write.rs 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. //! Direct libc-based write for internal debugging.
  2. //!
  3. //! This will replace the assertion macros to avoid deadlocks in panics, by utilizing a
  4. //! non-allocating writing primitive.
  5. use prelude::*;
  6. use core::fmt;
  7. use sys;
  8. /// The line lock.
  9. ///
  10. /// This lock is used to avoid bungling and intertwining lines.
  11. pub static LINE_LOCK: Mutex<()> = Mutex::new(());
  12. /// A log writer.
  13. ///
  14. /// This writes to `sys::log`.
  15. pub struct Writer;
  16. impl Writer {
  17. /// Standard error output.
  18. pub fn new() -> Writer {
  19. Writer
  20. }
  21. }
  22. impl fmt::Write for Writer {
  23. fn write_str(&mut self, s: &str) -> fmt::Result {
  24. if sys::log(s).is_err() {
  25. Err(fmt::Error)
  26. } else { Ok(()) }
  27. }
  28. }
  29. /// Make a runtime assertion.
  30. ///
  31. /// The only way it differs from the one provided by `libcore` is the panicking strategy, which
  32. /// allows for aborting, non-allocating panics when running the tests.
  33. #[macro_export]
  34. macro_rules! assert {
  35. ($e:expr) => {
  36. assert!($e, "No description.");
  37. };
  38. ($e:expr, $( $arg:expr ),*) => {{
  39. use write;
  40. use core::intrinsics;
  41. use core::fmt::Write;
  42. if !$e {
  43. // To avoid cluttering the lines, we acquire a lock.
  44. let _lock = write::LINE_LOCK.lock();
  45. let mut log = write::Writer::new();
  46. let _ = write!(log, "assertion failed at {}:{}: `{}` - ", file!(),
  47. line!(), stringify!($e));
  48. let _ = writeln!(log, $( $arg ),*);
  49. #[allow(unused_unsafe)]
  50. unsafe { intrinsics::abort() }
  51. }
  52. }}
  53. }
  54. /// Make a runtime assertion in debug mode.
  55. ///
  56. /// The only way it differs from the one provided by `libcore` is the panicking strategy, which
  57. /// allows for aborting, non-allocating panics when running the tests.
  58. #[macro_export]
  59. macro_rules! debug_assert {
  60. // We force the programmer to provide explanation of their assertion.
  61. ($first:expr, $( $arg:tt )*) => {{
  62. if cfg!(debug_assertions) {
  63. assert!($first, $( $arg )*);
  64. }
  65. }}
  66. }
  67. /// Make a runtime equality assertion in debug mode.
  68. ///
  69. /// The only way it differs from the one provided by `libcore` is the panicking strategy, which
  70. /// allows for aborting, non-allocating panics when running the tests.
  71. #[macro_export]
  72. macro_rules! assert_eq {
  73. ($left:expr, $right:expr) => ({
  74. // We evaluate _once_.
  75. let left = &$left;
  76. let right = &$right;
  77. assert!(left == right, "(left: `{:?}`, right: `{:?}`)", left, right)
  78. })
  79. }