- If you find a rule/best practice that does not make sense or seems not Rust idiomatic then please pack your suggestion in a pull request and we discuss and merge it.
- information dedicated to the developer of the application
TRACE- interesting application events, e.g. whenever a resource is created/destroyedDEBUG- only when the function returns a result that contains an error
- information dedicated to the user of the application
INFO- some interesting stuff for the userWARN- warnings dedicated to the user of the application, the functionality is not restricted but some kind of internal recoverable misbehavior occurredERROR- some severe failure occurred that is still handled with a result containing an error but the application can continue if the user can recover from itFATAL- the application panics after the log output
- Never return
Err(...), always usefail!macro.- iceoryx2 shall always log a message to
DEBUGwhenever anErr(...)is. - When providing for instance
selfas origin, the current state of the object that caused the problem is logged.// bad impl MyStruct { fn do_stuff(&self) -> Result<u64, u64> { Err(123) } } // good use iceoryx2_bb_log::fail; impl MyStruct { fn do_stuff(&self) -> Result<u64, u64> { // uses Debug to print self fail!(from self, with 123, "Failed to do stuff!"); } }
- iceoryx2 shall always log a message to
-
Never call
panic!(...)directly, always use thefatal_panic!macro.- iceoryx2 shall always log a message to
FATALwhenever a panic occurs. - When providing for instance
selfas origin, the current state of the object that caused the problem is logged.// bad impl MyStruct { fn whatever(&self) { panic!("whatever"); } } // good impl MyStruct { fn whatever(&self) { // uses Debug to print self fatal_panic!(from self, "whatever"); } }
- iceoryx2 shall always log a message to
-
If a panic error check is expensive and located on the hot path then use
debug_assert!.- Use it only when the panic check prevents API misuse and the misbehavior can
be easily detected with unit tests
// bad if expensive_check() { fatal_panic!("oh no ..."); } // good debug_assert!(expensive_check(), "oh no ...");
- Use it only when the panic check prevents API misuse and the misbehavior can
be easily detected with unit tests
-
The most common functionality of a construct shall be fully usable by only using:
use my::construct::prelude::*;
-
Use
pub use ...to re-export requirements. -
Use preludes, see https://doc.rust-lang.org/beta/reference/names/preludes.html
- Use
?operator in documentation examples to reduce error handling clutter. - Use
#to hide boilerplate code in documentation
- Use the
ouroboroscrate for self-referencing structs, required for non-movable types likeMutex&MutexHandle,Barrier&BarrierHandle,UnnamedSemaphore&SemaphoreHandle
- Always use the
assert_that!macro fromiceoryx2_bb_testing
- Never test a maximum runtime in a unit or integration test.
- Test at least runtimes with
assert_that!(start.elapsed(), time_at_least TIMEOUT) - Do not wait for events (indefinitely), use
assert_that!(|| { some_condition }, eq true, before Watchdog::default())- The watchdog will terminate the test in case of deadlock
- If the test can deadlock, instantiate a
iceoryx2_bb_testing::watchdog::Watchdogin the beginning of the test.