1mod types;
2
3use crate::types::{QuoPayload, QuoPayloadLanguage, QuoPayloadMeta, QuoPayloadVariable};
4use std::fmt::Debug;
5use std::time::{SystemTime, UNIX_EPOCH};
6use ureq::config::Config;
7
8#[cfg(debug_assertions)]
19#[doc(hidden)]
20fn quo_create_payload<T: Debug>(
21 value: T,
22 name: &str,
23 line: u32,
24 file: &str,
25 is_mutable: bool,
26) -> QuoPayload {
27 let var_type = std::any::type_name_of_val(&value).to_string();
28 let name = name;
29 let value = format!("{:?}", value);
30 let line = line;
31 let file = file;
32 let package_name = option_env!("CARGO_PKG_NAME").unwrap_or("Rust project");
33
34 let since_the_epoch = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
35
36 QuoPayload {
37 language: QuoPayloadLanguage::Rust,
38 meta: QuoPayloadMeta {
39 id: 0,
40 uid: since_the_epoch.as_nanos().to_string(),
41 origin: package_name.to_string(),
42 sender_origin: format!("{}:{}", file, line),
43 time_epoch_ms: since_the_epoch.as_millis() as i64,
44 variable: QuoPayloadVariable {
45 var_type: var_type.clone(),
46 name: name.to_string(),
47 value: value.clone(),
48 mutable: is_mutable,
49 is_constant: name == name.to_uppercase(),
51 },
52 },
53 }
54}
55
56#[cfg(debug_assertions)]
67#[doc(hidden)]
68fn quo<T: Debug>(value: T, name: &str, line: u32, file: &str, is_mutable: bool) -> () {
69 #[cfg(debug_assertions)]
70 {
71 let env_host = option_env!("QUO_HOST").unwrap_or("http://127.0.0.1");
72 let env_port = option_env!("QUO_PORT").unwrap_or("7312");
73
74 let body = quo_create_payload(value, name, line, file, is_mutable);
75
76 let send_fn = move || {
77 let quo_server = format!("{}:{}", env_host, env_port);
78
79 let config = Config::builder()
80 .user_agent("Quo-Rust")
81 .build();
82
83 let agent = config.new_agent();
84
85 let _ = match agent.post(quo_server).send_json(body) {
86 Ok(_response) => {}
87 Err(ureq::Error::StatusCode(code)) => {
88 eprintln!("[Quo] HTTP {} - is Quo running?", code)
89 }
90 Err(e) => {
91 eprintln!("[Quo] error \"{}\" - is Quo running?", e.to_string())
92 }
93 };
94 };
95
96 #[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))]
97 {
98 send_fn();
99 }
100
101 #[cfg(not(all(target_arch = "wasm32", not(target_feature = "atomics"))))]
102 {
103 std::thread::spawn(send_fn);
104 }
105 }
106}
107
108#[cfg(debug_assertions)]
109#[doc(hidden)]
110pub fn __private_quo<T: Debug>(
111 value: T,
112 name: &str,
113 line: u32,
114 file: &str,
115 is_mutable: bool,
116) -> () {
117 quo(value, name, line, file, is_mutable)
118}
119
120#[macro_export]
131macro_rules! quo {
132 ($( mut $var:ident ),*) => {{
133 #[cfg(debug_assertions)]
134 $(
135 $crate::__private_quo(&$var, stringify!($var), line!(), file!(), true);
136 )*
137 }};
138 ($( $var:ident ),*) => {{
139 #[cfg(debug_assertions)]
140 $(
141 $crate::__private_quo(&$var, stringify!($var), line!(), file!(), false);
142 )*
143 }};
144}
145
146#[cfg(test)]
147mod tests {
148 use super::*;
149
150 #[test]
151 fn fn_test() {
152 let fn_test_var = 1234;
153
154 let payload = quo_create_payload(&fn_test_var, "fn_test_var", line!(), file!(), false);
155 assert_eq!(payload.meta.variable.name, "fn_test_var");
156 assert_eq!(payload.meta.variable.value, "1234");
157 assert_eq!(payload.meta.variable.var_type, "&i32");
158 assert!(!payload.meta.variable.mutable);
159 assert!(!payload.meta.variable.is_constant);
160 }
161
162 #[test]
163 fn macro_const_test() {
164 const VAR_I32: i32 = -1234;
165
166 quo!(VAR_I32, VAR_I32, VAR_I32);
167
168 let payload = quo_create_payload(&VAR_I32, "VAR_I32", line!(), file!(), false);
169 assert_eq!(payload.meta.variable.name, "VAR_I32");
170 assert_eq!(payload.meta.variable.value, "-1234");
171 assert_eq!(payload.meta.variable.var_type, "&i32");
172 assert!(!payload.meta.variable.mutable);
173 assert!(payload.meta.variable.is_constant);
174 }
175
176 #[test]
177 fn macro_i32_test() {
178 let var_i32: i32 = -1234;
179
180 let payload = quo_create_payload(&var_i32, "var_i32", line!(), file!(), false);
181 assert_eq!(payload.meta.variable.name, "var_i32");
182 assert_eq!(payload.meta.variable.value, "-1234");
183 assert_eq!(payload.meta.variable.var_type, "&i32");
184 assert!(!payload.meta.variable.mutable);
185 assert!(!payload.meta.variable.is_constant);
186 }
187
188 #[test]
189 fn macro_u32_test() {
190 let var_u32: u32 = 1234;
191
192 let payload = quo_create_payload(&var_u32, "var_u32", line!(), file!(), false);
193 assert_eq!(payload.meta.variable.name, "var_u32");
194 assert_eq!(payload.meta.variable.value, "1234");
195 assert_eq!(payload.meta.variable.var_type, "&u32");
196 assert!(!payload.meta.variable.mutable);
197 assert!(!payload.meta.variable.is_constant);
198 }
199
200 #[test]
201 fn macro_string_test() {
202 let var_string: &str = "string";
203
204 let payload = quo_create_payload(&var_string, "var_string", line!(), file!(), false);
205 assert_eq!(payload.meta.variable.name, "var_string");
206 assert_eq!(payload.meta.variable.value, "\"string\"");
207 assert_eq!(payload.meta.variable.var_type, "&&str");
208 assert!(!payload.meta.variable.mutable);
209 assert!(!payload.meta.variable.is_constant);
210 }
211
212 #[test]
213 fn macro_bool_test() {
214 let var_bool: bool = true;
215
216 let payload = quo_create_payload(&var_bool, "var_bool", line!(), file!(), false);
217 assert_eq!(payload.meta.variable.name, "var_bool");
218 assert_eq!(payload.meta.variable.value, "true");
219 assert_eq!(payload.meta.variable.var_type, "&bool");
220 assert!(!payload.meta.variable.mutable);
221 assert!(!payload.meta.variable.is_constant);
222 }
223
224 #[test]
225 fn macro_tupl_test() {
226 let var_tuple: (bool, String, String, String, u32) = (
227 false,
228 String::from("hope"),
229 String::from("this"),
230 String::from("works"),
231 23423,
232 );
233
234 let payload = quo_create_payload(&var_tuple, "var_tuple", line!(), file!(), false);
235 assert_eq!(payload.meta.variable.name, "var_tuple");
236 assert_eq!(
237 payload.meta.variable.value,
238 "(false, \"hope\", \"this\", \"works\", 23423)"
239 );
240 assert_eq!(
241 payload.meta.variable.var_type,
242 "&(bool, alloc::string::String, alloc::string::String, alloc::string::String, u32)"
243 );
244 assert!(!payload.meta.variable.mutable);
245 assert!(!payload.meta.variable.is_constant);
246 }
247
248 #[test]
249 fn macro_arr_test() {
250 let var_array: [String; 3] = [
251 String::from("hope"),
252 String::from("this"),
253 String::from("works"),
254 ];
255
256 let payload = quo_create_payload(&var_array, "var_array", line!(), file!(), false);
257 assert_eq!(payload.meta.variable.name, "var_array");
258 assert_eq!(
259 payload.meta.variable.value,
260 "[\"hope\", \"this\", \"works\"]"
261 );
262 assert_eq!(
263 payload.meta.variable.var_type,
264 "&[alloc::string::String; 3]"
265 );
266 assert!(!payload.meta.variable.mutable);
267 assert!(!payload.meta.variable.is_constant);
268 }
269
270 #[test]
271 fn macro_vec_test() {
272 let var_vector: Vec<String> = vec![
273 String::from("hope"),
274 String::from("this"),
275 String::from("works"),
276 ];
277
278 let payload = quo_create_payload(&var_vector, "var_vector", line!(), file!(), false);
279 assert_eq!(payload.meta.variable.name, "var_vector");
280 assert_eq!(
281 payload.meta.variable.value,
282 "[\"hope\", \"this\", \"works\"]"
283 );
284 assert_eq!(
285 payload.meta.variable.var_type,
286 "&alloc::vec::Vec<alloc::string::String>"
287 );
288 assert!(!payload.meta.variable.mutable);
289 assert!(!payload.meta.variable.is_constant);
290 }
291
292 #[test]
293 fn macro_mut_test() {
294 let mut var_mut = 1;
295 let payload1 = quo_create_payload(&var_mut, "var_mut", line!(), file!(), true);
296 assert_eq!(payload1.meta.variable.name, "var_mut");
297 assert_eq!(payload1.meta.variable.value, "1");
298 assert_eq!(payload1.meta.variable.var_type, "&i32");
299 assert!(payload1.meta.variable.mutable);
300 assert!(!payload1.meta.variable.is_constant);
301
302 var_mut = 2;
303 let payload2 = quo_create_payload(&var_mut, "var_mut", line!(), file!(), true);
304 assert_eq!(payload2.meta.variable.name, "var_mut");
305 assert_eq!(payload2.meta.variable.value, "2");
306 assert_eq!(payload2.meta.variable.var_type, "&i32");
307 assert!(payload2.meta.variable.mutable);
308 assert!(!payload2.meta.variable.is_constant);
309 }
310
311 #[test]
312 fn macro_immut_test() {
313 let var_immut = 1;
314 let payload = quo_create_payload(&var_immut, "var_immut", line!(), file!(), false);
315 assert_eq!(payload.meta.variable.name, "var_immut");
316 assert_eq!(payload.meta.variable.value, "1");
317 assert_eq!(payload.meta.variable.var_type, "&i32");
318 assert!(!payload.meta.variable.mutable);
319 assert!(!payload.meta.variable.is_constant);
320 }
321
322 #[test]
323 #[allow(dead_code)]
324 fn complex_type_test() {
325 #[derive(Debug)]
326 struct Complex {
327 a: i32,
328 b: String,
329 c: Vec<i32>,
330 d: bool,
331 }
332
333 let var_complex = Complex {
334 a: 1,
335 b: String::from("complex"),
336 c: vec![1, 2, 3],
337 d: true,
338 };
339
340 let payload = quo_create_payload(&var_complex, "var_complex", line!(), file!(), false);
341 assert_eq!(payload.meta.variable.name, "var_complex");
342 assert_eq!(
343 payload.meta.variable.var_type,
344 "&quo_rust::tests::complex_type_test::Complex"
345 );
346 assert!(payload.meta.variable.value.contains("a: 1"));
347 assert!(payload.meta.variable.value.contains("complex"));
348 assert!(!payload.meta.variable.mutable);
349 assert!(!payload.meta.variable.is_constant);
350 }
351
352 #[test]
353 #[allow(dead_code)]
354 fn large_var_test() {
355 #[derive(Debug)]
356 struct Large {
357 a: i32,
358 b: i32,
359 c: i32,
360 d: i32,
361 e: i32,
362 f: i32,
363 g: i32,
364 h: i32,
365 i: i32,
366 j: i32,
367 }
368
369 let var_large = Large {
370 a: 1,
371 b: 2,
372 c: 3,
373 d: 4,
374 e: 5,
375 f: 6,
376 g: 7,
377 h: 8,
378 i: 9,
379 j: 10,
380 };
381
382 let payload = quo_create_payload(&var_large, "var_large", line!(), file!(), false);
383 assert_eq!(payload.meta.variable.name, "var_large");
384 assert_eq!(
385 payload.meta.variable.var_type,
386 "&quo_rust::tests::large_var_test::Large"
387 );
388 assert!(payload.meta.variable.value.contains("j: 10"));
389 assert!(!payload.meta.variable.mutable);
390 assert!(!payload.meta.variable.is_constant);
391 }
392
393 #[test]
394 fn macro_mut_explicit_test() {
395 let mut var_mut = 1;
396 quo!(mut var_mut);
397
398 let payload = quo_create_payload(&var_mut, "var_mut", line!(), file!(), true);
399 assert!(payload.meta.variable.mutable);
400
401 var_mut = 2;
402 quo!(var_mut);
403 }
404}