Skip to main content

quo_rust/
lib.rs

1mod info;
2pub mod macros;
3mod request;
4mod tests;
5mod types;
6
7use crate::info::hash::get_hash;
8use crate::info::runtime::get_runtime;
9use crate::info::stack_trace::get_stack_trace;
10use crate::info::system_usage::get_system_usage;
11use crate::info::thread::get_thread_id;
12use crate::info::time::get_time;
13use crate::request::make_request;
14use crate::types::{QuoContext, QuoPayload, QuoPayloadLanguage, QuoPayloadMeta, QuoPayloadVariable};
15pub use crate::types::QuoContext as __private_QuoContext;
16use std::fmt::Debug;
17use uuid::Uuid;
18
19/// This fn creates a QuoPayload. You might or might not question why this is a separate function: for testing.
20///
21/// # Example
22///
23/// let mut big_number: i128;
24///
25/// big_number = 170141183460469231731687303715884105727;
26///
27/// quo_create_payload(&big_number, "big_number", QuoContext { line: line!(), file: file!(), is_mutable: false, is_expression: false, package_name: "quo-rust", shared_grouping_hash: None });
28///
29#[cfg(debug_assertions)]
30#[doc(hidden)]
31fn quo_create_payload<T: Debug>(value: T, name: &str, ctx: QuoContext<'_>) -> QuoPayload {
32    let id = 0; // @TODO Pretty useless currently.
33    let var_type_raw = std::any::type_name_of_val(&value).to_string();
34    let var_type = var_type_raw
35        .strip_prefix('&')
36        .unwrap_or(&var_type_raw)
37        .to_string();
38
39    let value_str = format!("{:?}", value);
40
41    let uid: String = Uuid::new_v4().to_string();
42    let time_epoch_ms = get_time();
43    let memory_address = Some(format!("{:p}", &value as *const T));
44    let grouping_hash = ctx.shared_grouping_hash.or_else(|| get_hash(&var_type_raw, name, ctx.package_name));
45    let (stack_trace, caller_function) = get_stack_trace();
46    let thread_info = get_thread_id();
47    let (cpu_usage, memory_usage) = get_system_usage();
48    let runtime = get_runtime();
49
50    QuoPayload {
51        language: QuoPayloadLanguage::Rust,
52        meta: QuoPayloadMeta {
53            origin: ctx.package_name.to_string(),
54            sender_origin: format!("{}:{}", ctx.file, ctx.line),
55            variable: QuoPayloadVariable {
56                var_type: var_type.clone(),
57                name: name.to_string(),
58                value: value_str,
59                is_constant: name == name.to_uppercase(),
60                is_mutable: ctx.is_mutable || var_type_raw.contains("&mut "),
61                is_expression: ctx.is_expression,
62                memory_address,
63                grouping_hash,
64            },
65            id,
66            uid,
67            time_epoch_ms,
68            stack_trace,
69            thread_info,
70            runtime,
71            cpu_usage,
72            memory_usage,
73            caller_function,
74        },
75    }
76}
77
78/// This fn sends the provided variable to Quo.
79///
80/// # Example
81///
82/// let mut big_number: i128;
83///
84/// big_number = 170141183460469231731687303715884105727;
85///
86/// quo(&big_number, "big_number", QuoContext { line: line!(), file: file!(), is_mutable: false, is_expression: false, package_name: "quo-rust", shared_grouping_hash: None });
87///
88#[cfg(debug_assertions)]
89#[doc(hidden)]
90fn quo<T: Debug>(value: T, name: &str, ctx: QuoContext<'_>) {
91    #[cfg(debug_assertions)]
92    {
93        let env_host = option_env!("QUO_HOST").unwrap_or("http://127.0.0.1");
94        let env_port = option_env!("QUO_PORT").unwrap_or("7312");
95
96        let body = quo_create_payload(value, name, ctx);
97        let quo_server_address = format!("{}:{}/payload", env_host, env_port);
98
99        make_request(&quo_server_address, body);
100    }
101}
102
103/// Use the `quo!()` macro and not this fn directly.
104/// Returns a hash that is unique per call-site invocation: the nanosecond
105/// timestamp is mixed in so two separate `quo!(…)` calls — even with
106/// identical arguments — always produce different grouping hashes.
107#[cfg(debug_assertions)]
108#[doc(hidden)]
109pub fn __private_quo_grouping_hash(args_key: &str, package_name: &str) -> Option<String> {
110    let call_uid = Uuid::new_v4().to_string();
111    get_hash("grouped", &format!("{args_key}:{call_uid}"), package_name)
112}
113
114/// Use the `quo!()` macro and not this fn directly.
115#[cfg(debug_assertions)]
116#[doc(hidden)]
117pub fn __private_quo<T: Debug>(value: T, name: &str, ctx: QuoContext<'_>) {
118    quo(value, name, ctx)
119}