diff --git a/Cargo.lock b/Cargo.lock index 3a87016cb16700cdbd62825d172dc97ffb4f8cb4..d16a780e1a286e67fa5744bba4982d4a020f9fef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -32,6 +32,41 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "auto_enums" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "auto_enums_core 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "auto_enums_derive 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "auto_enums_core" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "auto_enums_derive" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "derive_utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "autocfg" version = "0.1.2" @@ -224,6 +259,16 @@ dependencies = [ "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "derive_utils" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "either" version = "1.5.2" @@ -306,6 +351,7 @@ name = "ion-shell" version = "1.0.0-alpha" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "auto_enums 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "calculate 0.7.0 (git+https://gitlab.redox-os.org/redox-os/calc)", "criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -321,6 +367,7 @@ dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "lexical 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "liner 0.4.5 (git+https://gitlab.redox-os.org/redox-os/liner)", + "object-pool 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "serial_test 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -336,6 +383,7 @@ dependencies = [ name = "ion_braces" version = "0.1.0" dependencies = [ + "auto_enums 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "permutate 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "small 0.1.0 (git+https://gitlab.redox-os.org/redox-os/small)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -422,6 +470,15 @@ dependencies = [ "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "lock_api" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "memchr" version = "2.2.0" @@ -519,11 +576,48 @@ name = "numtoa" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "object-pool" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ord_subset" version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "owning_ref" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "permutate" version = "0.3.2" @@ -828,6 +922,11 @@ name = "smallvec" version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "stable_deref_trait" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "stackvector" version = "1.0.2" @@ -1006,6 +1105,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" +"checksum auto_enums 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "5999c1e1bd0972da60a4a58d0eef0d183dab8b787a1fde0e94e9a995f6275928" +"checksum auto_enums_core 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "76cde7b6c90dbc5499dc58777e4fd3af08124ac8c26778044c10934e41a1e26e" +"checksum auto_enums_derive 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b14b1eac6d98375d2f325c86085dc75705fb27b95cce9a5ff232ee74d3813fa8" "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" "checksum backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f106c02a3604afcdc0df5d36cc47b44b55917dbaf3d808f71c163a0ddba64637" "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" @@ -1026,6 +1128,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum csv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f0782c7154d8dd08f4adeb5aa22ab178c10281915f7da68d10bb646f03aaee73" "checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65" "checksum decimal 2.0.4 (git+https://github.com/alkis/decimal.git)" = "<none>" +"checksum derive_utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58ced0880a3b675d62c255bbac6eefd4b4e672954084354cf65960ddea8be6d7" "checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" "checksum err-derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3d8ff65eb6c2fc68e76557239d16f5698fd56603925b89856d3f0f7105fd4543" "checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067" @@ -1042,6 +1145,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum lexical-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e82e023e062f1d25f807ad182008fba1b46538e999f908a08cc0c29e084462e" "checksum libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "bedcc7a809076656486ffe045abeeac163da1b558e963a31e29fbfbeba916917" "checksum liner 0.4.5 (git+https://gitlab.redox-os.org/redox-os/liner)" = "<none>" +"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" @@ -1054,7 +1158,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" "checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" +"checksum object-pool 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "656d9629602722ed1e911c3654ca2f60869e828cd5be441ff8383c2341eac4bc" "checksum ord_subset 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d7ce14664caf5b27f5656ff727defd68ae1eb75ef3c4d95259361df1eb376bef" +"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" +"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" +"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum permutate 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53b7d5b19a715ffab38693a9dd44b067fdfa2b18eef65bd93562dfe507022fae" "checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" "checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db" @@ -1092,6 +1200,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum serial_test_derive 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "89dd85be2e2ad75b041c9df2892ac078fa6e0b90024028b2b9fb4125b7530f01" "checksum small 0.1.0 (git+https://gitlab.redox-os.org/redox-os/small)" = "<none>" "checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" +"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum stackvector 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c049c77bf85fbc036484c97b008276d539d9ebff9dfbde37b632ebcd5b8746b6" "checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" diff --git a/Cargo.toml b/Cargo.toml index acd1a98072aaf3393e0638b35e41210942054524..573216cd3e956b6f08b843b076ca44395b0e1558 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,6 +67,8 @@ ion-ranges = { path = "members/ranges" } hashbrown = "0.1.2" itertools = "0.8" lexical = "2.0" +object-pool = "0.3.1" +auto_enums = "0.5.5" [lib] path = "src/lib/lib.rs" diff --git a/members/braces/Cargo.toml b/members/braces/Cargo.toml index 9a345265af703d470279f035e30c5fbc52410c2a..23d989320cc33b336eb049c8037890154eab94ac 100644 --- a/members/braces/Cargo.toml +++ b/members/braces/Cargo.toml @@ -2,8 +2,10 @@ name = "ion_braces" version = "0.1.0" authors = ["Michael Murphy <mmstickman@gmail.com>"] +edition = "2018" [dependencies] permutate = "0.3" smallvec = "0.6" small = { git = "https://gitlab.redox-os.org/redox-os/small", features = ["std"] } +auto_enums = "0.5.5" diff --git a/members/braces/src/lib.rs b/members/braces/src/lib.rs index 0e0249f7a186aa627765155c6a229ec0fe5f32b4..9e97c0969bde2ff648674a687979468cc851892a 100644 --- a/members/braces/src/lib.rs +++ b/members/braces/src/lib.rs @@ -1,7 +1,4 @@ -extern crate permutate; -extern crate small; -extern crate smallvec; - +use auto_enums::auto_enum; use permutate::Permutator; use smallvec::SmallVec; @@ -12,21 +9,16 @@ pub enum BraceToken { Expander, } +#[auto_enum] pub fn expand<'a>( tokens: &'a [BraceToken], expanders: &'a [&'a [&'a str]], -) -> Box<Iterator<Item = small::String> + 'a> { +) -> impl Iterator<Item = small::String> + 'a { + #[auto_enum(Iterator)] match expanders.len() { - 0 => Box::new(::std::iter::empty()), - 1 => { - let single_brace_expand = - SingleBraceExpand { elements: expanders[0].iter().cloned(), tokens, loop_count: 0 }; - Box::new(single_brace_expand) - } - _ => { - let multiple_brace_expand = MultipleBraceExpand::new(tokens, expanders); - Box::new(multiple_brace_expand) - } + 0 => ::std::iter::empty(), + 1 => SingleBraceExpand { elements: expanders[0].iter().cloned(), tokens, loop_count: 0 }, + _ => MultipleBraceExpand::new(tokens, expanders), } } diff --git a/src/lib/lib.rs b/src/lib/lib.rs index f50e53b7e71c66cb6cc43c882d91e967322352aa..83b637515e65470f164a56cb799974f884b6b0fd 100644 --- a/src/lib/lib.rs +++ b/src/lib/lib.rs @@ -15,8 +15,10 @@ pub mod types; pub mod parser; mod ascii_helpers; mod builtins; +mod memory; pub mod shell; +pub(crate) use self::memory::IonPool; pub use crate::shell::{ binary::MAN_ION, flags, pipe_exec::job_control::JobControl, status, Binary, Capture, Fork, IonError, IonResult, Shell, ShellBuilder, diff --git a/src/lib/memory.rs b/src/lib/memory.rs new file mode 100644 index 0000000000000000000000000000000000000000..ad932f565b550c5a998e0325b433d4e966f0f9c6 --- /dev/null +++ b/src/lib/memory.rs @@ -0,0 +1,36 @@ +// TODO: Shrink values that grow too large, after use. + +// use crate::types::Array; +use object_pool::Pool; +use small::String; + +thread_local! { + static STRINGS: Pool<String> = Pool::new(256, String::new); + // static STRING_VECS: Pool<Array> = Pool::new(1024, Array::new?); +} + +pub struct IonPool; + +impl IonPool { + pub fn string<T, F: FnMut(&mut String) -> T>(mut callback: F) -> T { + STRINGS.with(|pool| match pool.pull() { + Some(ref mut string) => { + string.clear(); + callback(string) + } + None => callback(&mut String::new()), + }) + } + + // pub fn vec_of_string<T, F: FnMut(&mut Array) -> T>(mut callback: F) -> T { + // STRING_VECS.with(|pool| { + // match pool.pull() { + // Some(ref mut vector) => { + // vector.clear(); + // callback(vector) + // } + // None => callback(&mut Array::new()) + // } + // }) + // } +} diff --git a/src/lib/parser/shell_expand/mod.rs b/src/lib/parser/shell_expand/mod.rs index f5faa527ebb5b3cbd904204fbc9e58c0ca0a9f66..7b213599615d9e613116c744cbca32a5c4245a34 100644 --- a/src/lib/parser/shell_expand/mod.rs +++ b/src/lib/parser/shell_expand/mod.rs @@ -295,72 +295,95 @@ fn expand_braces<E: Expander>( let tokens: &mut Vec<BraceToken> = &mut Vec::new(); let mut expanders: Vec<Vec<small::String>> = Vec::new(); - for word in word_tokens { - match *word { - WordToken::Array(ref elements, ref index) => { - output.push_str(&array_expand(elements, expand_func, &index).join(" ")); - } - WordToken::ArrayVariable(array, _, ref index) => { - if let Some(array) = expand_func.array(array, index) { - output.push_str(&array.join(" ")); - } - } - WordToken::ArrayProcess(command, _, ref index) => match *index { - Select::All => { - let mut temp = small::String::new(); - expand_process(&mut temp, command, &Select::All, expand_func, false); - output.push_str(&temp); - } - Select::Index(Index::Forward(id)) => { - let mut temp = small::String::new(); - expand_process(&mut temp, command, &Select::All, expand_func, false); - output.push_str(temp.split_whitespace().nth(id).unwrap_or_default()); - } - Select::Index(Index::Backward(id)) => { - let mut temp = small::String::new(); - expand_process(&mut temp, command, &Select::All, expand_func, false); - output.push_str(temp.split_whitespace().rev().nth(id).unwrap_or_default()); - } - Select::Range(range) => { - let mut temp = small::String::new(); - expand_process(&mut temp, command, &Select::All, expand_func, false); - let len = temp.split_whitespace().count(); - if let Some((start, length)) = range.bounds(len) { - let res = - temp.split_whitespace().skip(start).take(length).collect::<Vec<&str>>(); - output.push_str(&res.join(" ")); + { + let output = &mut output; + crate::IonPool::string(|temp| { + for word in word_tokens { + match *word { + WordToken::Array(ref elements, ref index) => { + output.push_str(&array_expand(elements, expand_func, &index).join(" ")); + } + WordToken::ArrayVariable(array, _, ref index) => { + if let Some(array) = expand_func.array(array, index) { + output.push_str(&array.join(" ")); + } + } + WordToken::ArrayProcess(command, _, ref index) => match *index { + Select::All => { + expand_process(temp, command, &Select::All, expand_func, false); + output.push_str(&temp); + } + Select::Index(Index::Forward(id)) => { + expand_process(temp, command, &Select::All, expand_func, false); + output.push_str(temp.split_whitespace().nth(id).unwrap_or_default()); + } + Select::Index(Index::Backward(id)) => { + expand_process(temp, command, &Select::All, expand_func, false); + output.push_str( + temp.split_whitespace().rev().nth(id).unwrap_or_default(), + ); + } + Select::Range(range) => { + expand_process(temp, command, &Select::All, expand_func, false); + let len = temp.split_whitespace().count(); + if let Some((start, length)) = range.bounds(len) { + let mut iter = temp.split_whitespace().skip(start).take(length); + if let Some(str) = iter.next() { + output.push_str(str); + iter.for_each(|str| { + output.push(' '); + output.push_str(str); + }); + } + } + } + Select::Key(_) | Select::None => (), + }, + WordToken::ArrayMethod(ref method) => { + method.handle(output, expand_func); + } + WordToken::StringMethod(ref method) => { + method.handle(output, expand_func); + } + WordToken::Brace(ref nodes) => expand_brace( + output, + &mut expanders, + tokens, + nodes, + expand_func, + reverse_quoting, + ), + WordToken::Whitespace(whitespace) => output.push_str(whitespace), + WordToken::Process(command, quoted, ref index) => { + expand_process( + output, + command, + &index, + expand_func, + quoted ^ reverse_quoting, + ); + } + WordToken::Variable(text, quoted, ref index) => { + if let Some(expanded) = expand_func.string(text, quoted ^ reverse_quoting) { + slice(output, expanded, &index); + }; + } + WordToken::Normal(ref text, _, tilde) => { + expand( + output, + &mut expanded_words, + expand_func, + text.as_ref(), + false, + tilde, + ); } + WordToken::Arithmetic(s) => expand_arithmetic(output, s, expand_func), } - Select::Key(_) | Select::None => (), - }, - WordToken::ArrayMethod(ref method) => { - method.handle(&mut output, expand_func); - } - WordToken::StringMethod(ref method) => { - method.handle(&mut output, expand_func); - } - WordToken::Brace(ref nodes) => expand_brace( - &mut output, - &mut expanders, - tokens, - nodes, - expand_func, - reverse_quoting, - ), - WordToken::Whitespace(whitespace) => output.push_str(whitespace), - WordToken::Process(command, quoted, ref index) => { - expand_process(&mut output, command, &index, expand_func, quoted ^ reverse_quoting); - } - WordToken::Variable(text, quoted, ref index) => { - if let Some(expanded) = expand_func.string(text, quoted ^ reverse_quoting) { - slice(&mut output, expanded, &index); - }; - } - WordToken::Normal(ref text, _, tilde) => { - expand(&mut output, &mut expanded_words, expand_func, text.as_ref(), false, tilde); + + temp.clear(); } - WordToken::Arithmetic(s) => expand_arithmetic(&mut output, s, expand_func), - } + }); } if expanders.is_empty() { @@ -559,78 +582,87 @@ pub(crate) fn expand_tokens<E: Expander>( let mut output = small::String::new(); let mut expanded_words = types::Array::new(); - for word in token_buffer { - match *word { - WordToken::Array(ref elements, ref index) => { - output.push_str(&array_expand(elements, expand_func, &index).join(" ")); - } - WordToken::ArrayVariable(array, _, ref index) => { - if let Some(array) = expand_func.array(array, index) { - output.push_str(&array.join(" ")); - } - } - WordToken::ArrayProcess(command, _, ref index) => match index { - Select::All => { - let mut temp = small::String::new(); - expand_process(&mut temp, command, &Select::All, expand_func, false); - output.push_str(&temp); - } - Select::Index(Index::Forward(id)) => { - let mut temp = small::String::new(); - expand_process(&mut temp, command, &Select::All, expand_func, false); - output.push_str(temp.split_whitespace().nth(*id).unwrap_or_default()); - } - Select::Index(Index::Backward(id)) => { - let mut temp = small::String::new(); - expand_process(&mut temp, command, &Select::All, expand_func, false); - output.push_str(temp.split_whitespace().rev().nth(*id).unwrap_or_default()); - } - Select::Range(range) => { - let mut temp = small::String::new(); - expand_process(&mut temp, command, &Select::All, expand_func, false); - if let Some((start, length)) = range.bounds(temp.split_whitespace().count()) - { - let temp = temp - .split_whitespace() - .skip(start) - .take(length) - .collect::<Vec<_>>(); - output.push_str(&temp.join(" ")) + { + let output = &mut output; + crate::IonPool::string(|temp| { + for word in token_buffer { + match *word { + WordToken::Array(ref elements, ref index) => { + output.push_str(&array_expand(elements, expand_func, &index).join(" ")); } + WordToken::ArrayVariable(array, _, ref index) => { + if let Some(array) = expand_func.array(array, index) { + output.push_str(&array.join(" ")); + } + } + WordToken::ArrayProcess(command, _, ref index) => match index { + Select::All => { + expand_process(temp, command, &Select::All, expand_func, false); + output.push_str(&temp); + } + Select::Index(Index::Forward(id)) => { + expand_process(temp, command, &Select::All, expand_func, false); + output + .push_str(temp.split_whitespace().nth(*id).unwrap_or_default()); + } + Select::Index(Index::Backward(id)) => { + expand_process(temp, command, &Select::All, expand_func, false); + output.push_str( + temp.split_whitespace().rev().nth(*id).unwrap_or_default(), + ); + } + Select::Range(range) => { + expand_process(temp, command, &Select::All, expand_func, false); + if let Some((start, length)) = + range.bounds(temp.split_whitespace().count()) + { + let temp = temp + .split_whitespace() + .skip(start) + .take(length) + .collect::<Vec<_>>(); + output.push_str(&temp.join(" ")) + } + } + Select::Key(_) | Select::None => (), + }, + WordToken::ArrayMethod(ref method) => { + method.handle(output, expand_func); + } + WordToken::StringMethod(ref method) => { + method.handle(output, expand_func); + } + WordToken::Brace(_) => unreachable!(), + WordToken::Normal(ref text, do_glob, tilde) => { + expand( + output, + &mut expanded_words, + expand_func, + text.as_ref(), + do_glob, + tilde, + ); + } + WordToken::Whitespace(text) => { + output.push_str(text); + } + WordToken::Process(command, quoted, ref index) => { + let quoted = if reverse_quoting { !quoted } else { quoted }; + expand_process(output, command, &index, expand_func, quoted); + } + WordToken::Variable(text, quoted, ref index) => { + if let Some(expanded) = + expand_func.string(text, quoted ^ reverse_quoting) + { + slice(output, expanded, &index); + } + } + WordToken::Arithmetic(s) => expand_arithmetic(output, s, expand_func), } - Select::Key(_) | Select::None => (), - }, - WordToken::ArrayMethod(ref method) => { - method.handle(&mut output, expand_func); - } - WordToken::StringMethod(ref method) => { - method.handle(&mut output, expand_func); - } - WordToken::Brace(_) => unreachable!(), - WordToken::Normal(ref text, do_glob, tilde) => { - expand( - &mut output, - &mut expanded_words, - expand_func, - text.as_ref(), - do_glob, - tilde, - ); - } - WordToken::Whitespace(text) => { - output.push_str(text); - } - WordToken::Process(command, quoted, ref index) => { - let quoted = if reverse_quoting { !quoted } else { quoted }; - expand_process(&mut output, command, &index, expand_func, quoted); - } - WordToken::Variable(text, quoted, ref index) => { - if let Some(expanded) = expand_func.string(text, quoted ^ reverse_quoting) { - slice(&mut output, expanded, &index); - } + + temp.clear(); } - WordToken::Arithmetic(s) => expand_arithmetic(&mut output, s, expand_func), - } + }); } if !output.is_empty() { @@ -648,33 +680,36 @@ pub(crate) fn expand_tokens<E: Expander>( /// ``` /// if `x=5` and `y=7` fn expand_arithmetic<E: Expander>(output: &mut small::String, input: &str, expander: &E) { - // small::String cannot be created with a capacity of 0 without causing a panic - let len = if !input.is_empty() { input.len() } else { 1 }; - let mut intermediate = small::String::with_capacity(len); - let mut varbuf = small::String::new(); - let flush = |var: &mut small::String, out: &mut small::String| { - if !var.is_empty() { - // We have reached the end of a potential variable, so we expand it and push - // it onto the result - out.push_str(expander.string(&var, false).as_ref().unwrap_or(var)); - } - }; - for c in input.bytes() { - match c { - 48...57 | 65...90 | 95 | 97...122 => { - varbuf.push(c as char); - } - _ => { - flush(&mut varbuf, &mut intermediate); - varbuf.clear(); - intermediate.push(c as char); + crate::IonPool::string(|intermediate| { + crate::IonPool::string(|varbuf| { + let flush = |var: &mut small::String, out: &mut small::String| { + if !var.is_empty() { + // We have reached the end of a potential variable, so we expand it and push + // it onto the result + out.push_str(expander.string(&var, false).as_ref().unwrap_or(var)); + } + }; + + for c in input.bytes() { + match c { + 48...57 | 65...90 | 95 | 97...122 => { + varbuf.push(c as char); + } + _ => { + flush(varbuf, intermediate); + varbuf.clear(); + intermediate.push(c as char); + } + } } - } - } - flush(&mut varbuf, &mut intermediate); - output.push_str(&match calc::eval(&intermediate) { - Ok(s) => s.to_string(), - Err(e) => e.to_string(), + + flush(varbuf, intermediate); + + output.push_str(&match calc::eval(&intermediate) { + Ok(s) => s.to_string(), + Err(e) => e.to_string(), + }); + }); }); } diff --git a/src/lib/shell/completer.rs b/src/lib/shell/completer.rs index 2c4ddf5f388e8050f26d824058f0b98acf0ea645..8c1e9567df91592ebbe06149cc4fb931e06979d5 100644 --- a/src/lib/shell/completer.rs +++ b/src/lib/shell/completer.rs @@ -3,6 +3,7 @@ use super::{ escape::{escape, unescape}, variables::Variables, }; +use auto_enums::auto_enum; use glob::glob; use liner::{Completer, FilenameCompleter}; use smallvec::SmallVec; @@ -86,6 +87,7 @@ impl Completer for IonFileCompleter { } } +#[auto_enum] fn filename_completion<'a, LC>( start: &'a str, liner_complete: LC, @@ -131,9 +133,10 @@ where } }); - let iter_inner_glob: Box<Iterator<Item = String>> = match globs { - Some(iter) => Box::new(iter), - None => Box::new(iter::once(escape(start))), + #[auto_enum(Iterator)] + let iter_inner_glob = match globs { + Some(iter) => iter, + None => iter::once(escape(start)), }; // Use Liner::Completer as well, to preserve the previous behaviour diff --git a/src/lib/shell/pipe_exec/mod.rs b/src/lib/shell/pipe_exec/mod.rs index 060c143f804d0b4513364110d3df734686ce772a..cc61d94e2b953fa5b1cbbd45a157241fd15bccea 100644 --- a/src/lib/shell/pipe_exec/mod.rs +++ b/src/lib/shell/pipe_exec/mod.rs @@ -582,15 +582,21 @@ impl PipelineExecution for Shell { } fn wait(&mut self, pgid: u32, commands: SmallVec<[RefinedJob; 16]>) -> i32 { - let as_string = if commands.is_empty() { - // This doesn't allocate - String::new() - } else { - commands.iter().map(RefinedJob::long).collect::<Vec<String>>().join(" | ") - }; + crate::IonPool::string(|as_string| { + if !commands.is_empty() { + let mut iter = commands.iter().map(RefinedJob::long); + if let Some(str) = iter.next() { + as_string.push_str(&str); + iter.for_each(|str| { + as_string.push_str(" | "); + as_string.push_str(&str); + }) + } + } - // Watch the foreground group, dropping all commands that exit as they exit. - self.watch_foreground(-(pgid as i32), &as_string) + // Watch the foreground group, dropping all commands that exit as they exit. + self.watch_foreground(-(pgid as i32), &as_string) + }) } fn generate_commands(