libfetch 0.1.0

Simple but reliable library for fetch tools
Documentation
use std::env::var;
use crate::{platform::Platform, utils, shared::{self, procfs::Memory}};
extern crate sysctl;
use sysctl::{Sysctl,CtlValue};

pub struct FreeBSD;

#[derive(Debug)]
#[repr(C)]
struct Boottime {
    sec: libc::c_int,
}

impl Platform for FreeBSD {
    fn new() -> Self {
        FreeBSD
    }
    
    fn name(&self) -> Option<String> {
        shared::os_release().or(Some("FreeBSD".to_string()))
    }

    fn user(&self) -> Option<String> {
        shared::libc_user()
    }

    fn kernel(&self) -> Option<String> {
        shared::libc_kernel()
    }

    fn hostname(&self) -> Option<String> {
        shared::libc_hostname()
    }

    fn desktop(&self) -> Option<String> {
        var("XDG_CURRENT_DESKTOP").ok()
    }

    fn shell(&self) -> Option<String> {
        var("SHELL").ok()
    }

    fn uptime(&self) -> Option<usize> {
        let result = sysctl::Ctl::new("kern.boottime").ok()?;
        let val_enum = result.value().ok()?;

        if let sysctl::CtlValue::Struct(val) = val_enum {
            let val_ptr: *const u8 = val.as_ptr();
            let struct_ptr: *const Boottime = val_ptr as *const Boottime;
            let struct_ref: &Boottime = unsafe { &*struct_ptr };

            let now = utils::get_now()?;
            let uptime = now - struct_ref.sec as u64;
            let uptime: usize = uptime.try_into().ok()?;

            return Some(uptime);
        }

        None
    }

    fn memory(&self) -> Option<Memory> {
        let pagesize = sysctl::Ctl::new("hw.pagesize").ok()?
            .value().ok()?;
        let pagesize = get_int_value(pagesize)?;


        let mem_inactive = sysctl::Ctl::new("vm.stats.vm.v_inactive_count").ok()?
            .value().ok()?;
        let mem_inactive = get_int_value(mem_inactive)?;


        let mem_unused = sysctl::Ctl::new("vm.stats.vm.v_free_count").ok()?
            .value().ok()?;
        let mem_unused = get_int_value(mem_unused)?;
 

        let mem_cache = sysctl::Ctl::new("vm.stats.vm.v_cache_count").ok()?
            .value().ok()?;
        let mem_cache = get_int_value(mem_cache)?;


        let mem_total = sysctl::Ctl::new("hw.physmem").ok()?
            .value().ok()?;
        let mem_total = get_int_value(mem_total)? / 1024;

        let mem_free = (mem_inactive + mem_unused + mem_cache) * pagesize / 1024;

        let memory = Memory::new(mem_total - mem_free, mem_total);

        Some(memory)
    }
}

fn get_int_value(enum_value: CtlValue) -> Option<usize> {
    match enum_value {
        CtlValue::Int(i) => {
            let as_usize: usize = i.try_into().ok()?;
            return Some(as_usize);
        }
        CtlValue::U32(i) => {
            let as_usize: usize = i.try_into().ok()?;
            return Some(as_usize);
        }
        CtlValue::Uint(i) => {
            let as_usize: usize = i.try_into().ok()?;
            return Some(as_usize);
        }
        CtlValue::Ulong(i) => {
            let as_usize: usize = i.try_into().ok()?;
            return Some(as_usize);
        }
        _ => {
            return None;
        }
    };
}