From 1363bfea3e74ccd549b58a7593c8b408d3c94fc2 Mon Sep 17 00:00:00 2001
From: stratact <stratact1@gmail.com>
Date: Tue, 29 May 2018 14:21:31 -0700
Subject: [PATCH] Use slices instead of iterators for PipelineExecution without
 needing to allocate a Vec as done before the iterator migration

---
 src/lib/builtins/mod.rs        |  2 +-
 src/lib/shell/binary/prompt.rs |  2 +-
 src/lib/shell/flow_control.rs  |  9 ++----
 src/lib/shell/fork_function.rs |  9 ++----
 src/lib/shell/job.rs           |  4 +--
 src/lib/shell/mod.rs           |  9 ++----
 src/lib/shell/pipe_exec/mod.rs | 54 +++++++++++++---------------------
 7 files changed, 31 insertions(+), 58 deletions(-)

diff --git a/src/lib/builtins/mod.rs b/src/lib/builtins/mod.rs
index 216f4add..e383294d 100644
--- a/src/lib/builtins/mod.rs
+++ b/src/lib/builtins/mod.rs
@@ -165,7 +165,7 @@ pub fn builtin_cd(args: &[&str], shell: &mut Shell) -> i32 {
                         shell.set_var("OLDPWD", pwd);
                         shell.set_var("PWD", current_dir);
                     }
-                    fork_function(shell, "CD_CHANGE", &mut ["ion"].iter());
+                    fork_function(shell, "CD_CHANGE", &["ion"]);
                 }
                 Err(_) => env::set_var("PWD", "?"),
             };
