endpoint_libs/libs/
utils.rs

1use std::fmt::Write;
2
3use convert_case::{Case, Casing};
4use eyre::{ContextCompat, Result};
5use serde::Serialize;
6
7use crate::model::EndpointSchema;
8
9pub fn get_log_id() -> u64 {
10    chrono::Utc::now().timestamp_micros() as _
11}
12
13pub fn get_conn_id() -> u32 {
14    chrono::Utc::now().timestamp_micros() as _
15}
16
17pub fn encode_header<T: Serialize>(v: T, schema: EndpointSchema) -> Result<String> {
18    let mut s = String::new();
19    write!(s, "0{}", schema.name.to_ascii_lowercase())?;
20    let v = serde_json::to_value(&v)?;
21
22    for (i, f) in schema.parameters.iter().enumerate() {
23        let key = f.name.to_case(Case::Camel);
24        let value = v.get(&key).with_context(|| format!("key: {}", key))?;
25        if value.is_null() {
26            continue;
27        }
28        write!(
29            s,
30            ", {}{}",
31            i + 1,
32            urlencoding::encode(&value.to_string().replace('\"', ""))
33        )?;
34    }
35    Ok(s)
36}
37
38pub fn get_time_milliseconds() -> i64 {
39    chrono::Utc::now().timestamp_millis()
40}
41pub fn get_time_micros() -> i64 {
42    chrono::Utc::now().timestamp_micros()
43}
44pub fn hex_decode(s: &[u8]) -> Result<Vec<u8>> {
45    if s.starts_with(b"0x") {
46        Ok(hex::decode(&s[2..])?)
47    } else {
48        Ok(hex::decode(s)?)
49    }
50}
51
52/// format decimal by specific significant figures
53pub fn decimal_sf(num: rust_decimal::Decimal, sig_figs: usize) -> rust_decimal::Decimal {
54    num.round_sf(sig_figs as _).unwrap()
55}
56
57/// Aligns the precision of one `f64` value to match another `f64` value.
58///
59/// # Examples
60///
61/// ```
62/// let a = 123.456789;
63/// let b = 78.9;
64/// let aligned_a = lib::utils::align_precision(a, b);
65/// assert_eq!(aligned_a, 123.5);
66/// ```
67/// ```
68/// let a = 2.37;
69/// let b = 631.3;
70/// let aligned_a = lib::utils::align_precision(a, b);
71/// assert_eq!(aligned_a, 2.4);
72/// ```
73pub fn align_precision(a: f64, b: f64) -> f64 {
74    let precision_b = count_dp(b);
75    let precision_a = format!("{:.0$}", { precision_b });
76    let aligned_a = format!("{:.*}", precision_a.parse::<usize>().unwrap(), a);
77    aligned_a.parse().unwrap()
78}
79
80/// ```
81/// assert_eq!(lib::utils::count_dp(1.5), 1);
82/// ```
83/// ```
84/// assert_eq!(lib::utils::count_dp(1.1), 1);
85/// ```
86pub fn count_dp(num: f64) -> usize {
87    // Convert the f64 to a string representation
88    let num_str = format!("{}", num);
89
90    // Find the position of the decimal point
91    if let Some(decimal_index) = num_str.find('.') {
92        // Count the number of characters after the decimal point
93        num_str.len() - decimal_index - 1
94    } else {
95        // If there is no decimal point, return 0
96        0
97    }
98}