write.rs 2.7 KB

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