From f337a1c56cbbb3cb05824be91f38d429ad154cea Mon Sep 17 00:00:00 2001 From: IGN-Styly Date: Thu, 14 Aug 2025 14:46:17 +0100 Subject: [PATCH 1/4] remove prototype trait --- enginelib/src/task.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/enginelib/src/task.rs b/enginelib/src/task.rs index 6099342..9e46522 100644 --- a/enginelib/src/task.rs +++ b/enginelib/src/task.rs @@ -76,13 +76,6 @@ pub enum Runner { CPU, } -pub trait TaskRegistry: Default + Clone { - fn register(&mut self, task: Arc, identifier: Identifier); - fn get(&self, mod_id: String, identifier: String) -> Option<&dyn Task>; - fn serialize(&self) -> Vec; - fn deserialize(bytes: &[u8]) -> Vec; -} - impl Clone for Box { fn clone(&self) -> Box { self.clone_box() From db94ac630d40bbc07e40c8d78753ceb4951af745 Mon Sep 17 00:00:00 2001 From: IGN-Styly Date: Thu, 14 Aug 2025 15:57:33 +0100 Subject: [PATCH 2/4] fix authentication issues --- Cargo.lock | 4 ++-- engine/proto/engine.proto | 1 + engine/src/bin/server.rs | 28 ++++++++++++++++++++++++---- enginelib/src/config.rs | 4 ++-- enginelib/src/events/start_event.rs | 3 +++ 5 files changed, 32 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9209f40..ef77b04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2902,9 +2902,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.104" +version = "2.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +checksum = "7bc3fcb250e53458e712715cf74285c1f889686520d79294a9ef3bd7aa1fc619" dependencies = [ "proc-macro2", "quote", diff --git a/engine/proto/engine.proto b/engine/proto/engine.proto index ac632ef..188c371 100644 --- a/engine/proto/engine.proto +++ b/engine/proto/engine.proto @@ -8,6 +8,7 @@ service Engine { rpc CreateTask(Task) returns (Task); rpc DeleteTask(TaskSelector) returns (empty); rpc GetTasks(TaskPageRequest) returns (TaskPage); + rpc CheckAuth(empty) returns (empty); } message TaskSelector { TaskState state = 1; diff --git a/engine/src/bin/server.rs b/engine/src/bin/server.rs index 4e2b6d2..d3f3277 100644 --- a/engine/src/bin/server.rs +++ b/engine/src/bin/server.rs @@ -33,14 +33,35 @@ struct EngineService { } #[tonic::async_trait] impl Engine for EngineService { + async fn check_auth( + &self, + request: tonic::Request, + ) -> Result, Status> { + let challenge = get_auth(&request); + let mut api = self.EngineAPI.write().await; + let db = api.db.clone(); + let output = Events::CheckAdminAuth(&mut api, challenge, ("".into(), "".into()), db); + if !output { + warn!("Auth check failed - permission denied"); + return Err(tonic::Status::permission_denied("Invalid Auth")); + }; + return Ok(tonic::Response::new(proto::Empty {})); + } async fn delete_task( &self, request: tonic::Request, ) -> Result, Status> { let mut api = self.EngineAPI.write().await; let data = request.get_ref(); + let challenge = get_auth(&request); + let db = api.db.clone(); let id = ID(&data.namespace, &data.task); + let output = Events::CheckAdminAuth(&mut api, challenge, ("".into(), "".into()), db); + if !output { + warn!("Auth check failed - permission denied"); + return Err(tonic::Status::permission_denied("Invalid Auth")); + }; // Generic helper for removing a task by id from a collection, using an id extractor closure fn delete_task_from_collection( collection: &mut HashMap<(String, String), Vec>, @@ -158,10 +179,9 @@ impl Engine for EngineService { ) -> std::result::Result, tonic::Status> { let mut api = self.EngineAPI.write().await; let challenge = get_auth(&request); - let uid = get_uid(&request); + let db = api.db.clone(); - if !Events::CheckAuth(&mut api, uid, challenge, db) { - //TODO: change to AdminSpecific Auth + if !Events::CheckAdminAuth(&mut api, challenge, ("".into(), "".into()), db) { info!("GetTask denied due to Invalid Auth"); return Err(Status::permission_denied("Invalid authentication")); }; @@ -581,7 +601,7 @@ async fn main() -> Result<(), Box> { EngineAPI::init(&mut api); Events::init_auth(&mut api); Events::StartEvent(&mut api); - let addr = api.cfg.config_toml.port.parse().unwrap(); + let addr = api.cfg.config_toml.host.parse().unwrap(); let apii = Arc::new(RwLock::new(api)); EngineAPI::init_chron(apii.clone()); let engine = EngineService { EngineAPI: apii }; diff --git a/enginelib/src/config.rs b/enginelib/src/config.rs index 239b9f8..4270184 100644 --- a/enginelib/src/config.rs +++ b/enginelib/src/config.rs @@ -6,14 +6,14 @@ use tracing::{error, instrument}; #[derive(Debug, Serialize, Deserialize, Clone)] pub struct ConfigTomlServer { pub cgrpc_token: Option, // Administrator Token, used to invoke cgrpc reqs. If not preset will default to no protection. - pub port: String, + pub host: String, pub clean_tasks: u64, pub pagination_limit: u32, } impl Default for ConfigTomlServer { fn default() -> Self { Self { - port: "[::1]:50051".into(), + host: "[::1]:50051".into(), cgrpc_token: None, clean_tasks: 60, pagination_limit: u32::MAX, diff --git a/enginelib/src/events/start_event.rs b/enginelib/src/events/start_event.rs index c4d0da5..18161a9 100644 --- a/enginelib/src/events/start_event.rs +++ b/enginelib/src/events/start_event.rs @@ -1,5 +1,7 @@ use std::{any::Any, process, sync::Arc}; +use tracing::info; + use crate::{ Identifier, api::EngineAPI, @@ -19,6 +21,7 @@ pub struct StartEvent { impl Events { pub fn StartEvent(api: &mut EngineAPI) { let lib_manager = api.lib_manager.clone(); + info!("Started on {}", api.cfg.config_toml.host); api.event_bus.handle( ID("core", "start_event"), &mut StartEvent { From 519ebbdf4626b91084bfc48a40ab2c6434957dea Mon Sep 17 00:00:00 2001 From: IGN-Styly Date: Sun, 30 Nov 2025 20:26:21 +0000 Subject: [PATCH 3/4] fix conflict --- engine/src/bin/packer.rs | 194 +++++++++++++++++++++++++++++---------- engine/src/bin/server.rs | 162 +++++++++++++++++++++----------- engine/src/lib.rs | 22 ++--- 3 files changed, 262 insertions(+), 116 deletions(-) diff --git a/engine/src/bin/packer.rs b/engine/src/bin/packer.rs index d3456bf..f28cee2 100644 --- a/engine/src/bin/packer.rs +++ b/engine/src/bin/packer.rs @@ -110,69 +110,167 @@ async fn main() { buf.push(unw); } let ns = buf.join("\n"); - let mut file = File::create("schema.rustforge.toml").unwrap(); - file.write_all(ns.as_bytes()).unwrap(); + match File::create("schema.rustforge.toml") { + Ok(mut file) => { + if let Err(e) = file.write_all(ns.as_bytes()) { + error!("Failed to write schema file: {}", e); + } else { + info!("Wrote schema.rustforge.toml"); + } + } + Err(e) => { + error!("Failed to create schema file: {}", e); + } + } } Commands::Unpack(input) => { if input.input.exists() { let mut final_out: Vec = Vec::new(); info!("Unpacking File: {}", input.input.to_string_lossy()); let mut buf = Vec::new(); - File::open(input.input) - .unwrap() - .read_to_end(&mut buf) - .unwrap(); - let k: TaskQueue = bincode::deserialize(&buf).unwrap(); - for tasks in k.tasks { - let tt = api.task_registry.tasks.get(&tasks.0.clone()).unwrap(); - for task in tasks.1 { - if tt.verify(task.bytes.clone()) { - let tmp_nt = tt.from_bytes(&task.bytes); - final_out.push(format![ - r#"[["{}:{}"]]"#, - tasks.0.0.clone(), - tasks.0.1.clone() - ]); - final_out.push(tmp_nt.to_toml()); - info!("{:?}", tmp_nt); - }; + match File::open(&input.input) { + Ok(mut f) => { + if let Err(e) = f.read_to_end(&mut buf) { + error!( + "Failed to read input file {}: {}", + input.input.display(), + e + ); + } else { + match bincode::deserialize::(&buf) { + Ok(k) => { + for tasks in k.tasks { + match api.task_registry.tasks.get(&tasks.0.clone()) { + Some(tt) => { + for task in tasks.1 { + if tt.verify(task.bytes.clone()) { + let tmp_nt = tt.from_bytes(&task.bytes); + final_out.push(format![ + r#"[["{}:{}"]]"#, + tasks.0.0.clone(), + tasks.0.1.clone() + ]); + final_out.push(tmp_nt.to_toml()); + info!("{:?}", tmp_nt); + } + } + } + None => { + error!( + "Unknown template for {}:{}", + tasks.0.0, tasks.0.1 + ); + } + } + } + } + Err(e) => { + error!("Failed to deserialize task queue: {}", e); + } + } + } + } + Err(e) => { + error!("Failed to open input file {}: {}", input.input.display(), e); } } let ns = final_out.join("\n"); - let mut file = File::create("output.rustforge.toml").unwrap(); - file.write_all(ns.as_bytes()).unwrap(); + match File::create("output.rustforge.toml") { + Ok(mut file) => { + if let Err(e) = file.write_all(ns.as_bytes()) { + error!("Failed to write output.rustforge.toml: {}", e); + } else { + info!("Wrote output.rustforge.toml"); + } + } + Err(e) => { + error!("Failed to create output.rustforge.toml: {}", e); + } + } } } Commands::Pack(input) => { if input.input.exists() { info!("Packing File: {}", input.input.to_string_lossy()); - let toml_str = std::fs::read_to_string(input.input).unwrap(); - let raw: RawDoc = toml::from_str(&toml_str).unwrap(); - let entries = parse_entries(raw); - for entry in entries { - let template = api - .task_registry - .get(&ID(entry.namespace.as_str(), entry.id.as_str())) - .unwrap(); - let toml_string = toml::to_string(&entry.data).unwrap(); - let t = template.from_toml(toml_string); - let mut tmp = api - .task_queue - .tasks - .get(&ID(entry.namespace.as_str(), entry.id.as_str())) - .unwrap() - .clone(); - tmp.push(StoredTask { - id: "".into(), //ids are minted on the server - bytes: t.to_bytes(), - }); - api.task_queue - .tasks - .insert(ID(entry.namespace.as_str(), entry.id.as_str()), tmp); + match std::fs::read_to_string(&input.input) { + Ok(toml_str) => { + match toml::from_str::(&toml_str) { + Ok(raw) => { + let entries = parse_entries(raw); + for entry in entries { + match api + .task_registry + .get(&ID(entry.namespace.as_str(), entry.id.as_str())) + { + Some(template) => { + match toml::to_string(&entry.data) { + Ok(toml_string) => { + let t = template.from_toml(toml_string); + let key = ID( + entry.namespace.as_str(), + entry.id.as_str(), + ); + let mut vec = api + .task_queue + .tasks + .get(&key) + .cloned() + .unwrap_or_default(); + vec.push(StoredTask { + id: "".into(), //ids are minted on the server + bytes: t.to_bytes(), + }); + api.task_queue.tasks.insert(key, vec); + } + Err(e) => { + error!( + "Failed to convert entry data to TOML string: {}", + e + ); + } + } + } + None => { + error!( + "Template not found for {}:{}", + entry.namespace, entry.id + ); + } + } + } + match bincode::serialize(&api.task_queue) { + Ok(data) => match File::create("output.rustforge.bin") { + Ok(mut file) => { + if let Err(e) = file.write_all(&data) { + error!( + "Failed to write output.rustforge.bin: {}", + e + ); + } else { + info!("Wrote output.rustforge.bin"); + } + } + Err(e) => { + error!( + "Failed to create output.rustforge.bin: {}", + e + ); + } + }, + Err(e) => { + error!("Failed to serialize task queue: {}", e); + } + } + } + Err(e) => { + error!("Failed to parse input TOML: {}", e); + } + } + } + Err(e) => { + error!("Failed to read input file {}: {}", input.input.display(), e); + } } - let data = bincode::serialize(&api.task_queue).unwrap(); - let mut file = File::create("output.rustforge.bin").unwrap(); - file.write_all(&data).unwrap(); } else { error!("File does not exist: {}", input.input.to_string_lossy()) } diff --git a/engine/src/bin/server.rs b/engine/src/bin/server.rs index d3f3277..eb350cb 100644 --- a/engine/src/bin/server.rs +++ b/engine/src/bin/server.rs @@ -17,6 +17,7 @@ use std::{ collections::HashMap, env::consts::OS, io::Read, + net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4}, sync::{Arc, RwLock as RS_RwLock}, }; use tokio::sync::RwLock; @@ -343,7 +344,13 @@ impl Engine for EngineService { out.clone(), ); let mut res = request.get_ref().clone(); - res.event_payload = out.read().unwrap().clone(); + res.event_payload = match out.read() { + Ok(g) => g.clone(), + Err(_) => { + warn!("CGRPC response lock poisoned, returning empty payload"); + Vec::new() + } + }; info!("CGRPC request processed successfully"); return Ok(tonic::Response::new(res)); } @@ -421,37 +428,52 @@ impl Engine for EngineService { ); return Err(Status::invalid_argument("Task Does not Exist")); } - let mut map = api - .task_queue - .tasks - .get(&ID(namespace, task_name)) - .unwrap() - .clone(); - let ttask = map.first().unwrap().clone(); + let key = ID(namespace, task_name); + let mut map = match api.task_queue.tasks.get(&key) { + Some(v) if !v.is_empty() => v.clone(), + _ => { + info!("No queued tasks for {}:{}", namespace, task_name); + return Err(Status::not_found("No queued tasks available")); + } + }; + let ttask = map.remove(0); let task_payload = ttask.bytes.clone(); - map.remove(0); // Get Task and remove it from queue - api.task_queue.tasks.insert(ID(namespace, task_name), map); - let store = bincode::serialize(&api.task_queue.clone()).unwrap(); - api.db.insert("tasks", store).unwrap(); + api.task_queue.tasks.insert(key.clone(), map); + match bincode::serialize(&api.task_queue.clone()) { + Ok(store) => { + if let Err(e) = api.db.insert("tasks", store) { + return Err(Status::internal(format!("DB insert error: {}", e))); + } + } + Err(e) => { + return Err(Status::internal(format!("Serialization error: {}", e))); + } + } // Move it to exec queue let mut exec_tsks = api .executing_tasks .tasks - .get(&ID(namespace, task_name)) - .unwrap() - .clone(); + .get(&key) + .cloned() + .unwrap_or_default(); exec_tsks.push(enginelib::task::StoredExecutingTask { bytes: task_payload.clone(), user_id: uid.clone(), given_at: Utc::now(), id: ttask.id.clone(), }); - api.executing_tasks - .tasks - .insert(ID(namespace, task_name), exec_tsks); - let store = bincode::serialize(&api.executing_tasks.clone()).unwrap(); - api.db.insert("executing_tasks", store).unwrap(); + api.executing_tasks.tasks.insert(key.clone(), exec_tsks); + match bincode::serialize(&api.executing_tasks.clone()) { + Ok(store) => { + if let Err(e) = api.db.insert("executing_tasks", store) { + return Err(Status::internal(format!("DB insert error: {}", e))); + } + } + Err(e) => { + return Err(Status::internal(format!("Serialization error: {}", e))); + } + } let response = proto::Task { id: ttask.id, task_id: input.task_id.clone(), @@ -492,21 +514,24 @@ impl Engine for EngineService { ); return Err(Status::invalid_argument("Task Does not Exist")); } + let key = ID(namespace, task_name); let mem_tsk = api .executing_tasks .tasks - .get(&ID(namespace, task_name)) - .unwrap() - .clone(); - let tsk = mem_tsk + .get(&key) + .cloned() + .unwrap_or_default(); + let tsk_opt = mem_tsk .iter() .find(|f| f.id == task_id.clone() && f.user_id == uid.clone()); - if let Some(tsk) = tsk { - let reg_tsk = api - .task_registry - .get(&ID(namespace, task_name)) - .unwrap() - .clone(); + if let Some(tsk) = tsk_opt { + let reg_tsk = match api.task_registry.get(&key) { + Some(r) => r.clone(), + None => { + warn!("Task registry missing for {}:{}", namespace, task_name); + return Err(Status::invalid_argument("Task Does not Exist")); + } + }; if !reg_tsk.verify(request.get_ref().task_payload.clone()) { info!("Failed to parse task"); return Err(Status::invalid_argument("Failed to parse given task bytes")); @@ -516,28 +541,37 @@ impl Engine for EngineService { nmem_tsk.retain(|f| f.id != task_id.clone() && f.user_id != uid.clone()); api.executing_tasks .tasks - .insert(ID(namespace, task_name), nmem_tsk.clone()); + .insert(key.clone(), nmem_tsk.clone()); let t_mem_execs = api.executing_tasks.clone(); - api.db - .insert("executing_tasks", bincode::serialize(&t_mem_execs).unwrap()) - .unwrap(); + match bincode::serialize(&t_mem_execs) { + Ok(store) => { + if let Err(e) = api.db.insert("executing_tasks", store) { + return Err(Status::internal(format!("DB insert error: {}", e))); + } + } + Err(e) => return Err(Status::internal(format!("Serialization error: {}", e))), + } // tsk-> solved Tsks let mut mem_solv = api .solved_tasks .tasks - .get(&ID(namespace, task_name)) - .unwrap() - .clone(); + .get(&key) + .cloned() + .unwrap_or_default(); mem_solv.push(enginelib::task::StoredTask { bytes: tsk.bytes.clone(), id: tsk.id.clone(), }); - api.solved_tasks - .tasks - .insert(ID(namespace, task_name), mem_solv); + api.solved_tasks.tasks.insert(key.clone(), mem_solv); // Solved tsks -> DB - let e_solv = bincode::serialize(&api.solved_tasks.tasks).unwrap(); - api.db.insert("solved_tasks", e_solv).unwrap(); + match bincode::serialize(&api.solved_tasks.tasks) { + Ok(e_solv) => { + if let Err(e) = api.db.insert("solved_tasks", e_solv) { + return Err(Status::internal(format!("DB insert error: {}", e))); + } + } + Err(e) => return Err(Status::internal(format!("Serialization error: {}", e))), + } info!("Task published successfully: {} by user: {}", task_id, uid); return Ok(tonic::Response::new(proto::Empty {})); } else { @@ -559,10 +593,13 @@ impl Engine for EngineService { }; let task = request.get_ref(); let task_id = task.task_id.clone(); - let id: Identifier = ( - task_id.split(":").collect::>()[0].to_string(), - task_id.split(":").collect::>()[1].to_string(), - ); + let parts: Vec<&str> = task_id.splitn(2, ':').collect(); + if parts.len() != 2 || parts[0].is_empty() || parts[1].is_empty() { + return Err(Status::invalid_argument( + "Invalid task ID format, expected 'namespace:task'", + )); + } + let id: Identifier = (parts[0].to_string(), parts[1].to_string()); let tsk_reg = api.task_registry.get(&id); if let Some(tsk_reg) = tsk_reg { if !tsk_reg.clone().verify(task.task_payload.clone()) { @@ -574,16 +611,18 @@ impl Engine for EngineService { id: druid::Druid::default().to_hex(), }; let mut mem_tsks = api.task_queue.clone(); - let mut mem_tsk = mem_tsks.tasks.get(&id).unwrap().clone(); + let mut mem_tsk = mem_tsks.tasks.get(&id).cloned().unwrap_or_default(); mem_tsk.push(tbp_tsk.clone()); mem_tsks.tasks.insert(id.clone(), mem_tsk); api.task_queue = mem_tsks; - api.db - .insert( - "tasks", - bincode::serialize(&api.task_queue.clone()).unwrap(), - ) - .unwrap(); + match bincode::serialize(&api.task_queue.clone()) { + Ok(store) => { + if let Err(e) = api.db.insert("tasks", store) { + return Err(Status::internal(format!("DB insert error: {}", e))); + } + } + Err(e) => return Err(Status::internal(format!("Serialization error: {}", e))), + } return Ok(tonic::Response::new(proto::Task { id: tbp_tsk.id.clone(), task_id: task_id.clone(), @@ -601,21 +640,32 @@ async fn main() -> Result<(), Box> { EngineAPI::init(&mut api); Events::init_auth(&mut api); Events::StartEvent(&mut api); - let addr = api.cfg.config_toml.host.parse().unwrap(); + let addr = api + .cfg + .config_toml + .host + .parse() + .unwrap_or(SocketAddr::V4(SocketAddrV4::new( + Ipv4Addr::new(127, 0, 0, 1), + 50051, + ))); let apii = Arc::new(RwLock::new(api)); EngineAPI::init_chron(apii.clone()); let engine = EngineService { EngineAPI: apii }; + // Build reflection service, mapping its concrete error into Box let reflection_service = tonic_reflection::server::Builder::configure() .register_encoded_file_descriptor_set(proto::FILE_DESCRIPTOR_SET) .build_v1() - .unwrap(); + .map_err(|e| Box::new(e) as Box)?; + // Start server and map transport errors into Box so `?` works with our return type. Server::builder() .add_service(reflection_service) .add_service(EngineServer::new(engine)) .serve(addr) - .await?; + .await + .map_err(|e| Box::new(e) as Box)?; Ok(()) } diff --git a/engine/src/lib.rs b/engine/src/lib.rs index 1b08618..5b529f0 100644 --- a/engine/src/lib.rs +++ b/engine/src/lib.rs @@ -1,19 +1,17 @@ use tonic::Request; pub fn get_uid(req: &Request) -> String { - let out = req.metadata().get("uid"); - if let Some(out) = out { - out.to_str().unwrap().to_string() - } else { - "".to_string() - } + req.metadata() + .get("uid") + .and_then(|v| v.to_str().ok()) + .map(|s| s.to_string()) + .unwrap_or_default() } pub fn get_auth(req: &Request) -> String { - let out = req.metadata().get("authorization"); - if let Some(out) = out { - out.to_str().unwrap().to_string() - } else { - "".to_string() - } + req.metadata() + .get("authorization") + .and_then(|v| v.to_str().ok()) + .map(|s| s.to_string()) + .unwrap_or_default() } From 4d6f50a04ba90b17748cb473e8908f813e903aaf Mon Sep 17 00:00:00 2001 From: IGN-Styly Date: Sun, 30 Nov 2025 20:47:02 +0000 Subject: [PATCH 4/4] fix conflict --- engine/src/bin/packer.rs | 99 +++++++++++++++++++++++----------------- 1 file changed, 57 insertions(+), 42 deletions(-) diff --git a/engine/src/bin/packer.rs b/engine/src/bin/packer.rs index f28cee2..8a41a3f 100644 --- a/engine/src/bin/packer.rs +++ b/engine/src/bin/packer.rs @@ -125,9 +125,11 @@ async fn main() { } Commands::Unpack(input) => { if input.input.exists() { - let mut final_out: Vec = Vec::new(); info!("Unpacking File: {}", input.input.to_string_lossy()); let mut buf = Vec::new(); + + // Attempt to open and read the input file. If either step fails, + // we do not proceed to deserialization or writing the output file. match File::open(&input.input) { Ok(mut f) => { if let Err(e) = f.read_to_end(&mut buf) { @@ -136,56 +138,69 @@ async fn main() { input.input.display(), e ); - } else { - match bincode::deserialize::(&buf) { - Ok(k) => { - for tasks in k.tasks { - match api.task_registry.tasks.get(&tasks.0.clone()) { - Some(tt) => { - for task in tasks.1 { - if tt.verify(task.bytes.clone()) { - let tmp_nt = tt.from_bytes(&task.bytes); - final_out.push(format![ - r#"[["{}:{}"]]"#, - tasks.0.0.clone(), - tasks.0.1.clone() - ]); - final_out.push(tmp_nt.to_toml()); - info!("{:?}", tmp_nt); - } - } - } - None => { - error!( - "Unknown template for {}:{}", - tasks.0.0, tasks.0.1 - ); - } - } - } - } - Err(e) => { - error!("Failed to deserialize task queue: {}", e); - } - } + // reading failed -> do not proceed to deserialize or write + return; } } Err(e) => { error!("Failed to open input file {}: {}", input.input.display(), e); + // opening failed -> do not proceed to deserialize or write + return; } } - let ns = final_out.join("\n"); - match File::create("output.rustforge.toml") { - Ok(mut file) => { - if let Err(e) = file.write_all(ns.as_bytes()) { - error!("Failed to write output.rustforge.toml: {}", e); - } else { - info!("Wrote output.rustforge.toml"); + + // Try to deserialize. Only on successful deserialization do we + // process entries and write the output TOML file. + let maybe_queue: Option = + match bincode::deserialize::(&buf) { + Ok(k) => Some(k), + Err(e) => { + error!("Failed to deserialize task queue: {}", e); + None + } + }; + + if let Some(k) = maybe_queue { + let mut final_out: Vec = Vec::new(); + + for tasks in k.tasks { + match api.task_registry.tasks.get(&tasks.0.clone()) { + Some(tt) => { + for task in tasks.1 { + if tt.verify(task.bytes.clone()) { + let tmp_nt = tt.from_bytes(&task.bytes); + final_out.push(format![ + r#"[["{}:{}"]]"#, + tasks.0.0.clone(), + tasks.0.1.clone() + ]); + final_out.push(tmp_nt.to_toml()); + info!("{:?}", tmp_nt); + } + } + } + None => { + error!("Unknown template for {}:{}", tasks.0.0, tasks.0.1); + } } } - Err(e) => { - error!("Failed to create output.rustforge.toml: {}", e); + + let ns = final_out.join("\n"); + match File::create("output.rustforge.toml") { + Ok(mut file) => { + if let Err(e) = file.write_all(ns.as_bytes()) { + error!("Failed to write output.rustforge.toml: {}", e); + } else { + info!("Wrote output.rustforge.toml"); + } + } + Err(e) => { + error!("Failed to create output.rustforge.toml: {}", e); + } } + } else { + // Deserialization failed; we logged the error above and intentionally do not + // create/write the output file to avoid producing an empty output. } } }