diff --git a/src/lib/shell/binary/prompt.rs b/src/lib/shell/binary/prompt.rs
index 6f456098..3f7288e7 100644
--- a/src/lib/shell/binary/prompt.rs
+++ b/src/lib/shell/binary/prompt.rs
@@ -20,7 +20,7 @@ pub(crate) fn prompt_fn(shell: &mut Shell) -> Option<String> {
     let mut output = None;
 
     match shell.fork(Capture::StdoutThenIgnoreStderr, |child| unsafe {
-        let _ = function.read().execute(child, &mut ["ion"].iter());
+        let _ = function.read().execute(child, &["ion"]);
     }) {
         Ok(result) => {
             let mut string = String::with_capacity(1024);
diff --git a/src/lib/shell/flow_control.rs b/src/lib/shell/flow_control.rs
index bc5aaa8a..1bb37795 100644
--- a/src/lib/shell/flow_control.rs
+++ b/src/lib/shell/flow_control.rs
@@ -2,7 +2,6 @@ use super::{flow::FlowLogic, Shell};
 use fnv::*;
 use parser::{assignments::*, pipelines::Pipeline};
 use std::fmt::{self, Display, Formatter};
-use std::iter::ExactSizeIterator;
 use types::{Identifier, *};
 
 #[derive(Debug, PartialEq, Clone)]
@@ -168,11 +167,7 @@ impl Display for FunctionError {
 }
 
 impl Function {
-    pub(crate) fn execute<'a, I>(self, shell: &mut Shell, args: &mut I) -> Result<(), FunctionError>
-        where
-            I: ExactSizeIterator,
-            <I as Iterator>::Item: AsRef<str>,
-    {
+    pub(crate) fn execute<S: AsRef<str>>(self, shell: &mut Shell, args: &[S]) -> Result<(), FunctionError> {
         if args.len() - 1 != self.args.len() {
             return Err(FunctionError::InvalidArgumentCount);
         }
@@ -183,7 +178,7 @@ impl Function {
         let mut arrays_backup: FnvHashMap<&str, Option<Array>> =
             FnvHashMap::with_capacity_and_hasher(64, Default::default());
 
-        for (type_, value) in self.args.iter().zip(args.skip(1)) {
+        for (type_, value) in self.args.iter().zip(args.iter().skip(1)) {
             let value = match value_check(shell, value.as_ref(), type_.kind) {
                 Ok(value) => value,
                 Err(_) => {
diff --git a/src/lib/shell/fork_function.rs b/src/lib/shell/fork_function.rs
index 05321f6a..eac3684c 100644
--- a/src/lib/shell/fork_function.rs
+++ b/src/lib/shell/fork_function.rs
@@ -1,19 +1,14 @@
 use super::{Capture, Function, Shell};
-use std::iter::ExactSizeIterator;
 use std::process;
 use sys;
 
 pub(crate) fn command_not_found(shell: &mut Shell, command: &str) -> bool {
-    fork_function(shell, "COMMAND_NOT_FOUND", &mut ["ion", &command].iter())
+    fork_function(shell, "COMMAND_NOT_FOUND", &["ion", command])
 }
 
 /// High-level function for executing a function programmatically.
 /// NOTE: Always add "ion" as a first argument in `args`.
-pub fn fork_function<I>(shell: &mut Shell, fn_name: &str, args: &mut I) -> bool
-where
-    I: ExactSizeIterator,
-    <I as Iterator>::Item: AsRef<str>,
-{
+pub fn fork_function<S: AsRef<str>>(shell: &mut Shell, fn_name: &str, args: &[S]) -> bool {
     let function = match shell.functions.get(fn_name) {
         Some(func) => func as *const Function,
         None => return false,
diff --git a/src/lib/shell/job.rs b/src/lib/shell/job.rs
index 4287890f..fc482c8e 100644
--- a/src/lib/shell/job.rs
+++ b/src/lib/shell/job.rs
@@ -233,7 +233,7 @@ impl RefinedJob {
                 ref stdout,
                 ref stderr,
             } => {
-                shell.exec_external(&name, args[1..].iter().map(|s| s.as_ref()), stdin, stdout, stderr)
+                shell.exec_external(&name, &args[1..], stdin, stdout, stderr)
             }
             RefinedJob::Builtin {
                 main,
@@ -252,7 +252,7 @@ impl RefinedJob {
                 ref stdout,
                 ref stderr,
             } => {
-                shell.exec_function(name, &mut args.iter(), stdout, stderr, stdin)
+                shell.exec_function(name, args, stdout, stderr, stdin)
             }
             _ => panic!("exec job should not be able to be called on Cat or Tee jobs"),
         }
diff --git a/src/lib/shell/mod.rs b/src/lib/shell/mod.rs
index 7187ca99..97c845ed 100644
--- a/src/lib/shell/mod.rs
+++ b/src/lib/shell/mod.rs
@@ -172,11 +172,7 @@ impl<'a> Shell {
 
     /// A method for executing a function with the given `name`, using `args` as the input.
     /// If the function does not exist, an `IonError::DoesNotExist` is returned.
-    pub fn execute_function<I>(&mut self, name: &str, args: &mut I) -> Result<i32, IonError>
-        where
-            I: ExactSizeIterator,
-            <I as Iterator>::Item: AsRef<str>,
-    {
+    pub fn execute_function<S: AsRef<str>>(&mut self, name: &str, args: &[S]) -> Result<i32, IonError> {
         self.functions
             .get_mut(name.into())
             .ok_or(IonError::DoesNotExist)
@@ -295,8 +291,7 @@ impl<'a> Shell {
         } else if let Some(function) = self.functions.get(&pipeline.items[0].job.command).cloned() {
             if !pipeline.requires_piping() {
                 let args: &[String] = pipeline.items[0].job.args.deref();
-                let mut args = args.iter();
-                match function.execute(self, &mut args) {
+                match function.execute(self, args) {
                     Ok(()) => None,
                     Err(FunctionError::InvalidArgumentCount) => {
                         eprintln!("ion: invalid number of function arguments supplied");
diff --git a/src/lib/shell/pipe_exec/mod.rs b/src/lib/shell/pipe_exec/mod.rs
index 1932e3e7..22a12a21 100644
--- a/src/lib/shell/pipe_exec/mod.rs
+++ b/src/lib/shell/pipe_exec/mod.rs
@@ -22,7 +22,7 @@ use builtins::{self, BuiltinFunction};
 use parser::pipelines::{Input, PipeItem, Pipeline, RedirectFrom, Redirection};
 use smallvec::SmallVec;
 use std::{
-    fs::{File, OpenOptions}, io::{self, Error, Write}, iter::{self, ExactSizeIterator},
+    fs::{File, OpenOptions}, io::{self, Error, Write}, iter,
     os::unix::io::{AsRawFd, FromRawFd, RawFd}, path::Path, process::{self, exit},
 };
 use sys;
@@ -388,28 +388,23 @@ pub(crate) trait PipelineExecution {
         stdin: &Option<File>,
     ) -> i32;
 
-    fn exec_external<'a, I>(
+    fn exec_external<'a, S: AsRef<str>>(
         &mut self,
-        name: &str,
-        args: I,
+        name: &'a str,
+        args: &'a [S],
         stdout: &Option<File>,
         stderr: &Option<File>,
         stdin: &Option<File>,
-    ) -> i32
-        where I: Iterator,
-              I::Item: AsRef<str> + 'a,
-              Vec<&'a str>: ::std::iter::FromIterator<I::Item>;
+    ) -> i32;
 
-    fn exec_function<I>(
+    fn exec_function<S: AsRef<str>>(
         &mut self,
         name: &str,
-        args: &mut I,
+        args: &[S],
         stdout: &Option<File>,
         stderr: &Option<File>,
         stdin: &Option<File>,
-    ) -> i32
-        where I: ExactSizeIterator,
-              <I as Iterator>::Item: AsRef<str>;
+    ) -> i32;
 
     /// For cat jobs
     fn exec_multi_in(
@@ -431,21 +426,17 @@ pub(crate) trait PipelineExecution {
 }
 
 impl PipelineExecution for Shell {
-    fn exec_external<'a, I>(
+    fn exec_external<'a, S: AsRef<str>>(
         &mut self,
-        name: &str,
-        args: I,
+        name: &'a str,
+        args: &'a [S],
         stdin: &Option<File>,
         stdout: &Option<File>,
         stderr: &Option<File>,
-    ) -> i32
-        where I: Iterator,
-              I::Item: AsRef<str> + 'a,
-              Vec<&'a str>: ::std::iter::FromIterator<I::Item>,
-    {
+    ) -> i32 {
         let result = sys::fork_and_exec(
             name,
-            &args.collect::<Vec<_>>(),
+            &args.iter().map(|s| s.as_ref()).collect::<Vec<_>>(),
             if let Some(ref f) = *stdin {
                 Some(f.as_raw_fd())
             } else {
@@ -493,7 +484,8 @@ impl PipelineExecution for Shell {
         stderr: &Option<File>,
         stdin: &Option<File>,
         kind: JobKind,
-    ) -> i32 {
+    ) -> i32
+    {
         if let Some(ref file) = *stdin {
             redir(file.as_raw_fd(), sys::STDIN_FILENO);
         }
@@ -537,7 +529,8 @@ impl PipelineExecution for Shell {
         sources: &mut [File],
         stdout: &Option<File>,
         stdin: &mut Option<File>,
-    ) -> i32 {
+    ) -> i32
+    {
         if let Some(ref file) = *stdin {
             redir(file.as_raw_fd(), sys::STDIN_FILENO)
         }
@@ -573,18 +566,14 @@ impl PipelineExecution for Shell {
         SUCCESS
     }
 
-    fn exec_function<I>(
+    fn exec_function<S: AsRef<str>>(
         &mut self,
         name: &str,
-        args: &mut I,
+        args: &[S],
         stdout: &Option<File>,
         stderr: &Option<File>,
         stdin: &Option<File>,
-    ) -> i32
-        where 
-            I: ExactSizeIterator,
-            <I as Iterator>::Item: AsRef<str>,
-    {
+    ) -> i32 {
         if let Some(ref file) = *stdin {
             redir(file.as_raw_fd(), sys::STDIN_FILENO);
         }
@@ -1015,11 +1004,10 @@ fn spawn_proc(
             ref stderr,
             ref stdin,
         } => {
-            let mut args = args.iter().map(|x| x as &str);
             match unsafe { sys::fork() } {
                 Ok(0) => {
                     prepare_child(block_child, pgid);
-                    let ret = shell.exec_function(name, &mut args, stdout, stderr, stdin);
+                    let ret = shell.exec_function(name, &args, stdout, stderr, stdin);
                     close(stdout);
                     close(stderr);
                     close(stdin);
-- 
GitLab