1use crate::CvlrLogger;
2
3pub trait CvlrLog {
4 fn log(&self, tag: &str, logger: &mut CvlrLogger);
5}
6
7#[inline(always)]
8pub fn cvlr_log_with<T: CvlrLog>(tag: &str, val: &T, logger: &mut CvlrLogger) {
9 val.log(tag, logger);
10}
11
12#[inline(always)]
13pub fn cvlr_log<T: CvlrLog>(tag: &str, val: &T) {
14 let mut logger = CvlrLogger::new();
15 val.log(tag, &mut logger);
16}
17
18#[cfg(not(feature = "no-loc"))]
19#[macro_export]
20macro_rules! cvlr_log_core_file {
21 () => {
22 ::core::file!()
23 };
24}
25
26#[cfg(not(feature = "no-loc"))]
27#[macro_export]
28macro_rules! cvlr_log_core_line {
29 () => {
30 ::core::line!()
31 };
32}
33
34#[cfg(feature = "no-loc")]
35#[macro_export]
36macro_rules! cvlr_log_core_file {
37 () => {
38 "<FILE>"
39 };
40}
41
42#[cfg(feature = "no-loc")]
43#[macro_export]
44macro_rules! cvlr_log_core_line {
45 () => {
46 0u32
47 };
48}
49
50#[macro_export]
51macro_rules! cvlr_log {
52 () => {
53 $crate::log_loc($crate::cvlr_log_core_file!(), $crate::cvlr_log_core_line!());
54 };
55
56 ($v:expr => $t:expr ; $logger:ident) => {
58 $crate::cvlr_log_with($t, &($v), &mut $logger)
59 };
60
61 ($v:expr => $t:expr, $( $vs:expr => $ts:expr ),+ $(,)?) => {
63 $crate::cvlr_log! { $v => $t }
64 $crate::cvlr_log! { $( $vs => $ts ),+ }
65 };
66
67 ($v:expr => $t:expr, $( $rest:tt )+) => {
69 $crate::cvlr_log! { $v => $t }
70 $crate::cvlr_log! { $( $rest )+ }
71 };
72
73 ($v:expr => $t:expr) => {
74 $crate::cvlr_log($t, &($v));
77 };
78
79 ($v:expr $(,)?) => {
80 $crate::cvlr_log! { $v => stringify!($v) }
81 };
82
83 ($v:expr, $( $rest:tt )+) => {
85 $crate::cvlr_log! { $v }
86 $crate::cvlr_log! { $( $rest )+ }
87 };
88}
89
90pub use cvlr_log as clog;
91
92macro_rules! impl_cvlr_log_for_uint {
93 ($t:ty) => {
94 impl CvlrLog for $t {
95 #[inline(always)]
96 fn log(&self, tag: &str, logger: &mut CvlrLogger) {
97 logger.log_u64(tag, *self as u64);
98 }
99 }
100 };
101}
102
103impl_cvlr_log_for_uint!(bool);
104impl_cvlr_log_for_uint!(u8);
105impl_cvlr_log_for_uint!(u16);
106impl_cvlr_log_for_uint!(u32);
107impl_cvlr_log_for_uint!(u64);
108impl_cvlr_log_for_uint!(usize);
109
110impl CvlrLog for u128 {
111 #[inline(always)]
112 fn log(&self, tag: &str, logger: &mut CvlrLogger) {
113 logger.log_u128(tag, *self);
114 }
115}
116
117macro_rules! impl_cvlr_log_for_int {
118 ($t:ty) => {
119 impl CvlrLog for $t {
120 #[inline(always)]
121 fn log(&self, tag: &str, logger: &mut CvlrLogger) {
122 logger.log_i64(tag, *self as i64);
123 }
124 }
125 };
126}
127
128impl_cvlr_log_for_int!(i8);
129impl_cvlr_log_for_int!(i16);
130impl_cvlr_log_for_int!(i32);
131impl_cvlr_log_for_int!(i64);
132
133impl CvlrLog for i128 {
134 #[inline(always)]
135 fn log(&self, tag: &str, logger: &mut CvlrLogger) {
136 logger.log_i128(tag, *self);
137 }
138}
139
140impl<T: CvlrLog> CvlrLog for &T {
141 #[inline(always)]
142 fn log(&self, tag: &str, logger: &mut CvlrLogger) {
143 (**self).log(tag, logger);
144 }
145}
146
147impl CvlrLog for &str {
148 #[inline(always)]
149 fn log(&self, _tag: &str, logger: &mut CvlrLogger) {
150 logger.log(self);
151 }
152}
153
154impl CvlrLog for () {
155 #[inline(always)]
156 fn log(&self, tag: &str, logger: &mut CvlrLogger) {
157 logger.log_str(tag, "()");
158 }
159}
160
161impl<T: CvlrLog> CvlrLog for Option<T> {
162 #[inline(always)]
163 fn log(&self, tag: &str, logger: &mut CvlrLogger) {
164 if let Some(v) = self {
165 v.log(tag, logger);
166 } else {
167 logger.log_str(tag, "None");
168 }
169 }
170}
171
172impl<T: CvlrLog, E: CvlrLog> CvlrLog for Result<T, E> {
173 #[inline(always)]
174 fn log(&self, tag: &str, logger: &mut CvlrLogger) {
175 match self {
176 Ok(v) => {
177 logger.log("Ok");
178 v.log(tag, logger)
179 }
180 Err(v) => {
181 logger.log("Err");
182 v.log(tag, logger)
183 }
184 }
185 }
186}
187
188#[cfg(feature = "mathint")]
189impl CvlrLog for cvlr_mathint::NativeInt {
190 #[inline(always)]
191 fn log(&self, tag: &str, logger: &mut CvlrLogger) {
192 logger.log_u64(tag, self.as_internal());
193 }
194}
195
196#[macro_export]
208macro_rules! impl_cvlr_log_for_struct {
209 ($prop:path $(, $field:ident)* $(,)?) => {
210 impl $crate::CvlrLog for $prop {
211 fn log(&self, tag: &str, logger: &mut $crate::CvlrLogger) {
212 logger.log_scope_start(tag);
213 let __self = self;
214 $(impl_cvlr_log_for_struct!(@field __self, logger, $field);)*
215 logger.log_scope_end(tag);
216 }
217 }
218 };
219
220 (@field $self:ident, $logger:ident, $field:ident) => {
221 $crate::cvlr_log_with(stringify!($field), &$self.$field, $logger);
222 };
223}
224
225pub use impl_cvlr_log_for_struct as impl_clog_for_struct;