zero4rs 2.0.0

zero4rs is a powerful, pragmatic, and extremely fast web framework for Rust
Documentation
use lazy_static::lazy_static;

use crate::core::auth0::UserDetails;
use std::str::FromStr;

lazy_static! {
    static ref RE: regex::Regex = regex::Regex::new(r#"(\d+)\.(\d+)(e|E)([-]?)(\d+)"#).unwrap();
}

#[rustfmt::skip]
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct LocationPo {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub id: Option<i64>,
    #[serde(rename = "deviceId", skip_serializing_if = "Option::is_none")]
    pub device_id: Option<String>,
    #[serde(rename = "userId", skip_serializing_if = "Option::is_none")]
    pub user_id: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub latitude: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub longitude: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub accuracy: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub altitude: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub speed: Option<String>,
    #[serde(rename = "speedAccuracy", skip_serializing_if = "Option::is_none")]
    pub speed_accuracy: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub heading: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub time: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tag: Option<String>,
    // #[serde(skip_serializing_if = "Option::is_none")]
    // pub isMocked: Option<String>,
    // #[serde(skip_serializing_if = "Option::is_none")]
    // pub provider: Option<String>,
}

#[rustfmt::skip]
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct LocationRecord {
    pub device_id: Option<String>,
    pub location_id: Option<i64>,
    pub user_id: Option<String>,
    pub upload_user: Option<String>,
    pub latitude: Option<String>,
    pub longitude: Option<String>,
    pub accuracy: Option<String>,
    pub altitude: Option<String>,
    pub speed: Option<String>,
    pub speed_accuracy: Option<String>,
    pub heading: Option<String>,
    pub timestamp: Option<String>,
    pub tag: Option<String>,
}

impl LocationRecord {
    pub fn from(user: Option<&UserDetails>, data: &LocationPo) -> Self {
        Self {
            device_id: data.device_id.to_owned(),
            location_id: data.id.to_owned(),
            user_id: data.user_id.to_owned(),
            upload_user: user.map(|u| u.user_id()),
            latitude: Self::get_float_val(&data.latitude),
            longitude: Self::get_float_val(&data.longitude),
            accuracy: Self::get_float_val(&data.accuracy),
            altitude: Self::get_float_val(&data.altitude),
            heading: Self::get_float_val(&data.heading),
            speed: Self::get_float_val(&data.speed),
            speed_accuracy: Self::get_float_val(&data.speed_accuracy),
            timestamp: data.time.to_owned(),
            tag: data.tag.to_owned(),
        }
    }

    //                6.832898911393256e-14
    // 0.00000000000006 832898911393256
    fn get_float_val(val: &Option<String>) -> Option<String> {
        match val {
            Some(sci_str) => match bigdecimal::BigDecimal::from_str(sci_str) {
                Ok(d) => {
                    if let Some(captures) = RE.captures(sci_str) {
                        let n1 = captures.get(1).unwrap().as_str();
                        let n2 = captures.get(2).unwrap().as_str();
                        let _n3 = captures.get(3).unwrap().as_str();
                        let _n4 = captures.get(4).unwrap().as_str();
                        let n5 = captures.get(5).unwrap().as_str();

                        let n = crate::commons::string_to_number::<usize>(n5).unwrap();
                        let s = format!("0.{}{}{}", "0".repeat(n - 1), n1, n2);

                        Some(s)
                    } else {
                        Some(d.to_string())
                    }
                }
                Err(e) => {
                    log::error!("get_float_val-Failed: val={}, err={:?}", sci_str, e);
                    None
                }
            },
            None => None,
        }
    }
}