jfsm 0.1.5

A command-line tool to read file system metadata then return it in JSON format (output and errors).
Documentation
use clap::Parser;
use std::collections::HashMap;
use crate::request::{Request, Arg};
use std::time::{SystemTime, UNIX_EPOCH};

// Get the crate version from Cargo.toml at compile time
const VERSION: &str = env!("CARGO_PKG_VERSION");

#[derive(Parser)]
#[command(name = "jfsm")]
#[command(version, about = "A command-line tool to read file system metadata then return it in JSON format (output and errors).", long_about = None)]
pub struct Cli {
    #[arg(value_name = "FILEPATH")]
    pub filepath: String,
    
    /// Provides detailed information
    #[arg(short = 'a', long = "all", default_value_t = false)]
    pub all: bool,
    
    /// Adds path related metadata
    #[arg(short = 'd', long = "path", default_value_t = false)]
    pub path: bool,
    
    /// Adds permissions related metadata
    #[arg(short = 'p', long = "perms", default_value_t = false)]
    pub perms: bool,
    
    /// Adds time related metadata
    #[arg(short = 't', long = "time", default_value_t = false)]
    pub time: bool,
    
    /// Optional request ID
    #[arg(long = "id")]
    pub id: Option<String>,
}

impl Cli {
    /// Builds a Request object from CLI information
    pub fn build_request(&self) -> Request {
        // Get current timestamp in nanoseconds since epoch
        let now = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .expect("Time went backwards");
        let timestamp_ns = now.as_nanos() as u64;
        
        // Use provided ID or null if not provided
        let id_arg = match &self.id {
            Some(id) => Arg::from(id.clone()),
            None => Arg::from(()), // This creates a null value
        };
        
        // Build params from CLI arguments
        let mut params = HashMap::new();
        params.insert("filepath".to_string(), Arg::from(self.filepath.clone()));
        params.insert("all".to_string(), Arg::from(self.all));
        params.insert("path".to_string(), Arg::from(self.path));
        params.insert("perms".to_string(), Arg::from(self.perms));
        params.insert("time".to_string(), Arg::from(self.time));
        params.insert("id".to_string(), id_arg);
        
        Request {
            method: "jfsm".to_string(),  // Name of the executable
            params,
            ts: serde_json::Number::from(timestamp_ns),  // Timestamp in nanoseconds
            version: VERSION.to_string(),  // Crate version from Cargo.toml
        }
    }
}