Line data Source code
1 : //! LIEF's logging API
2 : //!
3 : //! This module contains function to tweak or use LIEF's logging mechanisms
4 : //!
5 : //!
6 : //! ```
7 : //! use lief::logging;
8 : //!
9 : //! logging::set_level(logging::Level::DEBUG);
10 : //! logging::log(logging::Level::DEBUG, "Hi!");
11 : //! ```
12 :
13 : use lief_ffi as ffi;
14 :
15 : use std::convert::{From, Into};
16 : use std::path::Path;
17 :
18 : #[allow(non_camel_case_types)]
19 7 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
20 : /// The different levels of log
21 : pub enum Level {
22 : OFF,
23 : TRACE,
24 : DEBUG,
25 : INFO,
26 : WARN,
27 : ERR,
28 : CRITICAL,
29 : UNKNOWN(u32),
30 : }
31 :
32 : impl From<u32> for Level {
33 91 : fn from(value: u32) -> Self {
34 91 : match value {
35 0 : 0x00000000 => Level::OFF,
36 13 : 0x00000001 => Level::TRACE,
37 26 : 0x00000002 => Level::DEBUG,
38 39 : 0x00000003 => Level::INFO,
39 13 : 0x00000004 => Level::WARN,
40 0 : 0x00000005 => Level::ERR,
41 0 : 0x00000006 => Level::CRITICAL,
42 0 : _ => Level::UNKNOWN(value),
43 : }
44 91 : }
45 : }
46 :
47 : impl From<Level> for u32 {
48 156 : fn from(value: Level) -> Self {
49 156 : match value {
50 0 : Level::OFF => 0x00000000,
51 13 : Level::TRACE => 0x00000001,
52 52 : Level::DEBUG => 0x00000002,
53 39 : Level::INFO => 0x00000003,
54 26 : Level::WARN => 0x00000004,
55 26 : Level::ERR => 0x00000005,
56 0 : Level::CRITICAL => 0x00000006,
57 0 : Level::UNKNOWN(_) => 0x00000003, // INFO
58 : }
59 156 : }
60 : }
61 :
62 : /// Reset the current logger
63 26 : pub fn reset() {
64 26 : ffi::LIEF_Logging::reset()
65 26 : }
66 :
67 : /// Prevent any log message from being printed
68 13 : pub fn disable() {
69 13 : ffi::LIEF_Logging::disable()
70 13 : }
71 :
72 : /// Enable the logger
73 13 : pub fn enable() {
74 13 : ffi::LIEF_Logging::enable()
75 13 : }
76 :
77 : /// Change the logging level
78 : ///
79 : /// ```
80 : /// set_level(Level::INFO)
81 : /// ```
82 52 : pub fn set_level(level: Level) {
83 52 : ffi::LIEF_Logging::set_level(level.into())
84 52 : }
85 : /// Switch to a file-based logger (instead of stderr-based)
86 : ///
87 : /// ```
88 : /// let mut tmp = env::temp_dir();
89 : /// tmp.push("lief_log.log");
90 : /// logging::set_path(dir.as_path());
91 : /// ```
92 5 : pub fn set_path<P: AsRef<Path>>(path: P) {
93 5 : ffi::LIEF_Logging::set_path(path.as_ref().to_str().expect("Can't convert into string"))
94 5 : }
95 :
96 : /// Log a message with the logger
97 65 : pub fn log(level: Level, message: &str) {
98 65 : ffi::LIEF_Logging::log(level.into(), message)
99 65 : }
100 :
101 : /// Return the current logging level
102 91 : pub fn get_level() -> Level {
103 91 : Level::from(ffi::LIEF_Logging::get_level())
104 91 : }
105 :
106 : /// RAII-like scoped log level.
107 : ///
108 : ///
109 : /// ```
110 : /// use lief::logging;
111 : ///
112 : /// logging::set_level(logging::Level::INFO);
113 : ///
114 : /// {
115 : /// let _scoped = logging::Scoped::new(logging::Level::DEBUG);
116 : /// // Log level is now DEBUG
117 : /// }
118 : /// // Log level is restored to INFO
119 : /// ```
120 : pub struct Scoped {
121 : inner: cxx::UniquePtr<ffi::LIEF_Logging_Scoped>,
122 : }
123 :
124 : impl Scoped {
125 : /// Create a new scoped log level. The current log level is saved and
126 : /// replaced with the provided `level`. When this value is dropped, the
127 : /// original level is restored.
128 13 : pub fn new(level: Level) -> Self {
129 13 : Self {
130 13 : inner: ffi::LIEF_Logging_Scoped::create(level.into()),
131 13 : }
132 13 : }
133 :
134 : /// Change the log level within this scope
135 26 : pub fn set_level(&self, level: Level) {
136 26 : self.inner.set_level(level.into())
137 26 : }
138 :
139 : /// Reset the log level to the value it had before this scope was created
140 13 : pub fn reset(&mut self) {
141 13 : self.inner.pin_mut().reset()
142 13 : }
143 : }
144 :
145 : #[doc(hidden)]
146 : #[macro_export]
147 : macro_rules! __lief_log {
148 : ($level: expr) => {
149 : lief::logging::log($level, "")
150 : };
151 : ($level: expr, $($arg:tt)*) => {{
152 : lief::logging::log($level, &format!($($arg)*));
153 : }};
154 : }
155 :
156 : #[macro_export]
157 : macro_rules! log_dbg {
158 : ($($args:tt)*) => {
159 : $crate::__lief_log!(lief::logging::Level::DEBUG, $($args)*)
160 : };
161 : }
162 :
163 : #[macro_export]
164 : macro_rules! log_info {
165 : ($($args:tt)*) => {
166 : $crate::__lief_log!(lief::logging::Level::INFO, $($args)*)
167 : };
168 : }
169 :
170 : #[macro_export]
171 : macro_rules! log_warn {
172 : ($($args:tt)*) => {
173 : $crate::__lief_log!(lief::logging::Level::WARN, $($args)*)
174 : };
175 : }
176 :
177 : #[macro_export]
178 : macro_rules! log_err {
179 : ($($args:tt)*) => {
180 : $crate::__lief_log!(lief::logging::Level::ERR, $($args)*)
181 : };
182 : }
|