self_sdk 0.1.0

An SDK for interacting with the self network
Documentation
    use std::sync::atomic::{AtomicPtr, Ordering};

    use chrono::prelude::*;
    
    static mut NTP_OFFSET: AtomicPtr<chrono::Duration> = AtomicPtr::new(std::ptr::null_mut());
    static mut LAST_CHECK: AtomicPtr<DateTime<Utc>> = AtomicPtr::new(std::ptr::null_mut());
    
    pub fn rfc3339() -> String {
        return now().to_rfc3339();
    }
    
    pub fn unix() -> i64 {
        return now().timestamp();
    }
    
    pub fn now() -> DateTime<Utc> {
        let ts = Utc::now();
    
        unsafe {
            let last_check = LAST_CHECK.load(Ordering::SeqCst);
    
            if last_check == std::ptr::null_mut() || (*last_check).time() < ts.time() {
                if update_last_checked(last_check, ts) {
                    update_ntp_offset();
                }
            }
        }
    
        let offset = ntp_offset();
    
        return ts + offset;
    }
    
    fn update_ntp_offset() {
        loop {
            let stime = chrono::Utc::now();
    
            match ntp::request("time.google.com:123") {
                Ok(response) => {
                    // calculate the ntp offset
                    let dtime = chrono::Utc::now() - stime;
                    let rtime = chrono::Duration::seconds(response.recv_time.sec as i64)
                        + chrono::Duration::nanoseconds(response.recv_time.frac as i64);
                    let otime = chrono::Duration::seconds(response.orig_time.sec as i64)
                        + chrono::Duration::nanoseconds(response.orig_time.frac as i64);
    
                    let offset = ((rtime - otime) + dtime) / 2;
    
                    unsafe {
                        NTP_OFFSET.store(Box::into_raw(Box::new(offset)), Ordering::SeqCst);
                    }
    
                    return;
                }
                Err(err) => {
                    println!("ntp lookup failed with: {}", err);
                    std::thread::sleep(std::time::Duration::from_secs(10));
                }
            };
        }
    }
    
    fn ntp_offset() -> chrono::Duration {
        unsafe {
            loop {
                let offset = NTP_OFFSET.load(Ordering::SeqCst);
                if offset != std::ptr::null_mut() {
                    return *offset;
                }
    
                std::thread::sleep(std::time::Duration::from_millis(1));
            }
        }
    }
    
    fn update_last_checked(checked: *mut DateTime<Utc>, current_timestamp: DateTime<Utc>) -> bool {
        unsafe {
            return match LAST_CHECK.compare_exchange(
                checked,
                Box::into_raw(Box::new(current_timestamp)),
                Ordering::SeqCst,
                Ordering::SeqCst,
            ) {
                Ok(_) => true,
                Err(_) => false,
            };
        }
    }
    
    #[cfg(test)]
    mod tests {
        use super::*;
    
        #[test]
        fn get_rfc3339() {
            rfc3339();
            //println!("utc: {} - rfc: {}", chrono::Utc::now(), rfc3339());
        }
    }