From 01e3de22a53d30f21a829bf5d7cebc45c4d61ea8 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 24 Jan 2021 00:12:26 +0100 Subject: Initial task queue --- .gitignore | 1 + Cargo.lock | 5 ++++ Cargo.toml | 9 ++++++ rustfmt.toml | 1 + src/main.rs | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 113 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 rustfmt.toml create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..e64fc04 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "rebel" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..7712670 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "rebel" +version = "0.1.0" +authors = ["Matthias Schiffer "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..218e203 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1 @@ +hard_tabs = true diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..98d1b8d --- /dev/null +++ b/src/main.rs @@ -0,0 +1,97 @@ +use std::collections::{HashMap, HashSet}; +// use std::io::{self, Write}; +use std::io; +// use std::process::Command; + +struct Task { + // action: String, + deps: Vec, +} + +// impl Task { +// fn run(&self) -> io::Result<()> { +// let output = Command::new("sh").arg("-c").arg(&self.action).output()?; + +// let stdout = io::stdout(); +// let mut handle = stdout.lock(); +// handle.write_all(&output.stdout)?; + +// Ok(()) +// } +// } + +fn collect_subtasks<'a>( + queued: &HashSet<&'a str>, + tasks: &'a HashMap, + id: &str, +) -> io::Result> { + let (task_id, task) = match tasks.get_key_value(id) { + Some(t) => t, + None => { + return Err(io::Error::new(io::ErrorKind::NotFound, "Task not found")); + } + }; + + if queued.contains(id) { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + "Dependency cycle", + )); + } + + let mut queued_sub = queued.clone(); + queued_sub.insert(task_id); + + let mut subtasks: HashSet<&'a str> = HashSet::new(); + subtasks.insert(task_id); + + for dep in &task.deps { + let deptasks = collect_subtasks(&queued_sub, tasks, dep)?; + subtasks = subtasks.union(&deptasks).copied().collect(); + } + + Ok(subtasks) +} + +fn collect_tasks<'a>(tasks: &'a HashMap, id: &str) -> io::Result> { + collect_subtasks(&HashSet::new(), tasks, id) +} + +fn main() -> io::Result<()> { + let mut tasks = HashMap::new(); + tasks.insert( + String::from("ls"), + Task { + // action: String::from("ls"), + deps: vec!["foo".to_owned(), "bar".to_owned()], + }, + ); + tasks.insert( + String::from("foo"), + Task { + // action: String::from("echo foo"), + deps: vec!["bar".to_owned()], + }, + ); + tasks.insert( + String::from("bar"), + Task { + // action: String::from("echo bar"), + deps: vec![], + }, + ); + + let queue = collect_tasks(&tasks, "ls")?; + let (runnable, queued) = queue + .into_iter() + .partition::, _>(|id| tasks.get(*id).unwrap().deps.is_empty()); + + for t in &runnable { + println!("Runnable: {}", t); + } + for t in &queued { + println!("Queued: {}", t); + } + + Ok(()) +} -- cgit v1.2.3