pw_assert/pw_assert.rs
1// Copyright 2025 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14#![no_std]
15
16//! # pw_assert
17//!
18//! `pw_assert` provides crash-safe assert and panic macros that route to a
19//! configured backend. This is designed for embedded systems where standard
20//! library panics might not be suitable, or where specific logging/recovery
21//! behavior is needed.
22//!
23//! The macros in this crate are designed to be drop-in replacements for
24//! `core::panic!`, `core::assert!`, etc., and delegate to backend macros:
25//! - [`panic!`] and [`debug_panic!`] -> `panic_backend!`
26//! - [`assert!`] and [`debug_assert!`] -> `assert_unary_backend!`
27//! - [`eq!`], [`ne!`], [`debug_eq!`], and [`debug_ne!`] -> `assert_binary_backend!`
28//!
29//! # Example
30//!
31//! ```no_run
32//! pw_assert::assert!(42 == 16, "Stack start is not aligned");
33//!
34//! pw_assert::panic!("Unhandled interrupt: irq={}", 16 as u32);
35//!
36//! pw_assert::debug_assert!(1 == 0);
37//!
38//! pw_assert::debug_panic!("Next monotonic tick overflow");
39//! ```
40
41// Re-export backend macros for use by facade macros.
42#[doc(hidden)]
43pub mod __private {
44 pub use pw_assert_backend::{assert_binary_backend, assert_unary_backend, panic_backend};
45}
46
47/// Panics unconditionally.
48///
49/// This macro delegates to the backend macro `panic_backend!`.
50///
51/// # Examples
52///
53/// ```no_run
54/// pw_assert::panic!("Something went terribly wrong!");
55///
56/// pw_assert::panic!("Error code: {}", 42 as i32);
57/// ```
58#[macro_export]
59macro_rules! panic {
60 ($($arg:tt)*) => {
61 $crate::__private::panic_backend!($($arg)*)
62 };
63}
64
65/// Panics unconditionally when debug_assertions are enabled
66///
67/// If `debug_assertions` are enabled, this behaves exactly like [`panic!`]
68/// (delegating to `panic_backend!`).
69/// If `debug_assertions` are disabled, this macro is a no-op.
70///
71/// `debug_assertions` can be enabled by setting this bazel label to `True`
72/// `@pigweed//pw_assert/rust:debug_assertions`.
73///
74/// # Examples
75///
76/// ```no_run
77/// pw_assert::debug_panic!("This should never happen in debug mode.");
78/// ```
79#[macro_export]
80#[cfg(feature = "debug_assertions")]
81macro_rules! debug_panic {
82 ($($arg:tt)*) => {
83 $crate::__private::panic_backend!($($arg)*)
84 };
85}
86
87/// Panics unconditionally when debug_assertions are enabled.
88#[macro_export]
89#[cfg(not(feature = "debug_assertions"))]
90macro_rules! debug_panic {
91 ($($arg:tt)*) => {};
92}
93
94/// Asserts that a condition is true.
95///
96/// If the condition evaluates to `false`, this macro delegates to the backend
97/// macro `assert_unary_backend!`.
98///
99/// # Examples
100///
101/// ```no_run
102/// let x = 5;
103/// pw_assert::assert!(x > 0);
104/// pw_assert::assert!(x == 5, "x should be 5, but was {}", x as i32);
105/// ```
106#[macro_export]
107macro_rules! assert {
108 ($condition:expr $(,)?) => {{
109 $crate::__private::assert_unary_backend!($condition);
110 }};
111
112 ($condition:expr, $($args:expr),* $(,)?) => {{
113 $crate::__private::assert_unary_backend!($condition, $($args),*);
114 }};
115}
116
117/// Asserts that a condition is true when debug_assertions are enabled.
118///
119/// If `debug_assertions` are enabled, this behaves exactly like [`assert!`]
120/// (delegating to `assert_unary_backend!` if the condition evaluates to `false`).
121/// If `debug_assertions` are disabled, this macro is a no-op.
122///
123/// `debug_assertions` can be enabled by setting this bazel label to `True`
124/// `@pigweed//pw_assert/rust:debug_assertions`.
125///
126/// # Examples
127///
128/// ```no_run
129/// let x = 5;
130/// pw_assert::debug_assert!(x == 5);
131/// ```
132#[macro_export]
133#[cfg(feature = "debug_assertions")]
134macro_rules! debug_assert {
135 ($condition:expr $(,)?) => {{
136 $crate::__private::assert_unary_backend!($condition);
137 }};
138
139 ($condition:expr, $($args:expr),* $(,)?) => {{
140 $crate::__private::assert_unary_backend!($condition, $($args),*);
141 }};
142}
143
144/// Asserts that a condition is true when debug_assertions are enabled.
145#[macro_export]
146#[cfg(not(feature = "debug_assertions"))]
147macro_rules! debug_assert {
148 ($($arg:tt)*) => {};
149}
150
151/// Asserts that two expressions are equal (equivalent to `assert_eq!`).
152///
153/// If the expressions are not equal, this macro delegates to the backend macro
154/// `assert_binary_backend!`.
155///
156/// Note that depending on the backend, both expressions may need to be cast
157/// expressions (e.g., `x as i32`).
158///
159/// # Examples
160///
161/// ```no_run
162/// let x = 5;
163/// pw_assert::eq!(x as i32, 5 as i32);
164/// pw_assert::eq!(x as i32, 5 as i32, "x should be 5");
165/// ```
166#[macro_export]
167macro_rules! eq {
168 ($lhs:expr, $rhs:expr $(,)?) => {{
169 $crate::__private::assert_binary_backend!($lhs, ==, $rhs);
170 }};
171
172 ($lhs:expr, $rhs:expr, $($args:expr),* $(,)?) => {{
173 $crate::__private::assert_binary_backend!($lhs, ==, $rhs, $($args),*);
174 }};
175}
176
177/// Asserts that two expressions are not equal (equivalent to `assert_ne!`).
178///
179/// If the expressions are equal, this macro delegates to the backend macro
180/// `assert_binary_backend!`.
181///
182/// Note that depending on the backend, both expressions may need to be cast
183/// expressions (e.g., `x as i32`).
184///
185/// # Examples
186///
187/// ```no_run
188/// let x = 5;
189/// pw_assert::ne!(x as i32, 6 as i32);
190/// pw_assert::ne!(x as i32, 6 as i32, "x should not be 6");
191/// ```
192#[macro_export]
193macro_rules! ne {
194 ($lhs:expr, $rhs:expr $(,)?) => {{
195 $crate::__private::assert_binary_backend!($lhs, !=, $rhs);
196 }};
197
198 ($lhs:expr, $rhs:expr, $($args:expr),* $(,)?) => {{
199 $crate::__private::assert_binary_backend!($lhs, !=, $rhs, $($args),*);
200 }};
201}
202
203/// Asserts that two expressions are equal when debug_assertions are enabled.
204///
205/// If `debug_assertions` are enabled, this behaves exactly like [`eq!`].
206/// If `debug_assertions` are disabled, this macro is a no-op.
207///
208/// `debug_assertions` can be enabled by setting this bazel label to `True`
209/// `@pigweed//pw_assert/rust:debug_assertions`.
210///
211/// # Examples
212///
213/// ```no_run
214/// let x = 5;
215/// pw_assert::debug_eq!(x as i32, 5 as i32);
216/// ```
217#[macro_export]
218#[cfg(feature = "debug_assertions")]
219macro_rules! debug_eq {
220 ($lhs:expr, $rhs:expr $(,)?) => {{
221 $crate::__private::assert_binary_backend!($lhs, ==, $rhs);
222 }};
223
224 ($lhs:expr, $rhs:expr, $($args:expr),* $(,)?) => {{
225 $crate::__private::assert_binary_backend!($lhs, ==, $rhs, $($args),*);
226 }};
227}
228
229/// Asserts that two expressions are equal when debug_assertions are enabled.
230#[macro_export]
231#[cfg(not(feature = "debug_assertions"))]
232macro_rules! debug_eq {
233 ($($arg:tt)*) => {};
234}
235
236/// Asserts that two expressions are not equal when debug_assertions are enabled.
237///
238/// If `debug_assertions` are enabled, this behaves exactly like [`ne!`].
239/// If `debug_assertions` are disabled, this macro is a no-op.
240///
241/// `debug_assertions` can be enabled by setting this bazel label to `True`
242/// `@pigweed//pw_assert/rust:debug_assertions`.
243///
244/// # Examples
245///
246/// ```no_run
247/// let x = 5;
248/// pw_assert::debug_ne!(x as i32, 6 as i32);
249/// ```
250#[macro_export]
251#[cfg(feature = "debug_assertions")]
252macro_rules! debug_ne {
253 ($lhs:expr, $rhs:expr $(,)?) => {{
254 $crate::__private::assert_binary_backend!($lhs, !=, $rhs);
255 }};
256
257 ($lhs:expr, $rhs:expr, $($args:expr),* $(,)?) => {{
258 $crate::__private::assert_binary_backend!($lhs, !=, $rhs, $($args),*);
259 }};
260}
261
262/// Asserts that two expressions are not equal when debug_assertions are enabled.
263#[macro_export]
264#[cfg(not(feature = "debug_assertions"))]
265macro_rules! debug_ne {
266 ($($arg:tt)*) => {};
267}