use icepick_module::{ help::{Argument, ArgumentType}, Module, }; use serde::{Deserialize, Serialize}; use std::path::{Path, PathBuf}; fn path_for_filename(filename: &Path) -> PathBuf { PathBuf::from( std::env::vars() .find(|(k, _)| k == "ICEPICK_DATA_DIRECTORY") .map(|(_, v)| v) .as_deref() .unwrap_or("/media/external"), ) .join(filename) } #[derive(Serialize, Deserialize, Debug)] #[serde(tag = "operation", content = "values", rename_all = "kebab-case")] pub enum Request { LoadFile { filename: PathBuf, }, SaveFile { filename: PathBuf, #[serde(flatten)] values: serde_json::Value, }, } #[derive(thiserror::Error, Debug)] pub enum Error {} pub struct Internal; impl Module for Internal { type Error = Error; type Request = Request; fn describe_operations() -> Vec { let filename = Argument { name: "filename".to_string(), description: "The file to load or save data to.".to_string(), r#type: ArgumentType::Required, }; vec![ icepick_module::help::Operation { name: "load-file".to_string(), description: "Load data from a JSON file.".to_string(), arguments: vec![filename.clone()], }, icepick_module::help::Operation { name: "save-file".to_string(), description: "Save data from a JSON file.".to_string(), arguments: vec![filename.clone()], }, ] } fn handle_request(request: Self::Request) -> Result { match request { Request::LoadFile { filename } => { let path = path_for_filename(&filename); let mut attempt = 0; while !std::fs::exists(&path).is_ok_and(|v| v) { if attempt % 10 == 0 { eprintln!( "Waiting for {path} to be populated...", path = path.to_string_lossy() ); } attempt += 1; std::thread::sleep(std::time::Duration::from_secs(1)); } // if we ran at least once, we should have previously printed a message. write a // confirmation that we are no longer waiting. if we haven't, we've never printed // a message, therefore we don't need to confirm the prior reading. if attempt > 0 { eprintln!("File contents loaded."); } let file = std::fs::File::open(path).unwrap(); let json: serde_json::Value = serde_json::from_reader(file).unwrap(); Ok(serde_json::json!({ "blob": json, })) } Request::SaveFile { filename, values } => { let path = path_for_filename(&filename); let file = std::fs::File::create(path).unwrap(); serde_json::to_writer(file, &values).unwrap(); Ok(serde_json::json!({ "blob": {}, })) } } } }