diff --git a/src/error.rs b/src/error.rs index af3d32c..d0e05c9 100644 --- a/src/error.rs +++ b/src/error.rs @@ -15,18 +15,12 @@ pub enum Error { #[error("json: {0}")] Json(#[from] serde_json::Error), + #[error("bad pipe specification: a pipe must have exactly one reader and one writer: {0}")] + BadPipe(String), + #[error("bad specification type: only .json files are supported")] BadSpecType, - #[error("bad pipe trigger: this entrypoint is not triggered by a pipe")] - BadPipeTrigger, - - #[error("too many pipes: a pipe must have one reader and one writer: {0}")] - TooManyPipes(String), - - #[error("read only pipe: a pipe must have one reader and one writer: {0}")] - ReadOnlyPipe(String), - - #[error("write only pipe: a pipe must have one reader and one writer: {0}")] - WriteOnlyPipe(String), + #[error("bad trigger argument: this entrypoint is not triggered by something with arguments")] + BadTriggerArgument, } diff --git a/src/lib.rs b/src/lib.rs index 9317130..fc622f2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -79,45 +79,47 @@ pub fn run() -> Result<()> { .spawn() } +fn create_pipes(names: Vec<&str>) -> Result> { + let mut pipes = HashMap::new(); + for pipe in names { + info!("creating pipe pair `{}`", pipe); + pipes.insert(pipe.to_string(), PipePair::new(pipe)?); + } + + Ok(pipes) +} + pub struct PipePair { + name: String, + read: Option, write: Option, } impl PipePair { - fn take_read(&mut self) -> File { - self.read - .take() - .expect("read pipes should only be used once") - } - - fn take_write(&mut self) -> File { - self.write - .take() - .expect("write pipes should only be used once") - } -} - -fn create_pipes(names: Vec<&str>) -> Result> { - let mut pipes = HashMap::new(); - - for pipe in names { - info!("creating pipe pair `{}`", pipe); - + fn new(name: &str) -> Result { let (read, write) = unistd::pipe2(OFlag::O_DIRECT).map_err(|e| Error::Nix { msg: "pipe2", src: e, })?; // safe to create files given the successful return of pipe(2) - pipes.insert( - pipe.to_string(), - PipePair { - read: Some(unsafe { File::from_raw_fd(read) }), - write: Some(unsafe { File::from_raw_fd(write) }), - }, - ); + Ok(PipePair { + name: name.to_string(), + read: Some(unsafe { File::from_raw_fd(read) }), + write: Some(unsafe { File::from_raw_fd(write) }), + }) } - Ok(pipes) + fn take_read(&mut self) -> Result { + self.read + .take() + .ok_or_else(|| Error::BadPipe(self.name.to_string())) + } + + fn take_write(&mut self) -> Result { + self.write + .take() + .ok_or_else(|| Error::BadPipe(self.name.to_string())) + } } diff --git a/src/spawner.rs b/src/spawner.rs index 9359536..5e0212b 100644 --- a/src/spawner.rs +++ b/src/spawner.rs @@ -55,7 +55,7 @@ impl<'a> Spawner<'a> { } Trigger::Pipe(s) => { - let pipe = self.pipes.get_mut(s).unwrap().take_read(); + let pipe = self.pipes.get_mut(s).unwrap().take_read().unwrap(); let binary = PathBuf::from(self.binary).canonicalize()?; let mut builder = VoidBuilder::new(); @@ -126,11 +126,11 @@ impl<'a> Spawner<'a> { Arg::Pipe(p) => out.push(match p { Pipe::Rx(s) => { - let pipe = self.pipes.get_mut(s).unwrap().take_read(); + let pipe = self.pipes.get_mut(s).unwrap().take_read().unwrap(); CString::new(pipe.as_raw_fd().to_string()).unwrap() } Pipe::Tx(s) => { - let pipe = self.pipes.get_mut(s).unwrap().take_write(); + let pipe = self.pipes.get_mut(s).unwrap().take_write().unwrap(); CString::new(pipe.as_raw_fd().to_string()).unwrap() } }), diff --git a/src/specification.rs b/src/specification.rs index e864335..ae9f95f 100644 --- a/src/specification.rs +++ b/src/specification.rs @@ -122,25 +122,25 @@ impl Specification { for pipe in read { if !read_set.insert(pipe) { - return Err(Error::TooManyPipes(pipe.to_string())); + return Err(Error::BadPipe(pipe.to_string())); } } let mut write_set = HashSet::with_capacity(write.len()); for pipe in write { if !write_set.insert(pipe) { - return Err(Error::TooManyPipes(pipe.to_string())); + return Err(Error::BadPipe(pipe.to_string())); } } for pipe in read_set { if !write_set.remove(pipe) { - return Err(Error::ReadOnlyPipe(pipe.to_string())); + return Err(Error::BadPipe(pipe.to_string())); } } if let Some(pipe) = write_set.into_iter().next() { - return Err(Error::WriteOnlyPipe(pipe.to_string())); + return Err(Error::BadPipe(pipe.to_string())); } // validate pipe trigger arguments make sense @@ -148,7 +148,7 @@ impl Specification { if entrypoint.args.contains(&Arg::PipeTrigger) { match entrypoint.trigger { Trigger::Pipe(_) => {} - _ => return Err(Error::BadPipeTrigger), + _ => return Err(Error::BadTriggerArgument), } } }