diff --git a/Cargo.lock b/Cargo.lock index 2de48ccb53a9be13a368bf0ffe910643c776b988..d52e93c7c2086a5c82a09da06679f07504ba1c03 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,7 +41,7 @@ name = "backtrace-sys" version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -68,7 +68,7 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -104,7 +104,7 @@ version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", "ord_subset 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", @@ -176,7 +176,7 @@ dependencies = [ "liner 0.4.5 (git+https://gitlab.redox-os.org/redox-os/liner)", "rand 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smallstring 0.1.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.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -188,6 +188,7 @@ name = "ion_braces" version = "0.1.0" dependencies = [ "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.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -198,7 +199,7 @@ dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "calculate 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallstring 0.1.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.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -213,7 +214,7 @@ dependencies = [ name = "ion_ranges" version = "0.1.0" dependencies = [ - "smallstring 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "small 0.1.0 (git+https://gitlab.redox-os.org/redox-os/small)", ] [[package]] @@ -246,7 +247,7 @@ name = "libloading" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -349,17 +350,9 @@ version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "smallstring" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "smallvec" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "small" +version = "0.1.0" +source = "git+https://gitlab.redox-os.org/redox-os/small#9ecee66b5ce315236afb7062b36b608cb4e3dca2" [[package]] name = "smallvec" @@ -514,7 +507,7 @@ source = "git+https://github.com/whitequark/rust-xdg#090afef2509d746e48d6bfa9b2e "checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" "checksum bytecount 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "882585cd7ec84e902472df34a5e01891202db3bf62614e1f0afe459c1afcf744" "checksum calculate 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dfe3fe310e5858ba47beb9443acec7fb39b90ea5677d35636306fe7b495a547c" -"checksum cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "49ec142f5768efb5b7622aebc3fdbdbb8950a4b9ba996393cb76ef7466e8747d" +"checksum cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "2119ea4867bd2b8ed3aecab467709720b2d55b1bcfe09f772fd68066eaf15275" "checksum cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efe5c877e17a9c717a0bf3613b2709f723202c4e4675cc8f12926ded29bcb17e" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" @@ -543,8 +536,7 @@ source = "git+https://github.com/whitequark/rust-xdg#090afef2509d746e48d6bfa9b2e "checksum rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "76d7ba1feafada44f2d38eed812bd2489a03c0f5abb975799251518b68848649" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)" = "0c3adf19c07af6d186d91dae8927b83b0553d07ca56cbf7f2f32560455c91920" -"checksum smallstring 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30950abdb5b38f56a0e181ae56ed64a539b64fa77ea6325147203dc7faeb087f" -"checksum smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4f8266519bc1d17d0b5b16f6c21295625d562841c708f6376f49028a43e9c11e" +"checksum small 0.1.0 (git+https://gitlab.redox-os.org/redox-os/small)" = "<none>" "checksum smallvec 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "312a7df010092e73d6bbaf141957e868d4f30efd2bfd9bb1028ad91abec58514" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" diff --git a/Cargo.toml b/Cargo.toml index 953cf887750a295e22bc6c2c1f79ad14a52baf35..a483624b294dccca2dec56aff02efa0e37511b38 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,7 +42,7 @@ lazy_static = "1.0" liner = { git = "https://gitlab.redox-os.org/redox-os/liner" } rand = "0.5" regex = "1.0" -smallstring = "0.1" +small = { git = "https://gitlab.redox-os.org/redox-os/small", features = ["std"] } smallvec = "0.6" unicode-segmentation = "1.2" xdg = { git = "https://github.com/whitequark/rust-xdg" } diff --git a/members/braces/Cargo.toml b/members/braces/Cargo.toml index 97800764897ca59ffcb64c9ff173f83d67624533..9a345265af703d470279f035e30c5fbc52410c2a 100644 --- a/members/braces/Cargo.toml +++ b/members/braces/Cargo.toml @@ -6,3 +6,4 @@ authors = ["Michael Murphy <mmstickman@gmail.com>"] [dependencies] permutate = "0.3" smallvec = "0.6" +small = { git = "https://gitlab.redox-os.org/redox-os/small", features = ["std"] } diff --git a/members/braces/src/lib.rs b/members/braces/src/lib.rs index a3029aba25c96b331b0dd8e3efc79ad1346dc002..b9ef13b4c417eb848ff8edee8103cdd7d038a8db 100644 --- a/members/braces/src/lib.rs +++ b/members/braces/src/lib.rs @@ -1,5 +1,6 @@ extern crate permutate; extern crate smallvec; +extern crate small; use permutate::Permutator; use smallvec::SmallVec; @@ -7,14 +8,14 @@ use smallvec::SmallVec; #[derive(Debug)] /// A token primitive for the `expand_braces` function. pub enum BraceToken { - Normal(String), + Normal(small::String), Expander, } pub fn expand<'a>( tokens: &'a [BraceToken], expanders: &'a [&'a [&'a str]], -) -> Box<Iterator<Item = String> + 'a> { +) -> Box<Iterator<Item = small::String> + 'a> { if expanders.len() > 1 { let multiple_brace_expand = MultipleBraceExpand::new(tokens, expanders); Box::new(multiple_brace_expand) @@ -70,7 +71,7 @@ impl<'a> MultipleBraceExpand<'a> { } impl<'a> Iterator for MultipleBraceExpand<'a> { - type Item = String; + type Item = small::String; fn next(&mut self) -> Option<Self::Item> { if self.permutator.next_with_buffer(&mut self.buffer) { @@ -88,7 +89,7 @@ impl<'a> Iterator for MultipleBraceExpand<'a> { } }, ); - Some(unsafe { String::from_utf8_unchecked(small_vec.to_vec()) }) + Some(unsafe { small::String::from_utf8_unchecked(small_vec.to_vec()) }) } else { None } @@ -108,7 +109,7 @@ impl<'a, 'b, I> Iterator for SingleBraceExpand<'a, 'b, I> where I: Iterator<Item = &'a str>, { - type Item = String; + type Item = small::String; fn next(&mut self) -> Option<Self::Item> { match self.loop_count { @@ -127,7 +128,7 @@ where }, ); self.loop_count = 1; - Some(unsafe { String::from_utf8_unchecked(small_vec.to_vec()) }) + Some(unsafe { small::String::from_utf8_unchecked(small_vec.to_vec()) }) } _ => { if let Some(element) = self.elements.next() { @@ -144,7 +145,7 @@ where } }, ); - Some(unsafe { String::from_utf8_unchecked(small_vec.to_vec()) }) + Some(unsafe { small::String::from_utf8_unchecked(small_vec.to_vec()) }) } else { None } @@ -161,25 +162,25 @@ mod tests { fn test_multiple_brace_expand() { let expanders: &[&[&str]] = &[&["1", "2"][..], &["3", "4"][..], &["5", "6"][..]]; let tokens: &[BraceToken] = &[ - BraceToken::Normal("AB".to_owned()), + BraceToken::Normal("AB".into()), BraceToken::Expander, - BraceToken::Normal("CD".to_owned()), + BraceToken::Normal("CD".into()), BraceToken::Expander, - BraceToken::Normal("EF".to_owned()), + BraceToken::Normal("EF".into()), BraceToken::Expander, - BraceToken::Normal("GH".to_owned()), + BraceToken::Normal("GH".into()), ]; assert_eq!( - MultipleBraceExpand::new(tokens, expanders).collect::<Vec<String>>(), + MultipleBraceExpand::new(tokens, expanders).collect::<Vec<small::String>>(), vec![ - "AB1CD3EF5GH".to_owned(), - "AB1CD3EF6GH".to_owned(), - "AB1CD4EF5GH".to_owned(), - "AB1CD4EF6GH".to_owned(), - "AB2CD3EF5GH".to_owned(), - "AB2CD3EF6GH".to_owned(), - "AB2CD4EF5GH".to_owned(), - "AB2CD4EF6GH".to_owned(), + small::String::from("AB1CD3EF5GH"), + small::String::from("AB1CD3EF6GH"), + small::String::from("AB1CD4EF5GH"), + small::String::from("AB1CD4EF6GH"), + small::String::from("AB2CD3EF5GH"), + small::String::from("AB2CD3EF6GH"), + small::String::from("AB2CD4EF5GH"), + small::String::from("AB2CD4EF6GH"), ] ); } @@ -187,14 +188,18 @@ mod tests { #[test] fn test_single_brace_expand() { let elements = &["one", "two", "three"]; - let tokens: &[BraceToken] = &[BraceToken::Normal("A=".to_owned()), BraceToken::Expander]; + let tokens: &[BraceToken] = &[BraceToken::Normal("A=".into()), BraceToken::Expander]; assert_eq!( SingleBraceExpand { elements: elements.iter().map(|element| *element), tokens, loop_count: 0, - }.collect::<Vec<String>>(), - vec!["A=one".to_owned(), "A=two".to_owned(), "A=three".to_owned()] + }.collect::<Vec<small::String>>(), + vec![ + small::String::from("A=one"), + small::String::from("A=two"), + small::String::from("A=three"), + ] ); } } diff --git a/members/builtins/Cargo.toml b/members/builtins/Cargo.toml index 25a796d14a2994d3544804f6cd8c25c345806b2c..a1e15a27b4482f0fdbe565ed7572ea45ad4d1759 100644 --- a/members/builtins/Cargo.toml +++ b/members/builtins/Cargo.toml @@ -8,5 +8,5 @@ publish = false bitflags = "1.0" calculate = "0.5" rand = "0.5" -smallstring = "0.1" +small = { git = "https://gitlab.redox-os.org/redox-os/small", features = ["std"] } smallvec = "0.6" diff --git a/members/builtins/src/calc.rs b/members/builtins/src/calc.rs index 074e23bc281d4ef86b0fda91043c65f75d680727..537e767ad3df97075a769ae60c823443b145010e 100644 --- a/members/builtins/src/calc.rs +++ b/members/builtins/src/calc.rs @@ -1,5 +1,6 @@ use calculate::{eval, eval_polish, CalcError, Value}; use std::io::{self, Write}; +use small; const REPL_GUIDE: &'static str = r#"ion-calc Type in expressions to have them evaluated. @@ -49,7 +50,7 @@ fn calc_or_polish_calc(args: &str) -> Result<Value, CalcError> { } } -pub fn calc(args: &[String]) -> Result<(), String> { +pub fn calc(args: &[small::String]) -> Result<(), String> { let stdout = io::stdout(); let mut stdout = stdout.lock(); match args.first() { diff --git a/members/builtins/src/conditionals.rs b/members/builtins/src/conditionals.rs index 677342c0d46897754c8e5ecf34c882b89a9df1ef..0dc83bad26938a492e9275848f060e9e744fb232 100644 --- a/members/builtins/src/conditionals.rs +++ b/members/builtins/src/conditionals.rs @@ -1,17 +1,19 @@ +use small; + macro_rules! string_function { ($method:tt) => { - pub fn $method(args: &[String]) -> i32 { + pub fn $method(args: &[small::String]) -> i32 { match args.len() { 0...2 => { eprintln!("ion: {}: two arguments must be supplied", args[0]); return 2; } - 3 => if args[1].$method(&args[2]) { + 3 => if args[1].$method(args[2].as_str()) { 0 } else { 1 }, - _ => if args[2..].iter().any(|arg| args[1].$method(arg)) { + _ => if args[2..].iter().any(|arg| args[1].$method(arg.as_str())) { 0 } else { 1 diff --git a/members/builtins/src/echo.rs b/members/builtins/src/echo.rs index 2aa8b5c26c32609fee9f98d55dadba93ae217029..0911a3e98e186f2ec5c1f3daa457e1d6fcf065cf 100644 --- a/members/builtins/src/echo.rs +++ b/members/builtins/src/echo.rs @@ -1,3 +1,4 @@ +use small; use smallvec::SmallVec; use std::io::{self, BufWriter, Write}; @@ -9,7 +10,7 @@ bitflags! { } } -pub fn echo(args: &[String]) -> Result<(), io::Error> { +pub fn echo(args: &[small::String]) -> Result<(), io::Error> { let mut flags = Flags::empty(); let mut data: SmallVec<[&str; 16]> = SmallVec::with_capacity(16); diff --git a/members/builtins/src/lib.rs b/members/builtins/src/lib.rs index a2cce04c833c78d00bea496e73920b257050ff85..95fac1bd7916526d2294c92b1d0aa3ef892290ac 100644 --- a/members/builtins/src/lib.rs +++ b/members/builtins/src/lib.rs @@ -2,7 +2,7 @@ extern crate bitflags; extern crate calc as calculate; extern crate rand; -extern crate smallstring; +extern crate small; extern crate smallvec; pub mod calc; diff --git a/members/builtins/src/random.rs b/members/builtins/src/random.rs index fade40ba64eadd59e7a31d5a9e6d6c6d164d3a54..63219b2583e302bcf09e83ea118f36bd40615eed 100644 --- a/members/builtins/src/random.rs +++ b/members/builtins/src/random.rs @@ -1,14 +1,15 @@ use rand::{thread_rng, Rng}; use std::io::{self, Write}; +use small; #[allow(unused_must_use)] -fn rand_list(args: &[String]) -> Result<(), String> { +fn rand_list(args: &[small::String]) -> Result<(), small::String> { let stdout = io::stdout(); let mut stdout = stdout.lock(); let mut output = Vec::new(); let arg1 = match args[0].parse::<usize>() { Ok(v) => v, - Err(_) => return Err(String::from("Invalid argument for random")), + Err(_) => return Err("Invalid argument for random".into()), }; while output.len() < arg1 { let rand_num = thread_rng().gen_range(1, args.len()); @@ -21,8 +22,9 @@ fn rand_list(args: &[String]) -> Result<(), String> { writeln!(stdout); Ok(()) } + #[allow(unused_must_use)] -pub fn random(args: &[String]) -> Result<(), String> { +pub fn random(args: &[small::String]) -> Result<(), small::String> { let stdout = io::stdout(); let mut stdout = stdout.lock(); match args.len() { @@ -39,14 +41,14 @@ pub fn random(args: &[String]) -> Result<(), String> { 2 => { let arg1 = match args[0].parse::<u64>() { Ok(v) => v, - Err(_) => return Err(String::from("Invalid argument for random")), + Err(_) => return Err("Invalid argument for random".into()), }; let arg2 = match args[1].parse::<u64>() { Ok(v) => v, - Err(_) => return Err(String::from("Invalid argument for random")), + Err(_) => return Err("Invalid argument for random".into()), }; if arg2 <= arg1 { - return Err(String::from("END must be greater than START")); + return Err("END must be greater than START".into()); } let rand_num = thread_rng().gen_range(arg1, arg2); writeln!(stdout, "{}", rand_num); @@ -54,7 +56,7 @@ pub fn random(args: &[String]) -> Result<(), String> { 3 => { let arg1 = match args[0].parse::<u64>() { Ok(v) => v, - Err(_) => return Err(String::from("Invalid argument for random")), + Err(_) => return Err("Invalid argument for random".into()), }; let arg2 = match args[1].parse::<u64>() { Ok(v) => v, @@ -63,7 +65,7 @@ pub fn random(args: &[String]) -> Result<(), String> { match args[2].parse::<u64>() { Ok(v) => { if arg2 <= arg1 { - return Err(String::from("END must be greater than START")); + return Err("END must be greater than START".into()); } let mut end = v / arg2 + 1; if arg1 / arg2 >= end { diff --git a/members/builtins/src/test.rs b/members/builtins/src/test.rs index 63c9a0d29c7b83f7cfb727241ed4e2181b445c5d..8b931f475fdbe85b7b16f6186cb2baf0a2b94934 100644 --- a/members/builtins/src/test.rs +++ b/members/builtins/src/test.rs @@ -1,4 +1,4 @@ -use smallstring::SmallString; +use small; use std::{ fs, os::unix::fs::{FileTypeExt, MetadataExt, PermissionsExt}, @@ -118,12 +118,12 @@ const QUICK_GUIDE: &'static str = r#"Usage: test [EXPRESSION] Try 'test --help' for more information."#; -pub fn test(args: &[String]) -> Result<bool, String> { +pub fn test(args: &[small::String]) -> Result<bool, small::String> { let arguments = &args[1..]; evaluate_arguments(arguments) } -fn evaluate_arguments(arguments: &[String]) -> Result<bool, String> { +fn evaluate_arguments(arguments: &[small::String]) -> Result<bool, small::String> { match arguments.first() { Some(ref s) if s.starts_with('-') && s[1..].starts_with(char::is_alphabetic) => { // Access the second character in the flag string: this will be type of the @@ -151,7 +151,7 @@ fn evaluate_arguments(arguments: &[String]) -> Result<bool, String> { // If there is no right hand argument, a condition was expected let right_arg = arguments .get(2) - .ok_or_else(|| SmallString::from("parse error: condition expected"))?; + .ok_or_else(|| small::String::from("parse error: condition expected"))?; evaluate_expression(arg, operator, right_arg) }) } @@ -162,7 +162,7 @@ fn evaluate_arguments(arguments: &[String]) -> Result<bool, String> { } } -fn evaluate_expression(first: &str, operator: &str, second: &str) -> Result<bool, String> { +fn evaluate_expression(first: &str, operator: &str, second: &str) -> Result<bool, small::String> { match operator { "=" | "==" => Ok(first == second), "!=" => Ok(first != second), @@ -178,7 +178,7 @@ fn evaluate_expression(first: &str, operator: &str, second: &str) -> Result<bool "-le" => Ok(left <= right), "-lt" => Ok(left < right), "-ne" => Ok(left != right), - _ => Err(format!("test: unknown condition: {:?}", operator)), + _ => Err(format!("test: unknown condition: {:?}", operator).into()), } } } @@ -223,13 +223,13 @@ fn get_modified_file_time(filename: &str) -> Option<SystemTime> { } /// Attempt to parse a &str as a usize. -fn parse_integers(left: &str, right: &str) -> Result<(Option<isize>, Option<isize>), String> { - let parse_integer = |input: &str| -> Result<Option<isize>, String> { +fn parse_integers(left: &str, right: &str) -> Result<(Option<isize>, Option<isize>), small::String> { + let parse_integer = |input: &str| -> Result<Option<isize>, small::String> { match input .parse::<isize>() .map_err(|_| format!("test: integer expression expected: {:?}", input)) { - Err(why) => Err(why), + Err(why) => Err(why.into()), Ok(res) => Ok(Some(res)), } }; @@ -383,20 +383,20 @@ fn test_strings() { #[test] fn test_empty_str() { - let eval = |args: Vec<String>| evaluate_arguments(&args); - assert_eq!(eval(vec!["".to_owned()]), Ok(false)); + let eval = |args: Vec<small::String>| evaluate_arguments(&args); + assert_eq!(eval(vec!["".into()]), Ok(false)); assert_eq!( - eval(vec!["c".to_owned(), "=".to_owned(), "".to_owned()]), + eval(vec!["c".into(), "=".into(), "".into()]), Ok(false) ); } #[test] fn test_integers_arguments() { - fn vec_string(args: &[&str]) -> Vec<String> { + fn vec_string(args: &[&str]) -> Vec<small::String> { args.iter() - .map(|s| (*s).to_owned()) - .collect::<Vec<String>>() + .map(|s| (*s).into()) + .collect() } // Equal To assert_eq!( diff --git a/members/ranges/Cargo.toml b/members/ranges/Cargo.toml index bdedec443ce673becbbf0078fb2e312d6a15154e..7a625af75cd70d537fec241c03a0fc5b0015243a 100644 --- a/members/ranges/Cargo.toml +++ b/members/ranges/Cargo.toml @@ -4,4 +4,4 @@ version = "0.1.0" authors = ["Michael Murphy <mmstickman@gmail.com>"] [dependencies] -smallstring = "0.1" +small = { git = "https://gitlab.redox-os.org/redox-os/small", features = ["std"] } diff --git a/members/ranges/src/lib.rs b/members/ranges/src/lib.rs index c2b5997ab7903f9ab10e5d91d4a7b4dc5574839b..730a0dc341ec74ceb2fe2884477762aa1f7d7e61 100644 --- a/members/ranges/src/lib.rs +++ b/members/ranges/src/lib.rs @@ -1,4 +1,4 @@ -extern crate smallstring; +extern crate small; mod index; mod parse; @@ -65,150 +65,150 @@ mod tests { panic!("parse_range() failed"); } - let actual: Vec<String> = parse_range("-3...3").unwrap().collect(); - let expected: Vec<String> = vec![ - "-3".to_owned(), - "-2".to_owned(), - "-1".to_owned(), - "0".to_owned(), - "1".to_owned(), - "2".to_owned(), - "3".to_owned(), + let actual: Vec<small::String> = parse_range("-3...3").unwrap().collect(); + let expected: Vec<small::String> = vec![ + "-3".into(), + "-2".into(), + "-1".into(), + "0".into(), + "1".into(), + "2".into(), + "3".into(), ]; assert_eq!(actual, expected); - let actual: Vec<String> = parse_range("07...12").unwrap().collect(); - let expected: Vec<String> = vec![ - "07".to_owned(), - "08".to_owned(), - "09".to_owned(), - "10".to_owned(), - "11".to_owned(), - "12".to_owned(), + let actual: Vec<small::String> = parse_range("07...12").unwrap().collect(); + let expected: Vec<small::String> = vec![ + "07".into(), + "08".into(), + "09".into(), + "10".into(), + "11".into(), + "12".into(), ]; assert_eq!(actual, expected); - let actual: Vec<String> = parse_range("-3...10").unwrap().collect(); - let expected: Vec<String> = vec![ - "-3".to_owned(), - "-2".to_owned(), - "-1".to_owned(), - "0".to_owned(), - "1".to_owned(), - "2".to_owned(), - "3".to_owned(), - "4".to_owned(), - "5".to_owned(), - "6".to_owned(), - "7".to_owned(), - "8".to_owned(), - "9".to_owned(), - "10".to_owned(), + let actual: Vec<small::String> = parse_range("-3...10").unwrap().collect(); + let expected: Vec<small::String> = vec![ + "-3".into(), + "-2".into(), + "-1".into(), + "0".into(), + "1".into(), + "2".into(), + "3".into(), + "4".into(), + "5".into(), + "6".into(), + "7".into(), + "8".into(), + "9".into(), + "10".into(), ]; assert_eq!(actual, expected); - let actual: Vec<String> = parse_range("3...-3").unwrap().collect(); - let expected: Vec<String> = vec![ - "3".to_owned(), - "2".to_owned(), - "1".to_owned(), - "0".to_owned(), - "-1".to_owned(), - "-2".to_owned(), - "-3".to_owned(), + let actual: Vec<small::String> = parse_range("3...-3").unwrap().collect(); + let expected: Vec<small::String> = vec![ + "3".into(), + "2".into(), + "1".into(), + "0".into(), + "-1".into(), + "-2".into(), + "-3".into(), ]; assert_eq!(actual, expected); - let actual: Vec<String> = parse_range("03...-3").unwrap().collect(); - let expected: Vec<String> = vec![ - "03".to_owned(), - "02".to_owned(), - "01".to_owned(), - "00".to_owned(), - "-1".to_owned(), - "-2".to_owned(), - "-3".to_owned(), + let actual: Vec<small::String> = parse_range("03...-3").unwrap().collect(); + let expected: Vec<small::String> = vec![ + "03".into(), + "02".into(), + "01".into(), + "00".into(), + "-1".into(), + "-2".into(), + "-3".into(), ]; assert_eq!(actual, expected); - let actual: Vec<String> = parse_range("3...-03").unwrap().collect(); - let expected: Vec<String> = vec![ - "003".to_owned(), - "002".to_owned(), - "001".to_owned(), - "000".to_owned(), - "-01".to_owned(), - "-02".to_owned(), - "-03".to_owned(), + let actual: Vec<small::String> = parse_range("3...-03").unwrap().collect(); + let expected: Vec<small::String> = vec![ + "003".into(), + "002".into(), + "001".into(), + "000".into(), + "-01".into(), + "-02".into(), + "-03".into(), ]; assert_eq!(actual, expected); - let actual: Vec<String> = parse_range("a...c").unwrap().collect(); - let expected: Vec<String> = vec!["a".to_owned(), "b".to_owned(), "c".to_owned()]; + let actual: Vec<small::String> = parse_range("a...c").unwrap().collect(); + let expected: Vec<small::String> = vec!["a".into(), "b".into(), "c".into()]; assert_eq!(actual, expected); - let actual: Vec<String> = parse_range("c...a").unwrap().collect(); - let expected: Vec<String> = vec!["c".to_owned(), "b".to_owned(), "a".to_owned()]; + let actual: Vec<small::String> = parse_range("c...a").unwrap().collect(); + let expected: Vec<small::String> = vec!["c".into(), "b".into(), "a".into()]; assert_eq!(actual, expected); - let actual: Vec<String> = parse_range("A...C").unwrap().collect(); - let expected: Vec<String> = vec!["A".to_owned(), "B".to_owned(), "C".to_owned()]; + let actual: Vec<small::String> = parse_range("A...C").unwrap().collect(); + let expected: Vec<small::String> = vec!["A".into(), "B".into(), "C".into()]; assert_eq!(actual, expected); - let actual: Vec<String> = parse_range("C...A").unwrap().collect(); - let expected: Vec<String> = vec!["C".to_owned(), "B".to_owned(), "A".to_owned()]; + let actual: Vec<small::String> = parse_range("C...A").unwrap().collect(); + let expected: Vec<small::String> = vec!["C".into(), "B".into(), "A".into()]; assert_eq!(actual, expected); - let actual: Vec<String> = parse_range("C..A").unwrap().collect(); - let expected: Vec<String> = vec!["C".to_owned(), "B".to_owned()]; + let actual: Vec<small::String> = parse_range("C..A").unwrap().collect(); + let expected: Vec<small::String> = vec!["C".into(), "B".into()]; assert_eq!(actual, expected); - let actual: Vec<String> = parse_range("c..a").unwrap().collect(); - let expected: Vec<String> = vec!["c".to_owned(), "b".to_owned()]; + let actual: Vec<small::String> = parse_range("c..a").unwrap().collect(); + let expected: Vec<small::String> = vec!["c".into(), "b".into()]; assert_eq!(actual, expected); - let actual: Vec<String> = parse_range("-3..4").unwrap().collect(); - let expected: Vec<String> = vec![ - "-3".to_owned(), - "-2".to_owned(), - "-1".to_owned(), - "0".to_owned(), - "1".to_owned(), - "2".to_owned(), - "3".to_owned(), + let actual: Vec<small::String> = parse_range("-3..4").unwrap().collect(); + let expected: Vec<small::String> = vec![ + "-3".into(), + "-2".into(), + "-1".into(), + "0".into(), + "1".into(), + "2".into(), + "3".into(), ]; assert_eq!(actual, expected); - let actual: Vec<String> = parse_range("3..-4").unwrap().collect(); - let expected: Vec<String> = vec![ - "3".to_owned(), - "2".to_owned(), - "1".to_owned(), - "0".to_owned(), - "-1".to_owned(), - "-2".to_owned(), - "-3".to_owned(), + let actual: Vec<small::String> = parse_range("3..-4").unwrap().collect(); + let expected: Vec<small::String> = vec![ + "3".into(), + "2".into(), + "1".into(), + "0".into(), + "-1".into(), + "-2".into(), + "-3".into(), ]; assert_eq!(actual, expected); - let actual: Vec<String> = parse_range("-3...0").unwrap().collect(); - let expected: Vec<String> = vec!["-3".into(), "-2".into(), "-1".into(), "0".into()]; + let actual: Vec<small::String> = parse_range("-3...0").unwrap().collect(); + let expected: Vec<small::String> = vec!["-3".into(), "-2".into(), "-1".into(), "0".into()]; assert_eq!(actual, expected); - let actual: Vec<String> = parse_range("-3..0").unwrap().collect(); - let expected: Vec<String> = vec!["-3".into(), "-2".into(), "-1".into()]; + let actual: Vec<small::String> = parse_range("-3..0").unwrap().collect(); + let expected: Vec<small::String> = vec!["-3".into(), "-2".into(), "-1".into()]; assert_eq!(actual, expected); } } diff --git a/members/ranges/src/parse.rs b/members/ranges/src/parse.rs index de7312a28398ced2a21b5362828a2f8cc4b701d1..5d36191001ffb6b6b0229e9c0dc4f131f9dc7774 100644 --- a/members/ranges/src/parse.rs +++ b/members/ranges/src/parse.rs @@ -1,4 +1,5 @@ use super::{Index, Range}; +use small; use std::cmp::Ordering; fn stepped_range_numeric<'a>( @@ -6,7 +7,7 @@ fn stepped_range_numeric<'a>( end: isize, step: isize, nb_digits: usize, -) -> Option<Box<Iterator<Item = String> + 'a>> { +) -> Option<Box<Iterator<Item = small::String> + 'a>> { if step == 0 { None } else if start < end && step < 0 { @@ -24,7 +25,7 @@ fn stepped_range_numeric<'a>( if end.cmp(index) == ordering { let index_holder = *index; *index += step; // This step adds - Some(format!("{:0width$}", index_holder, width = nb_digits)) + Some(format!("{:0width$}", index_holder, width = nb_digits).into()) } else { None } @@ -38,7 +39,7 @@ fn stepped_range_chars<'a>( start: u8, end: u8, step: u8, -) -> Option<Box<Iterator<Item = String> + 'a>> { +) -> Option<Box<Iterator<Item = small::String> + 'a>> { if step == 0 { None } else { @@ -56,7 +57,7 @@ fn stepped_range_chars<'a>( Ordering::Less => index.wrapping_sub(step), _ => unreachable!(), }; - Some((index_holder as char).to_string()) + Some((index_holder as char).to_string().into()) } else { None } @@ -72,7 +73,7 @@ fn numeric_range<'a>( step: isize, inclusive: bool, nb_digits: usize, -) -> Option<Box<Iterator<Item = String> + 'a>> { +) -> Option<Box<Iterator<Item = small::String> + 'a>> { if start < end { if inclusive { end += 1; @@ -84,7 +85,7 @@ fn numeric_range<'a>( } stepped_range_numeric(start, end, step, nb_digits) } else { - Some(Box::new(Some(start.to_string()).into_iter())) + Some(Box::new(Some(start.to_string().into()).into_iter())) } } @@ -97,7 +98,7 @@ fn char_range<'a>( mut end: u8, step: isize, inclusive: bool, -) -> Option<Box<Iterator<Item = String> + 'a>> { +) -> Option<Box<Iterator<Item = small::String> + 'a>> { if !byte_is_valid_range(start) || !byte_is_valid_range(end) { return None; } @@ -121,7 +122,7 @@ fn char_range<'a>( } stepped_range_chars(start, end, char_step) } else { - Some(Box::new(Some((start as char).to_string()).into_iter())) + Some(Box::new(Some((start as char).to_string().into()).into_iter())) } } @@ -163,7 +164,7 @@ fn strings_to_isizes(a: &str, b: &str) -> Option<(isize, isize, usize)> { // Inclusive nonstepped: {start...end} // Exclusive stepped: {start..step..end} // Inclusive stepped: {start..step...end} -pub fn parse_range<'a>(input: &str) -> Option<Box<Iterator<Item = String> + 'a>> { +pub fn parse_range<'a>(input: &str) -> Option<Box<Iterator<Item = small::String> + 'a>> { let mut read = 0; let mut bytes_iterator = input.bytes(); while let Some(byte) = bytes_iterator.next() { diff --git a/members/ranges/src/select.rs b/members/ranges/src/select.rs index 083f1e7898b1382d39f9e7008ee0d0f834339e13..d5b98055066e4e7cb255bed19f434ab788ab5f9c 100644 --- a/members/ranges/src/select.rs +++ b/members/ranges/src/select.rs @@ -1,5 +1,5 @@ use super::{parse_index_range, Index, Range}; -use smallstring::SmallString; +use small; use std::{ iter::{empty, FromIterator}, str::FromStr, @@ -17,7 +17,7 @@ pub enum Select { /// Select a range of elements Range(Range), /// Select an element by mapped key - Key(SmallString), + Key(small::String), } pub trait SelectWithSize { diff --git a/src/lib/builtins/command_info.rs b/src/lib/builtins/command_info.rs index 9892bff392cfbf096dade907a3566a27e3a5614f..b6a124241fa00002871f32dce83049e011108268 100644 --- a/src/lib/builtins/command_info.rs +++ b/src/lib/builtins/command_info.rs @@ -1,11 +1,12 @@ use builtins::man_pages::*; use shell::{status::*, flow_control::Function, Shell}; +use small; use sys; use types; use std::{borrow::Cow, env, path::Path}; -pub(crate) fn which(args: &[String], shell: &mut Shell) -> Result<i32, ()> { +pub(crate) fn which(args: &[small::String], shell: &mut Shell) -> Result<i32, ()> { if check_help(args, MAN_WHICH) { return Ok(SUCCESS); } @@ -33,7 +34,7 @@ pub(crate) fn which(args: &[String], shell: &mut Shell) -> Result<i32, ()> { Ok(result) } -pub(crate) fn find_type(args: &[String], shell: &mut Shell) -> Result<i32, ()> { +pub(crate) fn find_type(args: &[small::String], shell: &mut Shell) -> Result<i32, ()> { // Type does not accept help flags, aka "--help". if args.len() == 1 { eprintln!("type: Expected at least 1 args, got only 0"); diff --git a/src/lib/builtins/exec.rs b/src/lib/builtins/exec.rs index eef34dfd75e54d60c061f45aa72512e4c5db2bcd..b91593e960a5c279c7f2bc051bdd9af3af58ccb5 100644 --- a/src/lib/builtins/exec.rs +++ b/src/lib/builtins/exec.rs @@ -1,10 +1,11 @@ use builtins::man_pages::{check_help, MAN_EXEC}; +use small; use shell::Shell; use std::error::Error; use sys::execve; /// Executes the givent commmand. -pub(crate) fn exec(shell: &mut Shell, args: &[String]) -> Result<(), String> { +pub(crate) fn exec(shell: &mut Shell, args: &[small::String]) -> Result<(), small::String> { const CLEAR_ENV: u8 = 1; let mut flags = 0u8; @@ -30,8 +31,8 @@ pub(crate) fn exec(shell: &mut Shell, args: &[String]) -> Result<(), String> { shell.prep_for_exit(); Err(execve(argument, args, (flags & CLEAR_ENV) == 1) .description() - .to_owned()) + .into()) } - None => Err("no command provided".to_owned()), + None => Err("no command provided".into()), } } diff --git a/src/lib/builtins/exists.rs b/src/lib/builtins/exists.rs index e555196d5f97e7067c800dc321047139c0cf8025..fcd166185f4087c5011d300161b1ce43281acdfb 100644 --- a/src/lib/builtins/exists.rs +++ b/src/lib/builtins/exists.rs @@ -1,5 +1,3 @@ -#[cfg(test)] -use smallstring::SmallString; use std::{fs, os::unix::fs::PermissionsExt}; #[cfg(test)] @@ -11,14 +9,15 @@ use shell::{ flow_control::Function, Shell, }; +use small; use types; -pub(crate) fn exists(args: &[String], shell: &Shell) -> Result<bool, String> { +pub(crate) fn exists(args: &[small::String], shell: &Shell) -> Result<bool, small::String> { let arguments = &args[1..]; evaluate_arguments(arguments, shell) } -fn evaluate_arguments(arguments: &[String], shell: &Shell) -> Result<bool, String> { +fn evaluate_arguments(arguments: &[small::String], shell: &Shell) -> Result<bool, small::String> { match arguments.first() { Some(ref s) if s.starts_with("--") => { let (_, option) = s.split_at(2); @@ -90,7 +89,7 @@ fn binary_is_in_path(binaryname: &str, shell: &Shell) -> bool { // TODO: Right now they use an entirely different logic which means that it // *might* be possible TODO: that `exists` reports a binary to be in the // path, while the shell cannot find it or TODO: vice-versa - if let Some(path) = shell.get::<types::Value>("PATH") { + if let Some(path) = shell.get::<types::Str>("PATH") { for dir in path.split(':') { let fname = format!("{}/{}", dir, binaryname); if let Ok(metadata) = fs::metadata(&fname) { @@ -134,7 +133,7 @@ fn array_var_is_not_empty(arrayvar: &str, shell: &Shell) -> bool { /// Returns true if the variable is a string and the string is not empty fn string_var_is_not_empty(stringvar: &str, shell: &Shell) -> bool { - match shell.variables.get::<types::Value>(stringvar) { + match shell.variables.get::<types::Str>(stringvar) { Some(string) => !string.is_empty(), None => false, } @@ -158,42 +157,42 @@ fn test_evaluate_arguments() { assert_eq!(evaluate_arguments(&[], &shell), Ok(false)); // multiple arguments // ignores all but the first argument - assert_eq!(evaluate_arguments(&["foo".to_owned(), "bar".to_owned()], &shell), Ok(true)); + assert_eq!(evaluate_arguments(&["foo".into(), "bar".into()], &shell), Ok(true)); // check `exists STRING` - assert_eq!(evaluate_arguments(&["".to_owned()], &shell), Ok(false)); - assert_eq!(evaluate_arguments(&["string".to_owned()], &shell), Ok(true)); - assert_eq!(evaluate_arguments(&["string with space".to_owned()], &shell), Ok(true)); - assert_eq!(evaluate_arguments(&["-startswithdash".to_owned()], &shell), Ok(true)); + assert_eq!(evaluate_arguments(&["".into()], &shell), Ok(false)); + assert_eq!(evaluate_arguments(&["string".into()], &shell), Ok(true)); + assert_eq!(evaluate_arguments(&["string with space".into()], &shell), Ok(true)); + assert_eq!(evaluate_arguments(&["-startswithdash".into()], &shell), Ok(true)); // check `exists -a` // no argument means we treat it as a string - assert_eq!(evaluate_arguments(&["-a".to_owned()], &shell), Ok(true)); + assert_eq!(evaluate_arguments(&["-a".into()], &shell), Ok(true)); shell .variables .set("emptyarray", types::Array::new()); - assert_eq!(evaluate_arguments(&["-a".to_owned(), "emptyarray".to_owned()], &shell), Ok(false)); + assert_eq!(evaluate_arguments(&["-a".into(), "emptyarray".into()], &shell), Ok(false)); let mut array = types::Array::new(); - array.push("element".to_owned()); + array.push("element".into()); shell.variables.set("array", array); - assert_eq!(evaluate_arguments(&["-a".to_owned(), "array".to_owned()], &shell), Ok(true)); + assert_eq!(evaluate_arguments(&["-a".into(), "array".into()], &shell), Ok(true)); shell.variables.remove_variable("array"); - assert_eq!(evaluate_arguments(&["-a".to_owned(), "array".to_owned()], &shell), Ok(false)); + assert_eq!(evaluate_arguments(&["-a".into(), "array".into()], &shell), Ok(false)); // check `exists -b` // TODO: see test_binary_is_in_path() // no argument means we treat it as a string - assert_eq!(evaluate_arguments(&["-b".to_owned()], &shell), Ok(true)); - let oldpath = shell.get::<types::Value>("PATH").unwrap_or("/usr/bin".to_owned()); - shell.set("PATH", "testing/".to_string()); + assert_eq!(evaluate_arguments(&["-b".into()], &shell), Ok(true)); + let oldpath = shell.get::<types::Str>("PATH").unwrap_or("/usr/bin".into()); + shell.set("PATH", "testing/"); assert_eq!( - evaluate_arguments(&["-b".to_owned(), "executable_file".to_owned()], &shell), + evaluate_arguments(&["-b".into(), "executable_file".into()], &shell), Ok(true) ); - assert_eq!(evaluate_arguments(&["-b".to_owned(), "empty_file".to_owned()], &shell), Ok(false)); + assert_eq!(evaluate_arguments(&["-b".into(), "empty_file".into()], &shell), Ok(false)); assert_eq!( - evaluate_arguments(&["-b".to_owned(), "file_does_not_exist".to_owned()], &shell), + evaluate_arguments(&["-b".into(), "file_does_not_exist".into()], &shell), Ok(false) ); @@ -203,49 +202,49 @@ fn test_evaluate_arguments() { // check `exists -d` // no argument means we treat it as a string - assert_eq!(evaluate_arguments(&["-d".to_owned()], &shell), Ok(true)); - assert_eq!(evaluate_arguments(&["-d".to_owned(), "testing/".to_owned()], &shell), Ok(true)); + assert_eq!(evaluate_arguments(&["-d".into()], &shell), Ok(true)); + assert_eq!(evaluate_arguments(&["-d".into(), "testing/".into()], &shell), Ok(true)); assert_eq!( - evaluate_arguments(&["-d".to_owned(), "testing/empty_file".to_owned()], &shell), + evaluate_arguments(&["-d".into(), "testing/empty_file".into()], &shell), Ok(false) ); assert_eq!( - evaluate_arguments(&["-d".to_owned(), "does/not/exist/".to_owned()], &shell), + evaluate_arguments(&["-d".into(), "does/not/exist/".into()], &shell), Ok(false) ); // check `exists -f` // no argument means we treat it as a string - assert_eq!(evaluate_arguments(&["-f".to_owned()], &shell), Ok(true)); - assert_eq!(evaluate_arguments(&["-f".to_owned(), "testing/".to_owned()], &shell), Ok(false)); + assert_eq!(evaluate_arguments(&["-f".into()], &shell), Ok(true)); + assert_eq!(evaluate_arguments(&["-f".into(), "testing/".into()], &shell), Ok(false)); assert_eq!( - evaluate_arguments(&["-f".to_owned(), "testing/empty_file".to_owned()], &shell), + evaluate_arguments(&["-f".into(), "testing/empty_file".into()], &shell), Ok(true) ); assert_eq!( - evaluate_arguments(&["-f".to_owned(), "does-not-exist".to_owned()], &shell), + evaluate_arguments(&["-f".into(), "does-not-exist".into()], &shell), Ok(false) ); // check `exists -s` // no argument means we treat it as a string - assert_eq!(evaluate_arguments(&["-s".to_owned()], &shell), Ok(true)); + assert_eq!(evaluate_arguments(&["-s".into()], &shell), Ok(true)); shell.set("emptyvar", "".to_string()); - assert_eq!(evaluate_arguments(&["-s".to_owned(), "emptyvar".to_owned()], &shell), Ok(false)); + assert_eq!(evaluate_arguments(&["-s".into(), "emptyvar".into()], &shell), Ok(false)); shell.set("testvar", "foobar".to_string()); - assert_eq!(evaluate_arguments(&["-s".to_owned(), "testvar".to_owned()], &shell), Ok(true)); + assert_eq!(evaluate_arguments(&["-s".into(), "testvar".into()], &shell), Ok(true)); shell.variables.remove_variable("testvar"); - assert_eq!(evaluate_arguments(&["-s".to_owned(), "testvar".to_owned()], &shell), Ok(false)); + assert_eq!(evaluate_arguments(&["-s".into(), "testvar".into()], &shell), Ok(false)); // also check that it doesn't trigger on arrays let mut array = types::Array::new(); - array.push("element".to_owned()); + array.push("element".into()); shell.variables.remove_variable("array"); shell.variables.set("array", array); - assert_eq!(evaluate_arguments(&["-s".to_owned(), "array".to_owned()], &shell), Ok(false)); + assert_eq!(evaluate_arguments(&["-s".into(), "array".into()], &shell), Ok(false)); // check `exists --fn` let name_str = "test_function"; - let name = SmallString::from_str(name_str); + let name = small::String::from(name_str); let mut args = Vec::new(); args.push(KeyBuf { name: "testy".into(), @@ -253,21 +252,21 @@ fn test_evaluate_arguments() { }); let mut statements = Vec::new(); statements.push(Statement::End); - let description = "description".to_owned(); + let description: small::String = "description".into(); shell.variables.set( &name, Function::new(Some(description), name.clone(), args, statements), ); - assert_eq!(evaluate_arguments(&["--fn".to_owned(), name_str.to_owned()], &shell), Ok(true)); + assert_eq!(evaluate_arguments(&["--fn".into(), name_str.into()], &shell), Ok(true)); shell.variables.remove_variable(name_str); - assert_eq!(evaluate_arguments(&["--fn".to_owned(), name_str.to_owned()], &shell), Ok(false)); + assert_eq!(evaluate_arguments(&["--fn".into(), name_str.into()], &shell), Ok(false)); // check invalid flags / parameters (should all be treated as strings and // therefore succeed) - assert_eq!(evaluate_arguments(&["--foo".to_owned()], &shell), Ok(true)); - assert_eq!(evaluate_arguments(&["-x".to_owned()], &shell), Ok(true)); + assert_eq!(evaluate_arguments(&["--foo".into()], &shell), Ok(true)); + assert_eq!(evaluate_arguments(&["-x".into()], &shell), Ok(true)); } #[test] @@ -367,7 +366,7 @@ fn test_array_var_is_not_empty() { assert_eq!(array_var_is_not_empty("EMPTY_ARRAY", &shell), false); let mut not_empty_array = types::Array::new(); - not_empty_array.push("array not empty".to_owned()); + not_empty_array.push("array not empty".into()); shell.variables.set("NOT_EMPTY_ARRAY", not_empty_array); assert_eq!(array_var_is_not_empty("NOT_EMPTY_ARRAY", &shell), true); @@ -377,7 +376,7 @@ fn test_array_var_is_not_empty() { // array_var_is_not_empty should NOT match for non-array variables with the // same name - shell.set("VARIABLE", "notempty-variable".to_string()); + shell.set("VARIABLE", "notempty-variable"); assert_eq!(array_var_is_not_empty("VARIABLE", &shell), false); } @@ -385,15 +384,15 @@ fn test_array_var_is_not_empty() { fn test_string_var_is_not_empty() { let mut shell = shell::ShellBuilder::new().as_library(); - shell.set("EMPTY", "".to_string()); + shell.set("EMPTY", ""); assert_eq!(string_var_is_not_empty("EMPTY", &shell), false); - shell.set("NOT_EMPTY", "notempty".to_string()); + shell.set("NOT_EMPTY", "notempty"); assert_eq!(string_var_is_not_empty("NOT_EMPTY", &shell), true); // string_var_is_not_empty should NOT match for arrays with the same name let mut array = types::Array::new(); - array.push("not-empty".to_owned()); + array.push("not-empty".into()); shell.variables.set("ARRAY_NOT_EMPTY", array); assert_eq!(string_var_is_not_empty("ARRAY_NOT_EMPTY", &shell), false); @@ -409,7 +408,7 @@ fn test_function_is_defined() { // create a simple dummy function let name_str = "test_function"; - let name = SmallString::from_str(name_str); + let name: small::String = name_str.into(); let mut args = Vec::new(); args.push(KeyBuf { name: "testy".into(), @@ -417,7 +416,7 @@ fn test_function_is_defined() { }); let mut statements = Vec::new(); statements.push(Statement::End); - let description = "description".to_owned(); + let description: small::String = "description".into(); shell.variables.set( &name, diff --git a/src/lib/builtins/is.rs b/src/lib/builtins/is.rs index b191e970870577eda4332702bf8edeacee49d01d..5712753b86a349497d31fa5ac94a0c949c65678c 100644 --- a/src/lib/builtins/is.rs +++ b/src/lib/builtins/is.rs @@ -1,7 +1,8 @@ use shell::Shell; use types; +use small; -pub(crate) fn is(args: &[String], shell: &mut Shell) -> Result<(), String> { +pub(crate) fn is(args: &[small::String], shell: &mut Shell) -> Result<(), String> { match args.len() { 4 => if args[1] != "not" { return Err(format!("Expected 'not' instead found '{}'\n", args[1]).to_string()); @@ -17,35 +18,35 @@ pub(crate) fn is(args: &[String], shell: &mut Shell) -> Result<(), String> { Ok(()) } -fn eval_arg(arg: &str, shell: &mut Shell) -> String { +fn eval_arg(arg: &str, shell: &mut Shell) -> types::Str { let value = get_var_string(arg, shell); - if value != "" { + if &*value != "" { return value; } - arg.to_string() + arg.into() } // On error returns an empty String. -fn get_var_string(name: &str, shell: &mut Shell) -> String { +fn get_var_string(name: &str, shell: &mut Shell) -> types::Str { if name.chars().nth(0).unwrap() != '$' { - return String::new(); + return "".into(); } - match shell.variables.get::<types::Value>(&name[1..]) { + match shell.variables.get::<types::Str>(&name[1..]) { Some(s) => s, - None => String::new(), + None => "".into(), } } #[test] fn test_is() { - fn vec_string(args: &[&str]) -> Vec<String> { - args.iter().map(|s| (*s).to_owned()).collect::<Vec<String>>() + fn vec_string(args: &[&str]) -> Vec<small::String> { + args.iter().map(|s| (*s).into()).collect() } use shell::ShellBuilder; let mut shell = ShellBuilder::new().as_library(); - shell.set("x", "value".to_string()); - shell.set("y", "0".to_string()); + shell.set("x", "value"); + shell.set("y", "0"); // Four arguments assert_eq!( diff --git a/src/lib/builtins/job_control.rs b/src/lib/builtins/job_control.rs index 423ca273a91f3b36f3650e283723547887c9aa84..ed318b130646882148ef8a42a7f28315d3cc9fd6 100644 --- a/src/lib/builtins/job_control.rs +++ b/src/lib/builtins/job_control.rs @@ -4,12 +4,13 @@ use shell::{ job_control::{JobControl, ProcessState}, signals, status::*, Shell, }; +use small; use smallvec::SmallVec; /// Disowns given process job IDs, and optionally marks jobs to not receive SIGHUP signals. /// The `-a` flag selects all jobs, `-r` selects all running jobs, and `-h` specifies to mark /// SIGHUP ignoral. -pub(crate) fn disown(shell: &mut Shell, args: &[String]) -> Result<(), String> { +pub(crate) fn disown(shell: &mut Shell, args: &[small::String]) -> Result<(), String> { // Specifies that a process should be set to not receive SIGHUP signals. const NO_SIGHUP: u8 = 1; // Specifies that all jobs in the process table should be manipulated. @@ -97,7 +98,7 @@ pub(crate) fn jobs(shell: &mut Shell) { /// Hands control of the foreground process to the specified jobs, recording their exit status. /// If the job is stopped, the job will be resumed. /// If multiple jobs are given, then only the last job's exit status will be returned. -pub(crate) fn fg(shell: &mut Shell, args: &[String]) -> i32 { +pub(crate) fn fg(shell: &mut Shell, args: &[small::String]) -> i32 { fn fg_job(shell: &mut Shell, njob: u32) -> i32 { let job = if let Some(borrowed_job) = shell.background.lock().unwrap().iter().nth(njob as usize) @@ -146,7 +147,7 @@ pub(crate) fn fg(shell: &mut Shell, args: &[String]) -> i32 { } /// Resumes a stopped background process, if it was stopped. -pub(crate) fn bg(shell: &mut Shell, args: &[String]) -> i32 { +pub(crate) fn bg(shell: &mut Shell, args: &[small::String]) -> i32 { fn bg_job(shell: &mut Shell, njob: u32) -> bool { if let Some(job) = shell .background diff --git a/src/lib/builtins/man_pages.rs b/src/lib/builtins/man_pages.rs index b0cabcd76700f92773d2f9bd622dafe109308a37..33a93f5c8f49f5d944fc998530e3e2b501f2c535 100644 --- a/src/lib/builtins/man_pages.rs +++ b/src/lib/builtins/man_pages.rs @@ -1,6 +1,8 @@ -pub(crate) fn check_help(args: &[String], man_page: &'static str) -> bool { +use small; + +pub(crate) fn check_help(args: &[small::String], man_page: &'static str) -> bool { for arg in args { - if &**arg == "-h" || &**arg == "--help" { + if arg == "-h" || arg == "--help" { println!("{}", man_page); return true; } diff --git a/src/lib/builtins/mod.rs b/src/lib/builtins/mod.rs index a482b9d8d0762c47dcf1b0611ff7e97c541abac5..7d6d63939d817a3d47da69a6794eb391927e2965 100644 --- a/src/lib/builtins/mod.rs +++ b/src/lib/builtins/mod.rs @@ -26,6 +26,7 @@ use shell::{ self, fork_function::fork_function, job_control::{JobControl, ProcessState}, status::*, FlowLogic, Shell, ShellHistory, }; +use small; use sys; use types; @@ -37,7 +38,7 @@ const SOURCE_DESC: &str = "Evaluate the file following the command or re-initial const DISOWN_DESC: &str = "Disowning a process removes that process from the shell's background process table."; -pub type BuiltinFunction = fn(&[String], &mut Shell) -> i32; +pub type BuiltinFunction = fn(&[small::String], &mut Shell) -> i32; macro_rules! map { ($($name:expr => $func:ident: $help:expr),+) => {{ @@ -130,12 +131,12 @@ impl BuiltinMap { } } -fn starts_with(args: &[String], _: &mut Shell) -> i32 { conditionals::starts_with(args) } -fn ends_with(args: &[String], _: &mut Shell) -> i32 { conditionals::ends_with(args) } -fn contains(args: &[String], _: &mut Shell) -> i32 { conditionals::contains(args) } +fn starts_with(args: &[small::String], _: &mut Shell) -> i32 { conditionals::starts_with(args) } +fn ends_with(args: &[small::String], _: &mut Shell) -> i32 { conditionals::ends_with(args) } +fn contains(args: &[small::String], _: &mut Shell) -> i32 { conditionals::contains(args) } // Definitions of simple builtins go here -fn builtin_status(args: &[String], shell: &mut Shell) -> i32 { +fn builtin_status(args: &[small::String], shell: &mut Shell) -> i32 { match status(args, shell) { Ok(()) => SUCCESS, Err(why) => { @@ -147,7 +148,7 @@ fn builtin_status(args: &[String], shell: &mut Shell) -> i32 { } } -pub fn builtin_cd(args: &[String], shell: &mut Shell) -> i32 { +pub fn builtin_cd(args: &[small::String], shell: &mut Shell) -> i32 { if check_help(args, MAN_CD) { return SUCCESS; } @@ -164,7 +165,7 @@ pub fn builtin_cd(args: &[String], shell: &mut Shell) -> i32 { } } -fn builtin_bool(args: &[String], shell: &mut Shell) -> i32 { +fn builtin_bool(args: &[small::String], shell: &mut Shell) -> i32 { if args.len() != 2 { let stderr = io::stderr(); let mut stderr = stderr.lock(); @@ -172,7 +173,7 @@ fn builtin_bool(args: &[String], shell: &mut Shell) -> i32 { return FAILURE; } - let opt = shell.variables.get::<types::Value>(&args[1][1..]); + let opt = shell.variables.get::<types::Str>(&args[1][1..]); let sh_var: &str = match opt.as_ref() { Some(s) => s, None => "", @@ -192,7 +193,7 @@ fn builtin_bool(args: &[String], shell: &mut Shell) -> i32 { SUCCESS } -fn builtin_is(args: &[String], shell: &mut Shell) -> i32 { +fn builtin_is(args: &[small::String], shell: &mut Shell) -> i32 { if check_help(args, MAN_IS) { return SUCCESS; } @@ -208,7 +209,7 @@ fn builtin_is(args: &[String], shell: &mut Shell) -> i32 { } } -fn builtin_dirs(args: &[String], shell: &mut Shell) -> i32 { +fn builtin_dirs(args: &[small::String], shell: &mut Shell) -> i32 { if check_help(args, MAN_DIRS) { return SUCCESS; } @@ -216,7 +217,7 @@ fn builtin_dirs(args: &[String], shell: &mut Shell) -> i32 { shell.directory_stack.dirs(args) } -fn builtin_pushd(args: &[String], shell: &mut Shell) -> i32 { +fn builtin_pushd(args: &[small::String], shell: &mut Shell) -> i32 { if check_help(args, MAN_PUSHD) { return SUCCESS; } @@ -231,7 +232,7 @@ fn builtin_pushd(args: &[String], shell: &mut Shell) -> i32 { } } -fn builtin_popd(args: &[String], shell: &mut Shell) -> i32 { +fn builtin_popd(args: &[small::String], shell: &mut Shell) -> i32 { if check_help(args, MAN_POPD) { return SUCCESS; } @@ -246,27 +247,27 @@ fn builtin_popd(args: &[String], shell: &mut Shell) -> i32 { } } -fn builtin_alias(args: &[String], shell: &mut Shell) -> i32 { +fn builtin_alias(args: &[small::String], shell: &mut Shell) -> i32 { let args_str = args[1..].join(" "); alias(&mut shell.variables, &args_str) } -fn builtin_unalias(args: &[String], shell: &mut Shell) -> i32 { +fn builtin_unalias(args: &[small::String], shell: &mut Shell) -> i32 { drop_alias(&mut shell.variables, args) } // TODO There is a man page for fn however the -h and --help flags are not // checked for. -fn builtin_fn(_: &[String], shell: &mut Shell) -> i32 { fn_(&mut shell.variables) } +fn builtin_fn(_: &[small::String], shell: &mut Shell) -> i32 { fn_(&mut shell.variables) } -fn builtin_read(args: &[String], shell: &mut Shell) -> i32 { +fn builtin_read(args: &[small::String], shell: &mut Shell) -> i32 { if check_help(args, MAN_READ) { return SUCCESS; } shell.variables.read(args) } -fn builtin_drop(args: &[String], shell: &mut Shell) -> i32 { +fn builtin_drop(args: &[small::String], shell: &mut Shell) -> i32 { if check_help(args, MAN_DROP) { return SUCCESS; } @@ -277,14 +278,14 @@ fn builtin_drop(args: &[String], shell: &mut Shell) -> i32 { } } -fn builtin_set(args: &[String], shell: &mut Shell) -> i32 { +fn builtin_set(args: &[small::String], shell: &mut Shell) -> i32 { if check_help(args, MAN_SET) { return SUCCESS; } set::set(args, shell) } -fn builtin_eq(args: &[String], shell: &mut Shell) -> i32 { +fn builtin_eq(args: &[small::String], shell: &mut Shell) -> i32 { if check_help(args, MAN_EQ) { return SUCCESS; } @@ -300,7 +301,7 @@ fn builtin_eq(args: &[String], shell: &mut Shell) -> i32 { } } -fn builtin_eval(args: &[String], shell: &mut Shell) -> i32 { +fn builtin_eval(args: &[small::String], shell: &mut Shell) -> i32 { if check_help(args, MAN_EVAL) { return SUCCESS; } @@ -315,14 +316,14 @@ fn builtin_eval(args: &[String], shell: &mut Shell) -> i32 { } } -fn builtin_history(args: &[String], shell: &mut Shell) -> i32 { +fn builtin_history(args: &[small::String], shell: &mut Shell) -> i32 { if check_help(args, MAN_HISTORY) { return SUCCESS; } shell.print_history(args) } -fn builtin_source(args: &[String], shell: &mut Shell) -> i32 { +fn builtin_source(args: &[small::String], shell: &mut Shell) -> i32 { if check_help(args, MAN_SOURCE) { return SUCCESS; } @@ -337,7 +338,7 @@ fn builtin_source(args: &[String], shell: &mut Shell) -> i32 { } } -fn builtin_echo(args: &[String], _: &mut Shell) -> i32 { +fn builtin_echo(args: &[small::String], _: &mut Shell) -> i32 { if check_help(args, MAN_ECHO) { return SUCCESS; } @@ -352,7 +353,7 @@ fn builtin_echo(args: &[String], _: &mut Shell) -> i32 { } } -fn builtin_test(args: &[String], _: &mut Shell) -> i32 { +fn builtin_test(args: &[small::String], _: &mut Shell) -> i32 { // Do not use `check_help` for the `test` builtin. The // `test` builtin contains a "-h" option. match test(args) { @@ -366,7 +367,7 @@ fn builtin_test(args: &[String], _: &mut Shell) -> i32 { } // TODO create manpage. -fn builtin_calc(args: &[String], _: &mut Shell) -> i32 { +fn builtin_calc(args: &[small::String], _: &mut Shell) -> i32 { match calc::calc(&args[1..]) { Ok(()) => SUCCESS, Err(why) => { @@ -376,7 +377,7 @@ fn builtin_calc(args: &[String], _: &mut Shell) -> i32 { } } -fn builtin_random(args: &[String], _: &mut Shell) -> i32 { +fn builtin_random(args: &[small::String], _: &mut Shell) -> i32 { if check_help(args, MAN_RANDOM) { return SUCCESS; } @@ -389,12 +390,12 @@ fn builtin_random(args: &[String], _: &mut Shell) -> i32 { } } -fn builtin_true(args: &[String], _: &mut Shell) -> i32 { +fn builtin_true(args: &[small::String], _: &mut Shell) -> i32 { check_help(args, MAN_TRUE); SUCCESS } -fn builtin_false(args: &[String], _: &mut Shell) -> i32 { +fn builtin_false(args: &[small::String], _: &mut Shell) -> i32 { if check_help(args, MAN_FALSE) { return SUCCESS; } @@ -402,32 +403,32 @@ fn builtin_false(args: &[String], _: &mut Shell) -> i32 { } // TODO create a manpage -fn builtin_wait(_: &[String], shell: &mut Shell) -> i32 { +fn builtin_wait(_: &[small::String], shell: &mut Shell) -> i32 { shell.wait_for_background(); SUCCESS } -fn builtin_jobs(args: &[String], shell: &mut Shell) -> i32 { +fn builtin_jobs(args: &[small::String], shell: &mut Shell) -> i32 { check_help(args, MAN_JOBS); job_control::jobs(shell); SUCCESS } -fn builtin_bg(args: &[String], shell: &mut Shell) -> i32 { +fn builtin_bg(args: &[small::String], shell: &mut Shell) -> i32 { if check_help(args, MAN_BG) { return SUCCESS; } job_control::bg(shell, &args[1..]) } -fn builtin_fg(args: &[String], shell: &mut Shell) -> i32 { +fn builtin_fg(args: &[small::String], shell: &mut Shell) -> i32 { if check_help(args, MAN_FG) { return SUCCESS; } job_control::fg(shell, &args[1..]) } -fn builtin_suspend(args: &[String], _: &mut Shell) -> i32 { +fn builtin_suspend(args: &[small::String], _: &mut Shell) -> i32 { if check_help(args, MAN_SUSPEND) { return SUCCESS; } @@ -435,7 +436,7 @@ fn builtin_suspend(args: &[String], _: &mut Shell) -> i32 { SUCCESS } -fn builtin_disown(args: &[String], shell: &mut Shell) -> i32 { +fn builtin_disown(args: &[small::String], shell: &mut Shell) -> i32 { for arg in args { if *arg == "--help" { println!("{}", MAN_DISOWN); @@ -451,7 +452,7 @@ fn builtin_disown(args: &[String], shell: &mut Shell) -> i32 { } } -fn builtin_help(args: &[String], shell: &mut Shell) -> i32 { +fn builtin_help(args: &[small::String], shell: &mut Shell) -> i32 { let builtins = shell.builtins; let stdout = io::stdout(); let mut stdout = stdout.lock(); @@ -477,7 +478,7 @@ fn builtin_help(args: &[String], shell: &mut Shell) -> i32 { SUCCESS } -fn builtin_exit(args: &[String], shell: &mut Shell) -> i32 { +fn builtin_exit(args: &[small::String], shell: &mut Shell) -> i32 { if check_help(args, MAN_EXIT) { return SUCCESS; } @@ -495,7 +496,7 @@ fn builtin_exit(args: &[String], shell: &mut Shell) -> i32 { ) } -fn builtin_exec(args: &[String], shell: &mut Shell) -> i32 { +fn builtin_exec(args: &[small::String], shell: &mut Shell) -> i32 { match exec(shell, &args[1..]) { // Shouldn't ever hit this case. Ok(()) => SUCCESS, @@ -509,7 +510,7 @@ fn builtin_exec(args: &[String], shell: &mut Shell) -> i32 { } use regex::Regex; -fn builtin_matches(args: &[String], _: &mut Shell) -> i32 { +fn builtin_matches(args: &[small::String], _: &mut Shell) -> i32 { if check_help(args, MAN_MATCHES) { return SUCCESS; } @@ -538,7 +539,7 @@ fn builtin_matches(args: &[String], _: &mut Shell) -> i32 { } } -fn builtin_exists(args: &[String], shell: &mut Shell) -> i32 { +fn builtin_exists(args: &[small::String], shell: &mut Shell) -> i32 { if check_help(args, MAN_EXISTS) { return SUCCESS; } @@ -552,21 +553,21 @@ fn builtin_exists(args: &[String], shell: &mut Shell) -> i32 { } } -fn builtin_which(args: &[String], shell: &mut Shell) -> i32 { +fn builtin_which(args: &[small::String], shell: &mut Shell) -> i32 { match which(args, shell) { Ok(result) => result, Err(()) => FAILURE, } } -fn builtin_type(args: &[String], shell: &mut Shell) -> i32 { +fn builtin_type(args: &[small::String], shell: &mut Shell) -> i32 { match find_type(args, shell) { Ok(result) => result, Err(()) => FAILURE, } } -fn builtin_isatty(args: &[String], _: &mut Shell) -> i32 { +fn builtin_isatty(args: &[small::String], _: &mut Shell) -> i32 { if check_help(args, MAN_ISATTY) { return SUCCESS; } diff --git a/src/lib/builtins/set.rs b/src/lib/builtins/set.rs index 98446b69dc98e9db1c115b6aceacb5e0b86c31af..38e41a8e493b9e3212896abd668a7848e18416ea 100644 --- a/src/lib/builtins/set.rs +++ b/src/lib/builtins/set.rs @@ -1,6 +1,7 @@ use liner::KeyBindings; use shell::{flags::*, Shell}; use types; +use small; use std::iter; enum PositionalArgs { @@ -10,7 +11,7 @@ enum PositionalArgs { use self::PositionalArgs::*; -pub(crate) fn set(args: &[String], shell: &mut Shell) -> i32 { +pub(crate) fn set(args: &[small::String], shell: &mut Shell) -> i32 { let mut args_iter = args.iter(); let mut positionals = None; @@ -75,12 +76,12 @@ pub(crate) fn set(args: &[String], shell: &mut Shell) -> i32 { match positionals { None => (), Some(kind) => { - let command: String = shell.variables.get::<types::Array>("args").unwrap()[0].to_owned(); + let command = shell.variables.get::<types::Array>("args").unwrap()[0].clone(); // This used to take a `&[String]` but cloned them all, so although // this is non-ideal and could probably be better done with `Rc`, it // hasn't got any slower. let arguments: types::Array = iter::once(command) - .chain(args_iter.map(|i| i.to_string())) + .chain(args_iter.cloned()) .collect(); match kind { UnsetIfNone => { shell.variables.set("args", arguments); } diff --git a/src/lib/builtins/source.rs b/src/lib/builtins/source.rs index 9a52ea480677c20f1a26c72081e9530b27a3ce02..85a7ca23753b36592fb1c8a90e966d458a641eaa 100644 --- a/src/lib/builtins/source.rs +++ b/src/lib/builtins/source.rs @@ -1,10 +1,11 @@ use shell::{FlowLogic, Shell}; use std::{fs::File, io::Read}; +use small; /// Evaluates the given file and returns 'SUCCESS' if it succeeds. -pub(crate) fn source(shell: &mut Shell, arguments: &[String]) -> Result<(), String> { +pub(crate) fn source(shell: &mut Shell, arguments: &[small::String]) -> Result<(), String> { match arguments.get(1) { - Some(argument) => if let Ok(mut file) = File::open(&argument) { + Some(argument) => if let Ok(mut file) = File::open(argument.as_str()) { let capacity = file.metadata().map(|x| x.len()).unwrap_or(0) as usize; let mut command_list = String::with_capacity(capacity); file.read_to_string(&mut command_list) diff --git a/src/lib/builtins/status.rs b/src/lib/builtins/status.rs index 3063f7165a02cb9014810459e370eca454ee3f5a..ea28e5368f06805f1a459ea43fcbda3e992435c4 100644 --- a/src/lib/builtins/status.rs +++ b/src/lib/builtins/status.rs @@ -1,5 +1,6 @@ use builtins::man_pages::{MAN_STATUS}; use shell::Shell; +use small; use std::env; @@ -12,7 +13,7 @@ bitflags! { } } -pub(crate) fn status(args: &[String], shell: &mut Shell) -> Result<(), String> { +pub(crate) fn status(args: &[small::String], shell: &mut Shell) -> Result<(), String> { let mut flags = Flags::empty(); let shell_args: Vec<_> = env::args().collect(); diff --git a/src/lib/builtins/variables.rs b/src/lib/builtins/variables.rs index 98fc23a0c93a7d92d3f3e1b124be3a6e5fa302a0..7018ff7f4cac5b52b063dc4b8aaa330c4293a51a 100644 --- a/src/lib/builtins/variables.rs +++ b/src/lib/builtins/variables.rs @@ -3,7 +3,7 @@ use std::io::{self, Write}; use shell::{status::*, variables::Variables}; -use types::*; +use types; fn print_list(vars: &Variables) { let stdout = io::stdout(); @@ -19,10 +19,10 @@ fn print_list(vars: &Variables) { } enum Binding { - InvalidKey(Identifier), + InvalidKey(types::Str), ListEntries, - KeyOnly(Identifier), - KeyValue(Identifier, Value), + KeyOnly(types::Str), + KeyValue(types::Str, types::Str), } /// Parses alias as a `(key, value)` tuple. @@ -49,18 +49,18 @@ fn parse_alias(args: &str) -> Binding { } } - let key: Identifier = key.into(); + let key: types::Str = key.into(); if !found_key && key.is_empty() { Binding::ListEntries } else { - let value: Value = char_iter.skip_while(|&x| x == ' ').collect(); + let value: String = char_iter.skip_while(|&x| x == ' ').collect(); if value.is_empty() { Binding::KeyOnly(key) } else if !Variables::is_valid_variable_name(&key) { Binding::InvalidKey(key) } else { - Binding::KeyValue(key, value) + Binding::KeyValue(key, value.into()) } } } @@ -74,7 +74,7 @@ pub(crate) fn alias(vars: &mut Variables, args: &str) -> i32 { return FAILURE; } Binding::KeyValue(key, value) => { - vars.set(&key, Alias(value)); + vars.set(&key, types::Alias(value)); } Binding::ListEntries => print_list(&vars), Binding::KeyOnly(key) => { @@ -143,11 +143,12 @@ mod test { use super::*; use parser::{expand_string, Expander}; use shell::status::{FAILURE, SUCCESS}; + use types::Array; struct VariableExpander(pub Variables); impl Expander for VariableExpander { - fn string(&self, var: &str, _: bool) -> Option<Value> { self.0.get::<Value>(var) } + fn string(&self, var: &str, _: bool) -> Option<types::Str> { self.0.get::<types::Str>(var) } } // TODO: Rewrite tests now that let is part of the grammar. @@ -177,7 +178,7 @@ mod test { #[test] fn drop_deletes_variable() { let mut variables = Variables::default(); - variables.set("FOO", "BAR".to_string()); + variables.set("FOO", "BAR"); let return_status = drop_variable(&mut variables, &["drop", "FOO"]); assert_eq!(SUCCESS, return_status); let expanded = expand_string("$FOO", &VariableExpander(variables), false).join(""); diff --git a/src/lib/lib.rs b/src/lib/lib.rs index 759a71b3db7754d9eb48cace0a03a4274b4d03ad..13e57505b55bafd9b377489e57e873b67fa90008 100644 --- a/src/lib/lib.rs +++ b/src/lib/lib.rs @@ -18,7 +18,7 @@ extern crate lazy_static; extern crate libloading; extern crate liner; extern crate regex; -extern crate smallstring; +extern crate small; extern crate smallvec; extern crate unicode_segmentation; extern crate xdg; diff --git a/src/lib/parser/assignments/checker.rs b/src/lib/parser/assignments/checker.rs index 84fe2e51134636daec58225d5a88fb185bd03a92..1589d2b1c02c509efeddc389c63df58281629ed2 100644 --- a/src/lib/parser/assignments/checker.rs +++ b/src/lib/parser/assignments/checker.rs @@ -1,7 +1,7 @@ use super::super::{expand_string, Expander}; use lexers::assignments::{Primitive, TypeError}; use shell::variables::VariableType; -use types::*; +use types; use std::iter::Iterator; #[derive(PartialEq, Clone, Copy, Debug)] @@ -143,7 +143,7 @@ fn is_float_array(value: VariableType) -> Result<VariableType, ()> { } fn get_string<E: Expander>(shell: &E, value: &str) -> VariableType { - VariableType::Str(expand_string(value, shell, false).join(" ")) + VariableType::Str(types::Str::from(expand_string(value, shell, false).join(" "))) } fn get_array<E: Expander>(shell: &E, value: &str) -> VariableType { @@ -152,7 +152,7 @@ fn get_array<E: Expander>(shell: &E, value: &str) -> VariableType { fn get_hash_map<E: Expander>(shell: &E, expression: &str, inner_kind: &Primitive) -> Result<VariableType, TypeError> { let array = expand_string(expression, shell, false); - let mut hmap: HashMap = HashMap::with_capacity_and_hasher(array.len(), Default::default()); + let mut hmap = types::HashMap::with_capacity_and_hasher(array.len(), Default::default()); for string in array { if let Some(found) = string.find('=') { @@ -185,7 +185,7 @@ fn get_hash_map<E: Expander>(shell: &E, expression: &str, inner_kind: &Primitive fn get_btree_map<E: Expander>(shell: &E, expression: &str, inner_kind: &Primitive) -> Result<VariableType, TypeError> { let array = expand_string(expression, shell, false); - let mut bmap: BTreeMap = BTreeMap::new(); + let mut bmap = types::BTreeMap::new(); for string in array { if let Some(found) = string.find('=') { @@ -241,7 +241,7 @@ pub(crate) fn value_check<E: Expander>( Primitive::Boolean if !is_array => { let value = get_string!(); let value = is_boolean_string(&value).map_err(|_| TypeError::BadValue(expected.clone()))?; - Ok(VariableType::Str(value.to_owned())) + Ok(VariableType::Str(value.into())) } Primitive::BooleanArray if is_array => { let mut values = get_array!(); @@ -273,6 +273,7 @@ pub(crate) fn value_check<E: Expander>( #[cfg(test)] mod test { use super::*; + use types::Array; #[test] fn is_array_() { diff --git a/src/lib/parser/loops.rs b/src/lib/parser/loops.rs index 6161a3ed4e67cad22d448f750a1766e0754fb54d..d1e24aece136b4726c43f6e8a471964b4d76d505 100644 --- a/src/lib/parser/loops.rs +++ b/src/lib/parser/loops.rs @@ -1,15 +1,15 @@ use parser::{expand_string, Expander}; -use types::Value; +use types; #[derive(Debug, PartialEq)] pub(crate) enum ForExpression { - Multiple(Vec<Value>), - Normal(Value), + Multiple(Vec<types::Str>), + Normal(types::Str), Range(usize, usize), } impl ForExpression { - pub(crate) fn new<E: Expander>(expression: &[String], expanders: &E) -> ForExpression { + pub(crate) fn new<E: Expander>(expression: &[types::Str], expanders: &E) -> ForExpression { let output: Vec<_> = expression .iter() .flat_map(|expression| expand_string(expression, expanders, true)) @@ -70,13 +70,13 @@ mod tests { struct VariableExpander(pub Variables); impl Expander for VariableExpander { - fn string(&self, var: &str, _: bool) -> Option<Value> { self.0.get::<Value>(var) } + fn string(&self, var: &str, _: bool) -> Option<types::Str> { self.0.get::<types::Str>(var) } } #[test] fn for_inclusive_range() { let variables = Variables::default(); - let input = &["1...10".to_owned()]; + let input = &["1...10".into()]; assert_eq!( ForExpression::new(input, &VariableExpander(variables)), ForExpression::Range(1, 11) @@ -86,7 +86,7 @@ mod tests { #[test] fn for_exclusive_range() { let variables = Variables::default(); - let input = &["1..10".to_owned()]; + let input = &["1..10".into()]; assert_eq!( ForExpression::new(input, &VariableExpander(variables)), ForExpression::Range(1, 10) @@ -97,11 +97,11 @@ mod tests { fn for_normal() { let variables = Variables::default(); let output = vec![ - "1".to_owned(), - "2".to_owned(), - "3".to_owned(), - "4".to_owned(), - "5".to_owned(), + "1".into(), + "2".into(), + "3".into(), + "4".into(), + "5".into(), ]; assert_eq!( ForExpression::new(&output.clone(), &VariableExpander(variables)), @@ -114,8 +114,8 @@ mod tests { let mut variables = Variables::default(); variables.set("A", "1 2 3 4 5".to_string()); assert_eq!( - ForExpression::new(&["$A".to_owned()], &VariableExpander(variables)), - ForExpression::Normal("1 2 3 4 5".to_owned()) + ForExpression::new(&["$A".into()], &VariableExpander(variables)), + ForExpression::Normal("1 2 3 4 5".into()) ); } } diff --git a/src/lib/parser/pipelines/collector.rs b/src/lib/parser/pipelines/collector.rs index b8259ce238d5c9dce18250e87c5216fdb4616d99..8393bbe433efad4fbedc6aec7a762322030782e7 100644 --- a/src/lib/parser/pipelines/collector.rs +++ b/src/lib/parser/pipelines/collector.rs @@ -163,7 +163,7 @@ impl<'a> Collector<'a> { let heredoc = heredoc.lines().skip(1).collect::<Vec<&str>>(); if heredoc.len() > 1 { let herestring = - Input::HereString(heredoc[..heredoc.len() - 1].join("\n")); + Input::HereString(heredoc[..heredoc.len() - 1].join("\n").into()); if let Some(x) = inputs.as_mut() { x.push(herestring.clone()) }; } } @@ -403,14 +403,14 @@ mod tests { fn stderr_redirection() { if let Statement::Pipeline(pipeline) = parse("git rev-parse --abbrev-ref HEAD ^> /dev/null") { - assert_eq!("git", pipeline.items[0].job.args[0]); - assert_eq!("rev-parse", pipeline.items[0].job.args[1]); - assert_eq!("--abbrev-ref", pipeline.items[0].job.args[2]); - assert_eq!("HEAD", pipeline.items[0].job.args[3]); + assert_eq!("git", pipeline.items[0].job.args[0].as_str()); + assert_eq!("rev-parse", pipeline.items[0].job.args[1].as_str()); + assert_eq!("--abbrev-ref", pipeline.items[0].job.args[2].as_str()); + assert_eq!("HEAD", pipeline.items[0].job.args[3].as_str()); let expected = vec![Redirection { from: RedirectFrom::Stderr, - file: "/dev/null".to_owned(), + file: "/dev/null".into(), append: false, }]; @@ -424,8 +424,8 @@ mod tests { fn braces() { if let Statement::Pipeline(pipeline) = parse("echo {a b} {a {b c}}") { let items = pipeline.items; - assert_eq!("{a b}", items[0].job.args[1]); - assert_eq!("{a {b c}}", items[0].job.args[2]); + assert_eq!("{a b}", items[0].job.args[1].as_str()); + assert_eq!("{a {b c}}", items[0].job.args[2].as_str()); } else { assert!(false); } @@ -435,9 +435,9 @@ mod tests { fn methods() { if let Statement::Pipeline(pipeline) = parse("echo @split(var, ', ') $join(array, ',')") { let items = pipeline.items; - assert_eq!("echo", items[0].job.args[0]); - assert_eq!("@split(var, ', ')", items[0].job.args[1]); - assert_eq!("$join(array, ',')", items[0].job.args[2]); + assert_eq!("echo", items[0].job.args[0].as_str()); + assert_eq!("@split(var, ', ')", items[0].job.args[1].as_str()); + assert_eq!("$join(array, ',')", items[0].job.args[2].as_str()); } else { assert!(false); } @@ -447,8 +447,8 @@ mod tests { fn nested_process() { if let Statement::Pipeline(pipeline) = parse("echo $(echo one $(echo two) three)") { let items = pipeline.items; - assert_eq!("echo", items[0].job.args[0]); - assert_eq!("$(echo one $(echo two) three)", items[0].job.args[1]); + assert_eq!("echo", items[0].job.args[0].as_str()); + assert_eq!("$(echo one $(echo two) three)", items[0].job.args[1].as_str()); } else { assert!(false); } @@ -458,8 +458,8 @@ mod tests { fn nested_array_process() { if let Statement::Pipeline(pipeline) = parse("echo @(echo one @(echo two) three)") { let items = pipeline.items; - assert_eq!("echo", items[0].job.args[0]); - assert_eq!("@(echo one @(echo two) three)", items[0].job.args[1]); + assert_eq!("echo", items[0].job.args[0].as_str()); + assert_eq!("@(echo one @(echo two) three)", items[0].job.args[1].as_str()); } else { assert!(false); } @@ -469,8 +469,8 @@ mod tests { fn quoted_process() { if let Statement::Pipeline(pipeline) = parse("echo \"$(seq 1 10)\"") { let items = pipeline.items; - assert_eq!("echo", items[0].job.args[0]); - assert_eq!("\"$(seq 1 10)\"", items[0].job.args[1]); + assert_eq!("echo", items[0].job.args[0].as_str()); + assert_eq!("\"$(seq 1 10)\"", items[0].job.args[1].as_str()); assert_eq!(2, items[0].job.args.len()); } else { assert!(false); @@ -481,8 +481,8 @@ mod tests { fn process() { if let Statement::Pipeline(pipeline) = parse("echo $(seq 1 10 | head -1)") { let items = pipeline.items; - assert_eq!("echo", items[0].job.args[0]); - assert_eq!("$(seq 1 10 | head -1)", items[0].job.args[1]); + assert_eq!("echo", items[0].job.args[0].as_str()); + assert_eq!("$(seq 1 10 | head -1)", items[0].job.args[1].as_str()); assert_eq!(2, items[0].job.args.len()); } else { assert!(false); @@ -493,8 +493,8 @@ mod tests { fn array_process() { if let Statement::Pipeline(pipeline) = parse("echo @(seq 1 10 | head -1)") { let items = pipeline.items; - assert_eq!("echo", items[0].job.args[0]); - assert_eq!("@(seq 1 10 | head -1)", items[0].job.args[1]); + assert_eq!("echo", items[0].job.args[0].as_str()); + assert_eq!("@(seq 1 10 | head -1)", items[0].job.args[1].as_str()); assert_eq!(2, items[0].job.args.len()); } else { assert!(false); @@ -506,7 +506,7 @@ mod tests { if let Statement::Pipeline(pipeline) = parse("cat") { let items = pipeline.items; assert_eq!(1, items.len()); - assert_eq!("cat", items[0].job.command); + assert_eq!("cat", items[0].job.command.as_str()); assert_eq!(1, items[0].job.args.len()); } else { assert!(false); @@ -518,10 +518,10 @@ mod tests { if let Statement::Pipeline(pipeline) = parse("echo a b c") { let items = pipeline.items; assert_eq!(1, items.len()); - assert_eq!("echo", items[0].job.args[0]); - assert_eq!("a", items[0].job.args[1]); - assert_eq!("b", items[0].job.args[2]); - assert_eq!("c", items[0].job.args[3]); + assert_eq!("echo", items[0].job.args[0].as_str()); + assert_eq!("a", items[0].job.args[1].as_str()); + assert_eq!("b", items[0].job.args[2].as_str()); + assert_eq!("c", items[0].job.args[3].as_str()); assert_eq!(4, items[0].job.args.len()); } else { assert!(false); @@ -533,9 +533,9 @@ mod tests { if let Statement::Pipeline(pipeline) = parse("ls -al dir") { let items = pipeline.items; assert_eq!(1, items.len()); - assert_eq!("ls", items[0].job.command); - assert_eq!("-al", items[0].job.args[1]); - assert_eq!("dir", items[0].job.args[2]); + assert_eq!("ls", items[0].job.command.as_str()); + assert_eq!("-al", items[0].job.args[1].as_str()); + assert_eq!("dir", items[0].job.args[2].as_str()); } else { assert!(false); } @@ -555,9 +555,9 @@ mod tests { if let Statement::Pipeline(pipeline) = parse("ls \t -al\t\tdir") { let items = pipeline.items; assert_eq!(1, items.len()); - assert_eq!("ls", items[0].job.command); - assert_eq!("-al", items[0].job.args[1]); - assert_eq!("dir", items[0].job.args[2]); + assert_eq!("ls", items[0].job.command.as_str()); + assert_eq!("-al", items[0].job.args[1].as_str()); + assert_eq!("dir", items[0].job.args[2].as_str()); } else { assert!(false); } @@ -567,8 +567,8 @@ mod tests { fn trailing_whitespace() { if let Statement::Pipeline(pipeline) = parse("ls -al\t ") { assert_eq!(1, pipeline.items.len()); - assert_eq!("ls", pipeline.items[0].job.command); - assert_eq!("-al", pipeline.items[0].job.args[1]); + assert_eq!("ls", pipeline.items[0].job.command.as_str()); + assert_eq!("-al", pipeline.items[0].job.args[1].as_str()); } else { assert!(false); } @@ -578,8 +578,8 @@ mod tests { fn double_quoting() { if let Statement::Pipeline(pipeline) = parse("echo \"a > 10\" \"a < 10\"") { let items = pipeline.items; - assert_eq!("\"a > 10\"", items[0].job.args[1]); - assert_eq!("\"a < 10\"", items[0].job.args[2]); + assert_eq!("\"a > 10\"", items[0].job.args[1].as_str()); + assert_eq!("\"a < 10\"", items[0].job.args[2].as_str()); assert_eq!(3, items[0].job.args.len()); } else { assert!(false) @@ -591,7 +591,7 @@ mod tests { if let Statement::Pipeline(pipeline) = parse("echo \"Hello 'Rusty' World\"") { let items = pipeline.items; assert_eq!(2, items[0].job.args.len()); - assert_eq!("\"Hello \'Rusty\' World\"", items[0].job.args[1]); + assert_eq!("\"Hello \'Rusty\' World\"", items[0].job.args[1].as_str()); } else { assert!(false) } @@ -602,7 +602,7 @@ mod tests { if let Statement::Pipeline(pipeline) = parse("echo \"Hello \"Rusty\" World\"") { let items = pipeline.items; assert_eq!(2, items[0].job.args.len()); - assert_eq!("\"Hello \"Rusty\" World\"", items[0].job.args[1]); + assert_eq!("\"Hello \"Rusty\" World\"", items[0].job.args[1].as_str()); } else { assert!(false) } @@ -610,7 +610,7 @@ mod tests { if let Statement::Pipeline(pipeline) = parse("echo \'Hello \'Rusty\' World\'") { let items = pipeline.items; assert_eq!(2, items[0].job.args.len()); - assert_eq!("\'Hello \'Rusty\' World\'", items[0].job.args[1]); + assert_eq!("\'Hello \'Rusty\' World\'", items[0].job.args[1].as_str()); } else { assert!(false) } @@ -676,7 +676,7 @@ mod tests { if let Statement::Pipeline(pipeline) = parse(" \techo") { let items = pipeline.items; assert_eq!(1, items.len()); - assert_eq!("echo", items[0].job.command); + assert_eq!("echo", items[0].job.command.as_str()); } else { assert!(false); } @@ -686,7 +686,7 @@ mod tests { fn single_quoting() { if let Statement::Pipeline(pipeline) = parse("echo '#!!;\"\\'") { let items = pipeline.items; - assert_eq!("'#!!;\"\\'", items[0].job.args[1]); + assert_eq!("'#!!;\"\\'", items[0].job.args[1].as_str()); } else { assert!(false); } @@ -698,11 +698,11 @@ mod tests { parse("echo 123 456 \"ABC 'DEF' GHI\" 789 one' 'two") { let items = pipeline.items; - assert_eq!("123", items[0].job.args[1]); - assert_eq!("456", items[0].job.args[2]); - assert_eq!("\"ABC 'DEF' GHI\"", items[0].job.args[3]); - assert_eq!("789", items[0].job.args[4]); - assert_eq!("one' 'two", items[0].job.args[5]); + assert_eq!("123", items[0].job.args[1].as_str()); + assert_eq!("456", items[0].job.args[2].as_str()); + assert_eq!("\"ABC 'DEF' GHI\"", items[0].job.args[3].as_str()); + assert_eq!("789", items[0].job.args[4].as_str()); + assert_eq!("one' 'two", items[0].job.args[5].as_str()); } else { assert!(false); } @@ -724,12 +724,12 @@ mod tests { let input = "cat | echo hello | cat < stuff > other"; if let Statement::Pipeline(pipeline) = parse(input) { assert_eq!(3, pipeline.items.len()); - assert_eq!("cat", &pipeline.clone().items[0].job.args[0]); - assert_eq!("echo", &pipeline.clone().items[1].job.args[0]); - assert_eq!("hello", &pipeline.clone().items[1].job.args[1]); - assert_eq!("cat", &pipeline.clone().items[2].job.args[0]); + assert_eq!("cat", pipeline.clone().items[0].job.args[0].as_str()); + assert_eq!("echo", pipeline.clone().items[1].job.args[0].as_str()); + assert_eq!("hello", pipeline.clone().items[1].job.args[1].as_str()); + assert_eq!("cat", pipeline.clone().items[2].job.args[0].as_str()); assert_eq!(vec![Input::File("stuff".into())], pipeline.items[2].inputs); - assert_eq!("other", &pipeline.clone().items[2].outputs[0].file); + assert_eq!("other", pipeline.clone().items[2].outputs[0].file.as_str()); assert!(!pipeline.clone().items[2].outputs[0].append); assert_eq!(input.to_owned(), pipeline.to_string()); } else { @@ -744,7 +744,7 @@ mod tests { if let Statement::Pipeline(pipeline) = parse("cat | echo hello | cat < stuff >> other") { assert_eq!(3, pipeline.items.len()); assert_eq!(Input::File("stuff".into()), pipeline.items[2].inputs[0]); - assert_eq!("other", pipeline.items[2].outputs[0].file); + assert_eq!("other", pipeline.items[2].outputs[0].file.as_str()); assert!(pipeline.items[2].outputs[0].append); } else { assert!(false); @@ -756,8 +756,8 @@ mod tests { // '^' while not in the top level fn args_loop_terminates() { if let Statement::Pipeline(pipeline) = parse("$(^) '$(^)'") { - assert_eq!("$(^)", pipeline.items[0].job.args[0]); - assert_eq!("\'$(^)\'", pipeline.items[0].job.args[1]); + assert_eq!("$(^)", pipeline.items[0].job.args[0].as_str()); + assert_eq!("\'$(^)\'", pipeline.items[0].job.args[1].as_str()); } else { assert!(false); } @@ -873,7 +873,7 @@ mod tests { if let Statement::Pipeline(pipeline) = parse("cat | echo hello | cat > stuff < other") { assert_eq!(3, pipeline.items.len()); assert_eq!(vec![Input::File("other".into())], pipeline.items[2].inputs); - assert_eq!("stuff", pipeline.items[2].outputs[0].file); + assert_eq!("stuff", pipeline.items[2].outputs[0].file.as_str()); } else { assert!(false); } @@ -883,19 +883,19 @@ mod tests { fn var_meets_quote() { if let Statement::Pipeline(pipeline) = parse("echo $x '{()}' test") { assert_eq!(1, pipeline.items.len()); - assert_eq!("echo", &pipeline.clone().items[0].job.args[0]); - assert_eq!("$x", &pipeline.clone().items[0].job.args[1]); - assert_eq!("'{()}'", &pipeline.clone().items[0].job.args[2]); - assert_eq!("test", &pipeline.clone().items[0].job.args[3]); + assert_eq!("echo", pipeline.clone().items[0].job.args[0].as_str()); + assert_eq!("$x", pipeline.clone().items[0].job.args[1].as_str()); + assert_eq!("'{()}'", pipeline.clone().items[0].job.args[2].as_str()); + assert_eq!("test", pipeline.clone().items[0].job.args[3].as_str()); } else { assert!(false); } if let Statement::Pipeline(pipeline) = parse("echo $x'{()}' test") { assert_eq!(1, pipeline.items.len()); - assert_eq!("echo", &pipeline.clone().items[0].job.args[0]); - assert_eq!("$x'{()}'", &pipeline.clone().items[0].job.args[1]); - assert_eq!("test", &pipeline.clone().items[0].job.args[2]); + assert_eq!("echo", pipeline.clone().items[0].job.args[0].as_str()); + assert_eq!("$x'{()}'", pipeline.clone().items[0].job.args[1].as_str()); + assert_eq!("test", pipeline.clone().items[0].job.args[2].as_str()); } else { assert!(false); } @@ -957,14 +957,14 @@ mod tests { fn awk_tests() { if let Statement::Pipeline(pipeline) = parse("awk -v x=$x '{ if (1) print $1 }' myfile") { assert_eq!(1, pipeline.items.len()); - assert_eq!("awk", &pipeline.clone().items[0].job.args[0]); - assert_eq!("-v", &pipeline.clone().items[0].job.args[1]); - assert_eq!("x=$x", &pipeline.clone().items[0].job.args[2]); + assert_eq!("awk", pipeline.clone().items[0].job.args[0].as_str()); + assert_eq!("-v", pipeline.clone().items[0].job.args[1].as_str()); + assert_eq!("x=$x", pipeline.clone().items[0].job.args[2].as_str()); assert_eq!( "'{ if (1) print $1 }'", - &pipeline.clone().items[0].job.args[3] + pipeline.clone().items[0].job.args[3].as_str() ); - assert_eq!("myfile", &pipeline.clone().items[0].job.args[4]); + assert_eq!("myfile", pipeline.clone().items[0].job.args[4].as_str()); } else { assert!(false); } diff --git a/src/lib/parser/pipelines/mod.rs b/src/lib/parser/pipelines/mod.rs index 87f03ffec2c1e573a34862f06fb0717bb135fc8a..107be704eab2bcf259ccb1cc249178acd42a1f23 100644 --- a/src/lib/parser/pipelines/mod.rs +++ b/src/lib/parser/pipelines/mod.rs @@ -4,6 +4,7 @@ pub(crate) use self::collector::*; use super::expand_string; use shell::{Job, JobKind, Shell}; +use small; use std::fmt; #[derive(Debug, PartialEq, Clone, Copy)] @@ -16,7 +17,7 @@ pub(crate) enum RedirectFrom { #[derive(Debug, PartialEq, Clone)] pub(crate) struct Redirection { pub from: RedirectFrom, - pub file: String, + pub file: small::String, pub append: bool, } @@ -25,10 +26,10 @@ pub(crate) struct Redirection { pub(crate) enum Input { /// A file; the contents of said file will be written to the `stdin` of a /// process - File(String), + File(small::String), /// A string literal that is written to the `stdin` of a process. /// If there is a second string, that second string is the EOF phrase for the heredoc. - HereString(String), + HereString(small::String), } #[derive(Debug, PartialEq, Clone)] @@ -49,13 +50,13 @@ impl PipeItem { for input in &mut self.inputs { *input = match input { - Input::File(ref s) => Input::File(expand_string(s, shell, false).join(" ")), - Input::HereString(ref s) => Input::HereString(expand_string(s, shell, true).join(" ")), + Input::File(ref s) => Input::File(expand_string(s, shell, false).join(" ").into()), + Input::HereString(ref s) => Input::HereString(expand_string(s, shell, true).join(" ").into()), }; } for output in &mut self.outputs { - output.file = expand_string(output.file.as_str(), shell, false).join(" "); + output.file = expand_string(output.file.as_str(), shell, false).join(" ").into(); } } @@ -86,7 +87,7 @@ impl Pipeline { impl fmt::Display for Pipeline { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut tokens: Vec<String> = Vec::with_capacity(self.items.len()); + let mut tokens: Vec<small::String> = Vec::with_capacity(self.items.len()); for item in &self.items { let job = &item.job; let kind = job.kind; diff --git a/src/lib/parser/shell_expand/mod.rs b/src/lib/parser/shell_expand/mod.rs index 4e4e367db618d8ca03727707905f382ff497b0bc..8e4c468fc9309b2fbffd90b158d6d042585244c3 100644 --- a/src/lib/parser/shell_expand/mod.rs +++ b/src/lib/parser/shell_expand/mod.rs @@ -7,8 +7,9 @@ pub(crate) use self::words::{Select, WordIterator, WordToken}; use braces::{self, BraceToken}; use ranges::{parse_range, Index, Range}; use glob::glob; +use small; use std::{ptr, str}; -use types::*; +use types::{self, Array}; use unicode_segmentation::UnicodeSegmentation; /// Determines whether an input string is expression-like as compared to a @@ -27,15 +28,15 @@ pub(crate) trait Expander { /// Expand a tilde form to the correct directory fn tilde(&self, &str) -> Option<String> { None } /// Expand an array variable with some selection - fn array(&self, &str, Select) -> Option<Array> { None } + fn array(&self, &str, Select) -> Option<types::Array> { None } /// Expand a string variable given if its quoted / unquoted - fn string(&self, &str, bool) -> Option<Value> { None } + fn string(&self, &str, bool) -> Option<types::Str> { None } /// Expand a subshell expression - fn command(&self, &str) -> Option<Value> { None } + fn command(&self, &str) -> Option<types::Str> { None } } fn expand_process<E: Expander>( - current: &mut String, + current: &mut small::String, command: &str, selection: Select, expander: &E, @@ -85,8 +86,8 @@ fn expand_process<E: Expander>( } fn expand_brace<E: Expander>( - current: &mut String, - expanders: &mut Vec<Vec<String>>, + current: &mut small::String, + expanders: &mut Vec<Vec<small::String>>, tokens: &mut Vec<BraceToken>, nodes: &[&str], expand_func: &E, @@ -116,9 +117,9 @@ fn expand_brace<E: Expander>( } } -fn array_expand<E: Expander>(elements: &[&str], expand_func: &E, selection: Select) -> Array { +fn array_expand<E: Expander>(elements: &[&str], expand_func: &E, selection: Select) -> types::Array { match selection { - Select::None => Array::new(), + Select::None => types::Array::new(), Select::All => elements .iter() .flat_map(|e| expand_string(e, expand_func, false)) @@ -127,11 +128,11 @@ fn array_expand<E: Expander>(elements: &[&str], expand_func: &E, selection: Sele .into_iter() .collect(), Select::Range(range) => array_range(elements, expand_func, range), - Select::Key(_) => Array::new(), + Select::Key(_) => types::Array::new(), } } -fn array_nth<E: Expander>(elements: &[&str], expand_func: &E, index: Index) -> Option<Value> { +fn array_nth<E: Expander>(elements: &[&str], expand_func: &E, index: Index) -> Option<types::Str> { let mut expanded = elements .iter() .flat_map(|e| expand_string(e, expand_func, false)); @@ -141,20 +142,20 @@ fn array_nth<E: Expander>(elements: &[&str], expand_func: &E, index: Index) -> O } } -fn array_range<E: Expander>(elements: &[&str], expand_func: &E, range: Range) -> Array { +fn array_range<E: Expander>(elements: &[&str], expand_func: &E, range: Range) -> types::Array { let expanded = elements .iter() .flat_map(|e| expand_string(e, expand_func, false)) - .collect::<Array>(); + .collect::<types::Array>(); let len = expanded.len(); if let Some((start, length)) = range.bounds(len) { expanded.into_iter().skip(start).take(length).collect() } else { - Array::new() + types::Array::new() } } -fn slice<S: AsRef<str>>(output: &mut String, expanded: S, selection: Select) { +fn slice<S: AsRef<str>>(output: &mut small::String, expanded: S, selection: Select) { match selection { Select::None => (), Select::All => output.push_str(expanded.as_ref()), @@ -192,7 +193,7 @@ pub(crate) fn expand_string<E: Expander>( original: &str, expand_func: &E, reverse_quoting: bool, -) -> Array { +) -> types::Array { let mut token_buffer = Vec::new(); let mut contains_brace = false; let mut word_iterator = WordIterator::new(original, expand_func, true); @@ -244,7 +245,7 @@ fn expand_string_no_glob<E: Expander>( original: &str, expand_func: &E, reverse_quoting: bool, -) -> Array { +) -> types::Array { let mut token_buffer = Vec::new(); let mut contains_brace = false; let mut word_iterator = WordIterator::new(original, expand_func, false); @@ -271,11 +272,11 @@ fn expand_braces<E: Expander>( word_tokens: &[WordToken], expand_func: &E, reverse_quoting: bool, -) -> Array { - let mut expanded_words = Array::new(); - let mut output = String::new(); +) -> types::Array { + let mut expanded_words = types::Array::new(); + let mut output = small::String::new(); let tokens: &mut Vec<BraceToken> = &mut Vec::new(); - let mut expanders: Vec<Vec<String>> = Vec::new(); + let mut expanders: Vec<Vec<small::String>> = Vec::new(); for word in word_tokens { match *word { @@ -290,23 +291,23 @@ fn expand_braces<E: Expander>( WordToken::ArrayProcess(command, _, ref index) => match *index { Select::None => (), Select::All => { - let mut temp = String::new(); + let mut temp = small::String::new(); expand_process(&mut temp, command, Select::All, expand_func, false); let temp = temp.split_whitespace().collect::<Vec<&str>>(); output.push_str(&temp.join(" ")); } Select::Index(Index::Forward(id)) => { - let mut temp = String::new(); + 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 = String::new(); + 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 = String::new(); + 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) { @@ -362,7 +363,7 @@ fn expand_braces<E: Expander>( } } if expanders.is_empty() { - expanded_words.push(output); + expanded_words.push(output.into()); } else { if !output.is_empty() { tokens.push(BraceToken::Normal(output)); @@ -377,22 +378,22 @@ fn expand_braces<E: Expander>( } } - expanded_words.into_iter().fold(Array::new(), |mut array, word| { + expanded_words.into_iter().fold(types::Array::new(), |mut array, word| { if word.find('*').is_some() { if let Ok(mut paths) = glob(&word) { match paths.next() { Some(path) => if let Ok(path_buf) = path { - array.push(path_buf.to_string_lossy().to_string()); + array.push((*path_buf.to_string_lossy()).into()); } else { - array.push(String::new()); + array.push("".into()); }, None => array.push(word), } for path in paths { if let Ok(path_buf) = path { - array.push(path_buf.to_string_lossy().to_string()); + array.push((*path_buf.to_string_lossy()).into()); } else { - array.push(String::new()); + array.push("".into()); } } } else { @@ -406,24 +407,24 @@ fn expand_braces<E: Expander>( }) } -fn expand_single_array_token<E: Expander>(token: &WordToken, expand_func: &E) -> Option<Array> { - let mut output = String::new(); +fn expand_single_array_token<E: Expander>(token: &WordToken, expand_func: &E) -> Option<types::Array> { + let mut output = small::String::new(); match *token { WordToken::Array(ref elements, ref index) => { Some(array_expand(elements, expand_func, index.clone())) } WordToken::ArrayVariable(array, quoted, ref index) => { match expand_func.array(array, index.clone()) { - Some(ref array) if quoted => Some(array.join(" ").into()).into_iter().collect(), + Some(ref array) if quoted => ::std::iter::once(Some(small::String::from(array.join(" ")))).collect(), Some(array) => Some(array), - None => Some(Array::new()), + None => Some(types::Array::new()), } } WordToken::ArrayProcess(command, _, ref index) => match *index { - Select::None => Some(Array::new()), + Select::None => Some(types::Array::new()), Select::All => { expand_process(&mut output, command, Select::All, expand_func, false); - Some(output.split_whitespace().map(From::from).collect::<Array>()) + Some(output.split_whitespace().map(From::from).collect::<types::Array>()) } Select::Index(Index::Forward(id)) => { expand_process(&mut output, command, Select::All, expand_func, false); @@ -460,10 +461,10 @@ fn expand_single_array_token<E: Expander>(token: &WordToken, expand_func: &E) -> .collect(), ) } else { - Some(Array::new()) + Some(types::Array::new()) } } - Select::Key(_) => Some(Array::new()), + Select::Key(_) => Some(types::Array::new()), }, WordToken::ArrayMethod(ref array_method) => Some(array_method.handle_as_array(expand_func)), _ => None, @@ -474,9 +475,9 @@ fn expand_single_string_token<E: Expander>( token: &WordToken, expand_func: &E, reverse_quoting: bool, -) -> Array { - let mut output = String::new(); - let mut expanded_words = Array::new(); +) -> types::Array { + let mut output = small::String::new(); + let mut expanded_words = types::Array::new(); match *token { WordToken::StringMethod(ref method) => method.handle(&mut output, expand_func), @@ -500,7 +501,7 @@ fn expand_single_string_token<E: Expander>( let expanded = match expand_func.string(text, quoted) { Some(var) => var, None => { - if output != "" { + if output.as_str() != "" { expanded_words.push(output); } return expanded_words; @@ -513,23 +514,23 @@ fn expand_single_string_token<E: Expander>( _ => unreachable!(), } - if output != "" { + if output.as_str() != "" { expanded_words.push(output.into()); } expanded_words } fn expand<E: Expander>( - output: &mut String, - expanded_words: &mut Array, + output: &mut small::String, + expanded_words: &mut types::Array, expand_func: &E, text: &str, do_glob: bool, tilde: bool, ) { - let expanded: String = if tilde { + let expanded: small::String = if tilde { match expand_func.tilde(text) { - Some(s) => s, + Some(s) => s.into(), None => text.into(), } } else { @@ -542,7 +543,7 @@ fn expand<E: Expander>( let mut globs_found = false; for path in var.filter_map(Result::ok) { globs_found = true; - expanded_words.push(path.to_string_lossy().into_owned()); + expanded_words.push(path.to_string_lossy().as_ref().into()); } if !globs_found { expanded_words.push(expanded); @@ -560,7 +561,7 @@ pub(crate) fn expand_tokens<E: Expander>( expand_func: &E, reverse_quoting: bool, contains_brace: bool, -) -> Array { +) -> types::Array { if !token_buffer.is_empty() { if contains_brace { return expand_braces(&token_buffer, expand_func, reverse_quoting); @@ -572,8 +573,8 @@ pub(crate) fn expand_tokens<E: Expander>( }; } - let mut output = String::new(); - let mut expanded_words = Array::new(); + let mut output = small::String::new(); + let mut expanded_words = types::Array::new(); for word in token_buffer { match *word { @@ -588,23 +589,23 @@ pub(crate) fn expand_tokens<E: Expander>( WordToken::ArrayProcess(command, _, ref index) => match index.clone() { Select::None => (), Select::All => { - let mut temp = String::new(); + let mut temp = small::String::new(); expand_process(&mut temp, command, Select::All, expand_func, false); let temp = temp.split_whitespace().collect::<Vec<&str>>(); output.push_str(&temp.join(" ")); } Select::Index(Index::Forward(id)) => { - let mut temp = String::new(); + 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 = String::new(); + 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 = String::new(); + 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()) { @@ -655,7 +656,7 @@ pub(crate) fn expand_tokens<E: Expander>( } } // I'm not entirely sure if empty strings are valid in any case- maarten - if output != "" { + if output.as_str() != "" { expanded_words.push(output); } expanded_words @@ -669,10 +670,10 @@ pub(crate) fn expand_tokens<E: Expander>( /// x * 5 + y => 22 /// ``` /// if `x=5` and `y=7` -fn expand_arithmetic<E: Expander>(output: &mut String, input: &str, expander: &E) { - let mut intermediate = String::with_capacity(input.as_bytes().len()); - let mut varbuf = String::new(); - let flush = |var: &mut String, out: &mut String| { +fn expand_arithmetic<E: Expander>(output: &mut small::String, input: &str, expander: &E) { + let mut intermediate = small::String::with_capacity(input.as_bytes().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 @@ -714,14 +715,14 @@ mod test { struct VariableExpander; impl Expander for VariableExpander { - fn string(&self, variable: &str, _: bool) -> Option<Value> { + fn string(&self, variable: &str, _: bool) -> Option<types::Str> { match variable { - "A" => Some("1".to_owned()), - "B" => Some("test".to_owned()), - "C" => Some("ing".to_owned()), - "D" => Some("1 2 3".to_owned()), - "FOO" => Some("FOO".to_owned()), - "BAR" => Some("BAR".to_owned()), + "A" => Some("1".into()), + "B" => Some("test".into()), + "C" => Some("ing".into()), + "D" => Some("1 2 3".into()), + "FOO" => Some("FOO".into()), + "BAR" => Some("BAR".into()), _ => None, } } @@ -730,23 +731,23 @@ mod test { struct CommandExpander; impl Expander for CommandExpander { - fn command(&self, cmd: &str) -> Option<Value> { Some(cmd.to_owned()) } + fn command(&self, cmd: &str) -> Option<types::Str> { Some(cmd.into()) } } #[test] fn expand_process_quoted() { - let mut output = String::new(); + let mut output = small::String::new(); let line = " Mary had\ta little \n\t lamb\t"; expand_process(&mut output, line, Select::All, &CommandExpander, true); - assert_eq!(output, line); + assert_eq!(output.as_str(), line); } #[test] fn expand_process_unquoted() { - let mut output = String::new(); + let mut output = small::String::new(); let line = " Mary had\ta little \n\t lamb\t"; expand_process(&mut output, line, Select::All, &CommandExpander, false); - assert_eq!(output, "Mary had a little lamb"); + assert_eq!(output.as_str(), "Mary had a little lamb"); } #[test] @@ -766,8 +767,8 @@ mod test { assert_eq!( expected .split_whitespace() - .map(|x| x.to_owned()) - .collect::<Array>(), + .map(|x| x.into()) + .collect::<types::Array>(), expanded ); } @@ -780,8 +781,8 @@ mod test { assert_eq!( expected .split_whitespace() - .map(|x| x.to_owned()) - .collect::<Array>(), + .map(|x| x.into()) + .collect::<types::Array>(), expanded ); } @@ -833,7 +834,7 @@ mod test { } } { - let expected = Array::new(); + let expected = types::Array::new(); let idxs = vec!["-17", "4..-4"]; for idx in idxs { assert_eq!(expected, expand_string(&base(idx), &expander, false)); diff --git a/src/lib/parser/shell_expand/words/methods/arrays.rs b/src/lib/parser/shell_expand/words/methods/arrays.rs index ad12232c95c6d759fd85d1835a3515cae595e893..77428336f40765a193dd499ac2f19b1eddfd6876 100644 --- a/src/lib/parser/shell_expand/words/methods/arrays.rs +++ b/src/lib/parser/shell_expand/words/methods/arrays.rs @@ -5,9 +5,9 @@ use super::{ strings::unescape, Pattern, }; use ranges::Index; -use smallstring::SmallString; +use small; use std::char; -use types::Array; +use types::{self, Array}; use unicode_segmentation::UnicodeSegmentation; #[derive(Debug, PartialEq, Clone)] @@ -30,8 +30,7 @@ impl<'a> ArrayMethod<'a> { Ok(variable .lines() .into_iter() - .map(|line| line.to_string()) - .collect()) + .map(|line| types::Str::from(line)) .collect()) } fn chars<E: Expander>(&self, expand_func: &E) -> Result<Array, &'static str> { @@ -39,7 +38,7 @@ impl<'a> ArrayMethod<'a> { let len = variable.chars().count(); Ok(variable .chars() - .map(|c| c.to_string()) + .map(|c| types::Str::from(c.to_string())) .select(self.selection.clone(), len)) } @@ -48,13 +47,13 @@ impl<'a> ArrayMethod<'a> { let len = variable.as_bytes().len(); Ok(variable .bytes() - .map(|b| b.to_string()) + .map(|b| types::Str::from(b.to_string())) .select(self.selection.clone(), len)) } fn graphemes<E: Expander>(&self, expand_func: &E) -> Result<Array, &'static str> { let variable = self.resolve_var(expand_func); - let graphemes: Vec<String> = UnicodeSegmentation::graphemes(variable.as_str(), true) + let graphemes: Vec<types::Str> = UnicodeSegmentation::graphemes(variable.as_str(), true) .map(From::from) .collect(); let len = graphemes.len(); @@ -71,7 +70,7 @@ impl<'a> ArrayMethod<'a> { { if value < variable.len() { let (l, r) = variable.split_at(value); - Ok(array![SmallString::from(l), SmallString::from(r)]) + Ok(array![types::Str::from(l), types::Str::from(r)]) } else { Err("value is out of bounds") } @@ -87,9 +86,9 @@ impl<'a> ArrayMethod<'a> { let res = match (&self.pattern, self.selection.clone()) { (_, Select::None) => Some("".into()).into_iter().collect(), (&Pattern::StringPattern(pattern), Select::All) => variable - .split(&unescape( + .split(unescape( &expand_string(pattern, expand_func, false).join(" ") - )?) + )?.as_str()) .map(From::from) .collect(), (&Pattern::Whitespace, Select::All) => variable @@ -100,7 +99,7 @@ impl<'a> ArrayMethod<'a> { (&Pattern::StringPattern(pattern), Select::Index(Index::Forward(id))) => variable .split(&unescape( &expand_string(pattern, expand_func, false).join(" ") - )?) + )?.as_str()) .nth(id) .map(From::from) .into_iter() @@ -115,7 +114,7 @@ impl<'a> ArrayMethod<'a> { (&Pattern::StringPattern(pattern), Select::Index(Index::Backward(id))) => variable .rsplit(&unescape( &expand_string(pattern, expand_func, false).join(" ") - )?) + )?.as_str()) .nth(id) .map(From::from) .into_iter() @@ -129,7 +128,7 @@ impl<'a> ArrayMethod<'a> { .collect(), (&Pattern::StringPattern(pattern), Select::Range(range)) => { let expansion = unescape(&expand_string(pattern, expand_func, false).join(" "))?; - let iter = variable.split(&expansion); + let iter = variable.split(expansion.as_str()); if let Some((start, length)) = range.bounds(iter.clone().count()) { iter.skip(start).take(length).map(From::from).collect() } else { @@ -170,11 +169,11 @@ impl<'a> ArrayMethod<'a> { } #[inline] - fn resolve_var<E: Expander>(&self, expand_func: &E) -> String { + fn resolve_var<E: Expander>(&self, expand_func: &E) -> types::Str { if let Some(variable) = expand_func.string(self.variable, false) { variable } else if is_expression(self.variable) { - expand_string(self.variable, expand_func, false).join(" ") + types::Str::from_string(expand_string(self.variable, expand_func, false).join(" ")) } else { "".into() } @@ -198,7 +197,7 @@ impl<'a> ArrayMethod<'a> { }) } - pub(crate) fn handle<E: Expander>(&self, current: &mut String, expand_func: &E) { + pub(crate) fn handle<E: Expander>(&self, current: &mut small::String, expand_func: &E) { let res = match self.method { "split" => self.split(expand_func).map(|r| r.join(" ")), _ => Err("invalid array method"), @@ -214,23 +213,23 @@ impl<'a> ArrayMethod<'a> { mod test { use super::*; use ranges::Range; - use types::Value; + use types; struct VariableExpander; impl Expander for VariableExpander { - fn array(&self, variable: &str, _: Select) -> Option<Array> { + fn array(&self, variable: &str, _: Select) -> Option<types::Array> { match variable { "ARRAY" => Some(array!["a", "b", "c"].to_owned()), _ => None, } } - fn string(&self, variable: &str, _: bool) -> Option<Value> { + fn string(&self, variable: &str, _: bool) -> Option<types::Str> { match variable { - "FOO" => Some("FOOBAR".to_owned()), - "SPACEDFOO" => Some("FOO BAR".to_owned()), - "MULTILINE" => Some("FOO\nBAR".to_owned()), + "FOO" => Some("FOOBAR".into()), + "SPACEDFOO" => Some("FOO BAR".into()), + "MULTILINE" => Some("FOO\nBAR".into()), _ => None, } } @@ -238,7 +237,7 @@ mod test { #[test] fn test_split_string_all() { - let mut output = String::new(); + let mut output = types::Str::new(); let method = ArrayMethod { method: "split", variable: "$FOO", @@ -246,12 +245,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "FO AR"); + assert_eq!(&*output, "FO AR"); } #[test] fn test_split_whitespace_all() { - let mut output = String::new(); + let mut output = types::Str::new(); let method = ArrayMethod { method: "split", variable: "$SPACEDFOO", @@ -259,12 +258,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "FOO BAR"); + assert_eq!(&*output, "FOO BAR"); } #[test] fn test_split_string_index_forward() { - let mut output = String::new(); + let mut output = types::Str::new(); let method = ArrayMethod { method: "split", variable: "$FOO", @@ -272,12 +271,12 @@ mod test { selection: Select::Index(Index::Forward(1)), }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "AR"); + assert_eq!(&*output, "AR"); } #[test] fn test_split_whitespace_index_forward() { - let mut output = String::new(); + let mut output = types::Str::new(); let method = ArrayMethod { method: "split", variable: "$SPACEDFOO", @@ -285,12 +284,12 @@ mod test { selection: Select::Index(Index::Forward(1)), }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "BAR"); + assert_eq!(&*output, "BAR"); } #[test] fn test_split_string_index_backward() { - let mut output = String::new(); + let mut output = types::Str::new(); let method = ArrayMethod { method: "split", variable: "$FOO", @@ -298,12 +297,12 @@ mod test { selection: Select::Index(Index::Backward(1)), }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "FO"); + assert_eq!(&*output, "FO"); } #[test] fn test_split_whitespace_index_backward() { - let mut output = String::new(); + let mut output = types::Str::new(); let method = ArrayMethod { method: "split", variable: "$SPACEDFOO", @@ -311,12 +310,12 @@ mod test { selection: Select::Index(Index::Backward(1)), }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "FOO"); + assert_eq!(&*output, "FOO"); } #[test] fn test_split_string_range() { - let mut output = String::new(); + let mut output = types::Str::new(); let method = ArrayMethod { method: "split", variable: "$FOO", @@ -324,12 +323,12 @@ mod test { selection: Select::Range(Range::from(Index::Forward(0))), }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "FO AR"); + assert_eq!(&*output, "FO AR"); } #[test] fn test_split_whitespace_range() { - let mut output = String::new(); + let mut output = types::Str::new(); let method = ArrayMethod { method: "split", variable: "$SPACEDFOO", @@ -337,12 +336,12 @@ mod test { selection: Select::Range(Range::from(Index::Forward(0))), }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "FOO BAR"); + assert_eq!(&*output, "FOO BAR"); } #[test] fn test_split_none() { - let mut output = String::new(); + let mut output = types::Str::new(); let method = ArrayMethod { method: "split", variable: "$SPACEDFOO", @@ -350,12 +349,12 @@ mod test { selection: Select::None, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, ""); + assert_eq!(&*output, ""); } #[test] fn test_split_key() { - let mut output = String::new(); + let mut output = types::Str::new(); let method = ArrayMethod { method: "split", variable: "$SPACEDFOO", @@ -363,7 +362,7 @@ mod test { selection: Select::Key("1".into()), }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, ""); + assert_eq!(&*output, ""); } #[test] diff --git a/src/lib/parser/shell_expand/words/methods/mod.rs b/src/lib/parser/shell_expand/words/methods/mod.rs index 23de3a8b5f6eaf89f1f011b5d0e80652364b9ba1..2068be11738c2367323cff6d9ac6ab0dbb2d50b4 100644 --- a/src/lib/parser/shell_expand/words/methods/mod.rs +++ b/src/lib/parser/shell_expand/words/methods/mod.rs @@ -6,6 +6,7 @@ use self::strings::unescape; use lexers::ArgumentSplitter; use super::{expand_string, Expander}; +use small; #[derive(Debug, PartialEq, Clone)] pub(crate) enum Pattern<'a> { @@ -20,15 +21,15 @@ pub(crate) struct MethodArgs<'a, 'b, E: 'b + Expander> { } impl<'a, 'b, E: 'b + Expander> MethodArgs<'a, 'b, E> { - pub(crate) fn array<'c>(&'c self) -> impl Iterator<Item = String> + 'c { + pub(crate) fn array<'c>(&'c self) -> impl Iterator<Item = small::String> + 'c { ArgumentSplitter::new(self.args) .flat_map(move |x| expand_string(x, self.expand, false).into_iter()) - .map(|s| unescape(&s).unwrap_or_else(|_| String::from(""))) + .map(|s| unescape(&s).unwrap_or_else(|_| small::String::from(""))) } - pub(crate) fn join(self, pattern: &str) -> String { + pub(crate) fn join(self, pattern: &str) -> small::String { unescape(&expand_string(self.args, self.expand, false).join(pattern)) - .unwrap_or_else(|_| String::from("")) + .unwrap_or_else(|_| small::String::from("")) } pub(crate) fn new(args: &'a str, expand: &'b E) -> MethodArgs<'a, 'b, E> { diff --git a/src/lib/parser/shell_expand/words/methods/strings.rs b/src/lib/parser/shell_expand/words/methods/strings.rs index e8f0685281a855613652b0362b26fcd7dca6e084..e6e3c62facedf64932bcf07c41bffa3b7164c65a 100644 --- a/src/lib/parser/shell_expand/words/methods/strings.rs +++ b/src/lib/parser/shell_expand/words/methods/strings.rs @@ -8,6 +8,7 @@ use parser::assignments::is_array; use regex::Regex; use shell::plugins::methods::{self, MethodArguments, StringMethodPlugins}; use std::path::Path; +use small; use sys; use unicode_segmentation::UnicodeSegmentation; @@ -15,10 +16,10 @@ lazy_static! { static ref STRING_METHODS: StringMethodPlugins = methods::collect(); } -pub(crate) fn unescape(input: &str) -> Result<String, &'static str> { +pub(crate) fn unescape(input: &str) -> Result<small::String, &'static str> { let mut check = false; - let mut out = String::with_capacity(input.len()); - let add_char = |out: &mut String, check: &mut bool, c| { + let mut out = small::String::with_capacity(input.len()); + let add_char = |out: &mut small::String, check: &mut bool, c| { out.push(c); *check = false; }; @@ -33,7 +34,7 @@ pub(crate) fn unescape(input: &str) -> Result<String, &'static str> { 'a' if check => add_char(&mut out, &mut check, '\u{0007}'), 'b' if check => add_char(&mut out, &mut check, '\u{0008}'), 'c' if check => { - out = String::from(""); + out = small::String::from(""); break; } 'e' if check => add_char(&mut out, &mut check, '\u{001B}'), @@ -97,7 +98,7 @@ pub(crate) struct StringMethod<'a> { } impl<'a> StringMethod<'a> { - pub(crate) fn handle<E: Expander>(&self, output: &mut String, expand: &E) { + pub(crate) fn handle<E: Expander>(&self, output: &mut small::String, expand: &E) { let variable = self.variable; let pattern = MethodArgs::new(self.pattern, expand); @@ -105,11 +106,11 @@ impl<'a> StringMethod<'a> { ($variable:ident $method:tt) => {{ let pattern = pattern.join(" "); let is_true = if let Some(value) = expand.string($variable, false) { - value.$method(&pattern) + value.$method(pattern.as_str()) } else if is_expression($variable) { expand_string($variable, expand, false) .join(" ") - .$method(&pattern) + .$method(pattern.as_str()) } else { false }; @@ -121,7 +122,7 @@ impl<'a> StringMethod<'a> { ($method:tt) => {{ if let Some(value) = expand.string(variable, false) { output.push_str( - Path::new(&value) + Path::new(&*value) .$method() .and_then(|os_str| os_str.to_str()) .unwrap_or(value.as_str()), @@ -154,7 +155,7 @@ impl<'a> StringMethod<'a> { if let Some(value) = expand.string(variable, false) { value } else { - expand_string(variable, expand, false).join(" ") + small::String::from(expand_string(variable, expand, false).join(" ")) } }}; } @@ -179,7 +180,7 @@ impl<'a> StringMethod<'a> { let mut args = pattern.array(); match (args.next(), args.next()) { (Some(replace), Some(with)) => { - let res = &get_var!().replace(&replace, &with); + let res = &get_var!().replace(replace.as_str(), &with); output.push_str(res); } _ => eprintln!("ion: replace: two arguments are required"), @@ -190,7 +191,7 @@ impl<'a> StringMethod<'a> { match (args.next(), args.next(), args.next()) { (Some(replace), Some(with), Some(nth)) => if let Ok(nth) = nth.parse::<usize>() { - let res = &get_var!().replacen(&replace, &with, nth); + let res = &get_var!().replacen(replace.as_str(), &with, nth); output.push_str(res); } else { eprintln!("ion: replacen: third argument isn't a valid integer"); @@ -254,11 +255,11 @@ impl<'a> StringMethod<'a> { }, "find" => { let out = if let Some(value) = expand.string(variable, false) { - value.find(&pattern.join(" ")) + value.find(pattern.join(" ").as_str()) } else if is_expression(variable) { expand_string(variable, expand, false) .join(" ") - .find(&pattern.join(" ")) + .find(pattern.join(" ").as_str()) } else { None }; @@ -268,7 +269,7 @@ impl<'a> StringMethod<'a> { let out = if let Some(value) = expand.string(variable, false) { value } else if is_expression(variable) { - expand_string(variable, expand, false).join(" ") + expand_string(variable, expand, false).join(" ").into() } else { return; }; @@ -281,7 +282,7 @@ impl<'a> StringMethod<'a> { let word = if let Some(value) = expand.string(variable, false) { value } else if is_expression(variable) { - expand_string(variable, expand, false).join(" ") + expand_string(variable, expand, false).join(" ").into() } else { return; }; @@ -328,14 +329,14 @@ impl<'a> StringMethod<'a> { #[cfg(test)] mod test { use super::*; - use types::Value; + use types; struct VariableExpander; impl Expander for VariableExpander { - fn string(&self, variable: &str, _: bool) -> Option<Value> { + fn string(&self, variable: &str, _: bool) -> Option<types::Str> { match variable { - "FOO" => Some("FOOBAR".to_owned()), + "FOO" => Some("FOOBAR".into()), _ => None, } } @@ -357,7 +358,7 @@ mod test { #[test] fn test_ends_with_succeeding() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "ends_with", variable: "$FOO", @@ -365,12 +366,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "1"); + assert_eq!(&*output, "1"); } #[test] fn test_ends_with_failing() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "ends_with", variable: "$FOO", @@ -378,12 +379,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "0"); + assert_eq!(&*output, "0"); } #[test] fn test_contains_succeeding() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "contains", variable: "$FOO", @@ -391,12 +392,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "1"); + assert_eq!(&*output, "1"); } #[test] fn test_contains_failing() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "contains", variable: "$FOO", @@ -404,12 +405,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "0"); + assert_eq!(&*output, "0"); } #[test] fn test_starts_with_succeeding() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "starts_with", variable: "$FOO", @@ -417,12 +418,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "1"); + assert_eq!(&*output, "1"); } #[test] fn test_starts_with_failing() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "starts_with", variable: "$FOO", @@ -430,12 +431,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "0"); + assert_eq!(&*output, "0"); } #[test] fn test_basename() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "basename", variable: "\"/home/redox/file.txt\"", @@ -443,12 +444,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "file.txt"); + assert_eq!(&*output, "file.txt"); } #[test] fn test_extension() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "extension", variable: "\"/home/redox/file.txt\"", @@ -456,12 +457,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "txt"); + assert_eq!(&*output, "txt"); } #[test] fn test_filename() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "filename", variable: "\"/home/redox/file.txt\"", @@ -469,12 +470,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "file"); + assert_eq!(&*output, "file"); } #[test] fn test_parent() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "parent", variable: "\"/home/redox/file.txt\"", @@ -482,12 +483,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "/home/redox"); + assert_eq!(&*output, "/home/redox"); } #[test] fn test_to_lowercase() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "to_lowercase", variable: "\"Ford Prefect\"", @@ -495,12 +496,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "ford prefect"); + assert_eq!(&*output, "ford prefect"); } #[test] fn test_to_uppercase() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "to_uppercase", variable: "\"Ford Prefect\"", @@ -508,12 +509,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "FORD PREFECT"); + assert_eq!(&*output, "FORD PREFECT"); } #[test] fn test_repeat_succeeding() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "repeat", variable: "$FOO", @@ -521,12 +522,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "FOOBARFOOBAR"); + assert_eq!(&*output, "FOOBARFOOBAR"); } #[test] fn test_repeat_failing() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "repeat", variable: "$FOO", @@ -534,12 +535,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, ""); + assert_eq!(&*output, ""); } #[test] fn test_replace_succeeding() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "replace", variable: "$FOO", @@ -547,12 +548,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "BARBAR"); + assert_eq!(&*output, "BARBAR"); } #[test] fn test_replace_failing() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "replace", variable: "$FOO", @@ -560,12 +561,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, ""); + assert_eq!(&*output, ""); } #[test] fn test_replacen_succeeding() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "replacen", variable: "\"FOO$FOO\"", @@ -573,12 +574,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "BARFOOBAR"); + assert_eq!(&*output, "BARFOOBAR"); } #[test] fn test_replacen_failing() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "replacen", variable: "$FOO", @@ -586,12 +587,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, ""); + assert_eq!(&*output, ""); } #[test] fn test_regex_replace_succeeding() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "regex_replace", variable: "$FOO", @@ -599,12 +600,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "fOOBAR"); + assert_eq!(&*output, "fOOBAR"); } #[test] fn test_regex_replace_failing() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "regex_replace", variable: "$FOO", @@ -612,12 +613,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "FOOBAR"); + assert_eq!(&*output, "FOOBAR"); } #[test] fn test_join_with_string() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "join", variable: "[\"FOO\" \"BAR\"]", @@ -625,12 +626,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "FOO BAR"); + assert_eq!(&*output, "FOO BAR"); } #[test] fn test_join_with_array() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "join", variable: "[\"FOO\" \"BAR\"]", @@ -638,12 +639,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "FOO- -BAR"); + assert_eq!(&*output, "FOO- -BAR"); } #[test] fn test_len_with_array() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "len", variable: "[\"1\"]", @@ -651,12 +652,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "1"); + assert_eq!(&*output, "1"); } #[test] fn test_len_with_string() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "len", variable: "\"FOO\"", @@ -664,12 +665,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "3"); + assert_eq!(&*output, "3"); } #[test] fn test_len_with_variable() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "len", variable: "$FOO", @@ -677,12 +678,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "6"); + assert_eq!(&*output, "6"); } #[test] fn test_len_bytes_with_variable() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "len_bytes", variable: "$FOO", @@ -690,12 +691,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "6"); + assert_eq!(&*output, "6"); } #[test] fn test_len_bytes_with_string() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "len_bytes", variable: "\"oh là là \"", @@ -703,12 +704,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "10"); + assert_eq!(&*output, "10"); } #[test] fn test_reverse_with_variable() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "reverse", variable: "$FOO", @@ -716,12 +717,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "RABOOF"); + assert_eq!(&*output, "RABOOF"); } #[test] fn test_reverse_with_string() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "reverse", variable: "\"FOOBAR\"", @@ -729,12 +730,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "RABOOF"); + assert_eq!(&*output, "RABOOF"); } #[test] fn test_find_succeeding() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "find", variable: "$FOO", @@ -742,12 +743,12 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "1"); + assert_eq!(&*output, "1"); } #[test] fn test_find_failing() { - let mut output = String::new(); + let mut output = small::String::new(); let method = StringMethod { method: "find", variable: "$FOO", @@ -755,6 +756,6 @@ mod test { selection: Select::All, }; method.handle(&mut output, &VariableExpander); - assert_eq!(output, "-1"); + assert_eq!(&*output, "-1"); } } diff --git a/src/lib/parser/shell_expand/words/tests.rs b/src/lib/parser/shell_expand/words/tests.rs index 02dea66f1e5214e4f82b993eac3e415d29bdea51..b4ac797ed4f95400204dd06e8706bc9c5de7d789 100644 --- a/src/lib/parser/shell_expand/words/tests.rs +++ b/src/lib/parser/shell_expand/words/tests.rs @@ -1,5 +1,5 @@ use super::*; -use types::{Array, Value}; +use types::{self, Array}; use ranges::{Index, Range}; struct Empty; @@ -264,10 +264,10 @@ fn test_braces() { struct WithVars; impl Expander for WithVars { - fn string(&self, var: &str, _: bool) -> Option<Value> { + fn string(&self, var: &str, _: bool) -> Option<types::Str> { match var { - "pkmn1" => "Pokémon".to_owned().into(), - "pkmn2" => "Poke\u{0301}mon".to_owned().into(), + "pkmn1" => Some("Pokémon".into()), + "pkmn2" => Some("Poke\u{0301}mon".into()), _ => None, } } diff --git a/src/lib/parser/statement/parse.rs b/src/lib/parser/statement/parse.rs index 35750efc5cd619cadc9932414772aafa9fd2c052..33b3153599f4ff07aaa36789b6d024a93891482a 100644 --- a/src/lib/parser/statement/parse.rs +++ b/src/lib/parser/statement/parse.rs @@ -4,6 +4,7 @@ use super::{ case, functions::{collect_arguments, parse_function}, }; use shell::flow_control::{Case, ElseIf, ExportAction, LocalAction, Statement}; +use small; use std::char; fn collect<F>(arguments: &str, statement: F) -> Statement @@ -128,7 +129,7 @@ pub(crate) fn parse(code: &str) -> Statement { return Statement::For { variable: variable.into(), values: ArgumentSplitter::new(cmd[3..].trim_left()) - .map(String::from) + .map(small::String::from) .collect(), statements: Vec::new(), }; @@ -183,7 +184,7 @@ pub(crate) fn parse(code: &str) -> Statement { match collect_arguments(args) { Ok(args) => { return Statement::Function { - description: description.map(String::from), + description: description.map(small::String::from), name: name.into(), args, statements: Vec::new(), @@ -233,12 +234,12 @@ mod tests { let correct_parse = Statement::If { expression: Pipeline { items: vec![PipeItem { - job: Job::new( + job: Job::new( vec![ - "test".to_owned(), - "1".to_owned(), - "-eq".to_owned(), - "2".to_owned(), + "test".into(), + "1".into(), + "-eq".into(), + "2".into(), ].into_iter() .collect(), JobKind::Last, @@ -337,7 +338,7 @@ mod tests { let parsed_if = parse("fn bob a b --bob is a nice function"); let correct_parse = Statement::Function { - description: Some("bob is a nice function".to_string()), + description: Some("bob is a nice function".into()), name: "bob".into(), args: vec![ KeyBuf { diff --git a/src/lib/shell/assignments.rs b/src/lib/shell/assignments.rs index 9f4c798ed5571a6e2eb3f718c2ac25f826e96740..fa751cec036cb93772f14110d699f9a958ab0cb3 100644 --- a/src/lib/shell/assignments.rs +++ b/src/lib/shell/assignments.rs @@ -4,7 +4,7 @@ use super::{ use itoa; use lexers::assignments::{Operator, Primitive}; use parser::assignments::*; -use smallstring::SmallString; +use small; use smallvec::SmallVec; use shell::{ history::ShellHistory, @@ -22,7 +22,7 @@ fn list_vars(shell: &Shell) { let mut buffer = BufWriter::new(stdout.lock()); // Small function for formatting and append an array entry to a string buffer. - fn print_array<W: Write>(buffer: &mut W, key: &str, array: &[String]) { + fn print_array<W: Write>(buffer: &mut W, key: &str, array: &[small::String]) { let _ = buffer.write([key, " = [ "].concat().as_bytes()); if array.len() > 1 { let mut vars = array.iter(); @@ -47,7 +47,7 @@ fn list_vars(shell: &Shell) { // Then immediately follow that with a list of array variables. let _ = buffer.write(b"\n# Array Variables\n"); for (key, val) in shell.variables.arrays() { - print_array(&mut buffer, &key, &val) + print_array(&mut buffer, &key, &**val) } } @@ -64,9 +64,9 @@ impl VariableStore for Shell { fn export(&mut self, action: ExportAction) -> i32 { let actions = match action { ExportAction::Assign(ref keys, op, ref vals) => AssignmentActions::new(keys, op, vals), - ExportAction::LocalExport(ref key) => match self.get::<types::Value>(key) { + ExportAction::LocalExport(ref key) => match self.get::<types::Str>(key) { Some(var) => { - env::set_var(key, &var); + env::set_var(key, &*var); return SUCCESS; } None => { @@ -106,10 +106,10 @@ impl VariableStore for Shell { match value_check(self, &expression, &key.kind) { Ok(VariableType::Str(value)) => { let key_name: &str = &key.name; - let lhs: String = self + let lhs: types::Str = self .variables - .get::<types::Value>(key_name) - .unwrap_or_else(|| String::from("0")); + .get::<types::Str>(key_name) + .unwrap_or_else(|| "0".into()); let result = math(&lhs, &key.kind, operator, &value, |value| { env::set_var(key_name, &OsStr::from_bytes(value)) @@ -219,7 +219,7 @@ impl VariableStore for Shell { Ok(VariableType::Array(values)) => { match self.variables.get_mut(key.name) { Some(VariableType::Array(ref mut array)) => { - let mut iterator: Box<Iterator<Item=&String>> = Box::new(array.iter()); + let mut iterator: Box<Iterator<Item=&types::Str>> = Box::new(array.iter()); for value in &values { iterator = Box::new(iterator.filter(move |item| *item != value)); } @@ -300,7 +300,7 @@ impl VariableStore for Shell { let result = math(&lhs, &key.kind, operator, &value, |value| { collected.insert(key.name, VariableType::Str(unsafe { str::from_utf8_unchecked(value) - }.to_owned())); + }.into())); }); if let Err(why) = result { @@ -344,7 +344,7 @@ impl VariableStore for Shell { } for i in 0..part.len() { - output.push(vec.extract(i).to_string()); + output.push(vec.extract(i).to_string().into()); } } @@ -404,7 +404,7 @@ impl VariableStore for Shell { Ok(VariableType::Str(ref index)) => { match self.variables.get_mut(key.name) { Some(VariableType::HashMap(hmap)) => { - hmap.entry(SmallString::from_str(index)).or_insert(VariableType::Str(value)); + hmap.entry(index.clone()).or_insert(VariableType::Str(value)); } Some(VariableType::BTreeMap(bmap)) => { bmap.entry(index.clone()).or_insert(VariableType::Str(value)); diff --git a/src/lib/shell/binary/mod.rs b/src/lib/shell/binary/mod.rs index 03bce01ed8de7f7bc7dbfce236e696bb7e5ebd35..96c41862f349ea941153011e042ff0a5abc542a7 100644 --- a/src/lib/shell/binary/mod.rs +++ b/src/lib/shell/binary/mod.rs @@ -98,11 +98,11 @@ impl Binary for Shell { let mut context = Context::new(); context.word_divider_fn = Box::new(word_divide); if "1" == self.get_str_or_empty("HISTFILE_ENABLED") { - let path = self.get::<types::Value>("HISTFILE").expect("shell didn't set HISTFILE"); - context.history.set_file_name(Some(path.clone())); + let path = self.get::<types::Str>("HISTFILE").expect("shell didn't set HISTFILE"); + context.history.set_file_name(Some(path.to_string())); if !Path::new(path.as_str()).exists() { eprintln!("ion: creating history file at \"{}\"", path); - if let Err(why) = File::create(path) { + if let Err(why) = File::create(&*path) { eprintln!("ion: could not create history file: {}", why); } } @@ -128,7 +128,7 @@ impl Binary for Shell { self.evaluate_init_file(); self.variables - .set("args", iter::once(env::args().next().unwrap()).collect::<types::Array>()); + .set("args", iter::once(env::args().next().unwrap().into()).collect::<types::Array>()); loop { if let Some(command) = self.readln() { diff --git a/src/lib/shell/binary/readln.rs b/src/lib/shell/binary/readln.rs index 8d9498495185bb2d38a9170487bca869753bffe8..e2e2610e7aa6d478c409aeff4f69b94764758891 100644 --- a/src/lib/shell/binary/readln.rs +++ b/src/lib/shell/binary/readln.rs @@ -1,11 +1,10 @@ use super::super::{completer::*, Binary, DirectoryStack, Shell, Variables}; use liner::{BasicCompleter, CursorPosition, Event, EventKind}; -use smallstring::SmallString; use std::{ env, io::{self, ErrorKind, Write}, mem, path::PathBuf, }; use sys; -use types::*; +use types; pub(crate) fn readln(shell: &mut Shell) -> Option<String> { { @@ -17,7 +16,7 @@ pub(crate) fn readln(shell: &mut Shell) -> Option<String> { // Map each underlying `liner::Buffer` into a `String`. .map(|x| x.chars().cloned().collect()) // Collect each result into a vector to avoid borrowing issues. - .collect::<Vec<SmallString>>(); + .collect::<Vec<types::Str>>(); loop { let prompt = handle_prompt(shell.prompt()).unwrap(); @@ -64,17 +63,17 @@ pub(crate) fn readln(shell: &mut Shell) -> Option<String> { // in the creation of a custom completer. let words = builtins.keys().iter() // Add built-in commands to the completer's definitions. - .map(|&s| Identifier::from(s)) + .map(|&s| s.to_string()) // Add the history list to the completer's definitions. - .chain(history.iter().cloned()) + .chain(history.iter().map(|s| s.to_string())) // Add the aliases to the completer's definitions. - .chain(vars.aliases().map(|(key, _)| key.clone())) + .chain(vars.aliases().map(|(key, _)| key.to_string())) // Add the list of available functions to the completer's definitions. - .chain(vars.functions().map(|(key, _)| key.clone())) + .chain(vars.functions().map(|(key, _)| key.to_string())) // Add the list of available variables to the completer's definitions. // TODO: We should make it free to do String->SmallString // and mostly free to go back (free if allocated) - .chain(vars.string_vars().map(|(s, _)| ["$", &s].concat().into())) + .chain(vars.string_vars().map(|(s, _)| ["$", &s].concat())) .collect(); // Initialize a new completer from the definitions collected. diff --git a/src/lib/shell/flow.rs b/src/lib/shell/flow.rs index 5a6df96df07bf6c3acb02afed325ea2f74cee40e..7da5dd095281545a3b64e1a967cb6de4a96d65f2 100644 --- a/src/lib/shell/flow.rs +++ b/src/lib/shell/flow.rs @@ -11,7 +11,7 @@ use shell::{ assignments::VariableStore, variables::VariableType, }; - +use small; use std::{ io::{stdout, Write}, iter, mem, }; @@ -48,7 +48,7 @@ pub(crate) trait FlowLogic { fn execute_for( &mut self, variable: &str, - values: &[String], + values: &[small::String], statements: Vec<Statement>, ) -> Condition; @@ -72,7 +72,7 @@ pub(crate) trait FlowLogic { /// Expand an expression and run a branch based on the value of the /// expanded expression - fn execute_match(&mut self, expression: String, cases: Vec<Case>) -> Condition; + fn execute_match(&mut self, expression: small::String, cases: Vec<Case>) -> Condition; } impl FlowLogic for Shell { @@ -357,7 +357,7 @@ impl FlowLogic for Shell { fn execute_for( &mut self, variable: &str, - values: &[String], + values: &[small::String], statements: Vec<Statement>, ) -> Condition { let ignore_variable = variable == "_"; @@ -385,7 +385,7 @@ impl FlowLogic for Shell { } }, ForExpression::Normal(values) => for value in values.lines() { - self.set(variable, value.to_string()); + self.set(variable, value); match self.execute_statements(statements.clone()) { Condition::Break => break, Condition::SigInt => return Condition::SigInt, @@ -625,7 +625,7 @@ impl FlowLogic for Shell { condition.unwrap_or(Condition::NoOp) } - fn execute_match(&mut self, expression: String, cases: Vec<Case>) -> Condition { + fn execute_match(&mut self, expression: small::String, cases: Vec<Case>) -> Condition { // Logic for determining if the LHS of a match-case construct (the value we are // matching against) matches the RHS of a match-case construct (a value // in a case statement). For example, checking to see if the value @@ -661,9 +661,9 @@ impl FlowLogic for Shell { } else { previous_bind = self .variables - .get::<types::Value>(bind) + .get::<types::Str>(bind) .map(|x| VariableType::Str(x)); - self.set(&bind, value.join(" ").to_string()); + self.set(&bind, value.join(" ")); } } @@ -701,9 +701,9 @@ impl FlowLogic for Shell { } else { previous_bind = self .variables - .get::<types::Value>(bind) + .get::<types::Str>(bind) .map(|x| VariableType::Str(x)); - self.set(&bind, value.join(" ").to_string()); + self.set(&bind, value.join(" ")); } } diff --git a/src/lib/shell/flow_control.rs b/src/lib/shell/flow_control.rs index 2515fb557f9509367aac695723e7d7618920857c..f6831ba464bfc6bda7a92c17d4a5879eb9c44b99 100644 --- a/src/lib/shell/flow_control.rs +++ b/src/lib/shell/flow_control.rs @@ -1,8 +1,9 @@ use shell::{flow::FlowLogic, Shell}; use parser::{assignments::*, pipelines::Pipeline}; +use small; use smallvec::SmallVec; use std::fmt::{self, Display, Formatter}; -use types::Identifier; +use types; use lexers::assignments::{KeyBuf, Operator, Primitive}; #[derive(Debug, PartialEq, Clone)] @@ -69,14 +70,14 @@ pub(crate) enum Statement { }, ElseIf(ElseIf), Function { - name: Identifier, - description: Option<String>, + name: types::Str, + description: Option<small::String>, args: Vec<KeyBuf>, statements: Vec<Statement>, }, For { - variable: Identifier, - values: Vec<String>, + variable: types::Str, + values: Vec<small::String>, statements: Vec<Statement>, }, While { @@ -84,7 +85,7 @@ pub(crate) enum Statement { statements: Vec<Statement>, }, Match { - expression: String, + expression: small::String, cases: Vec<Case>, }, Else, @@ -146,8 +147,8 @@ impl Default for FlowControl { #[derive(Clone, Debug, PartialEq)] pub struct Function { - description: Option<String>, - name: Identifier, + description: Option<small::String>, + name: types::Str, args: Vec<KeyBuf>, statements: Vec<Statement>, } @@ -201,7 +202,7 @@ impl Function { shell.variables.new_scope(true); for (type_, value) in values { - shell.variables.shadow(type_.name.into(), value); + shell.variables.shadow(&type_.name, value); } shell.execute_statements(self.statements); @@ -211,11 +212,11 @@ impl Function { Ok(()) } - pub(crate) fn get_description<'a>(&'a self) -> Option<&'a String> { self.description.as_ref() } + pub(crate) fn get_description<'a>(&'a self) -> Option<&'a small::String> { self.description.as_ref() } pub(crate) fn new( - description: Option<String>, - name: Identifier, + description: Option<small::String>, + name: types::Str, args: Vec<KeyBuf>, statements: Vec<Statement>, ) -> Function { diff --git a/src/lib/shell/history.rs b/src/lib/shell/history.rs index f50e8ae1dbb9df3b0f6df7f83994461fc1328a18..a88ef353d0689e4657a8d697457384ead4a4f21c 100644 --- a/src/lib/shell/history.rs +++ b/src/lib/shell/history.rs @@ -2,6 +2,7 @@ use shell::{status::*, Shell}; use regex::Regex; use std::io::{self, Write}; +use small; use types; bitflags! { @@ -40,7 +41,7 @@ impl IgnoreSetting { pub(crate) trait ShellHistory { /// Prints the commands contained within the history buffers to standard /// output. - fn print_history(&self, _arguments: &[String]) -> i32; + fn print_history(&self, _arguments: &[small::String]) -> i32; /// Sets the history size for the shell context equal to the HISTORY_SIZE shell variable if /// it @@ -125,7 +126,7 @@ impl ShellHistory for Shell { context.history.set_max_size(max_history_size); if &*variables.get_str_or_empty("HISTFILE_ENABLED") == "1" { - context.history.set_file_name(variables.get::<types::Value>("HISTFILE")); + context.history.set_file_name(variables.get::<types::Str>("HISTFILE").map(|v| v.to_string())); let max_histfile_size = variables .get_str_or_empty("HISTFILE_SIZE") @@ -137,7 +138,7 @@ impl ShellHistory for Shell { } } - fn print_history(&self, _arguments: &[String]) -> i32 { + fn print_history(&self, _arguments: &[small::String]) -> i32 { if let Some(context) = self.context.as_ref() { let mut buffer = Vec::with_capacity(8 * 1024); for command in &context.lock().unwrap().history.buffers { diff --git a/src/lib/shell/job.rs b/src/lib/shell/job.rs index 88d64ac2b6ac53e63ae6b0f99eab9ca44afa11f3..4a4b663552a5f6dd75cca596250ec16fbc4324ec 100644 --- a/src/lib/shell/job.rs +++ b/src/lib/shell/job.rs @@ -2,9 +2,8 @@ use super::Shell; use builtins::{BuiltinFunction, BUILTINS}; use parser::{expand_string, pipelines::RedirectFrom}; use shell::pipe_exec::PipelineExecution; -use smallstring::SmallString; use std::{fmt, fs::File, str}; -use types::*; +use types::{self, Array}; #[derive(Debug, PartialEq, Clone, Copy)] pub(crate) enum JobKind { @@ -16,8 +15,8 @@ pub(crate) enum JobKind { #[derive(Clone)] pub(crate) struct Job { - pub command: Identifier, - pub args: Array, + pub command: types::Str, + pub args: types::Array, pub kind: JobKind, pub builtin: Option<BuiltinFunction>, } @@ -26,14 +25,14 @@ impl Job { /// Takes the current job's arguments and expands them, one argument at a /// time, returning a new `Job` with the expanded arguments. pub(crate) fn expand(&mut self, shell: &Shell) { - let mut expanded = Array::new(); + let mut expanded = types::Array::new(); expanded.grow(self.args.len()); expanded.extend(self.args.drain().flat_map(|arg| expand_arg(&arg, shell))); self.args = expanded; } - pub(crate) fn new(args: Array, kind: JobKind) -> Self { - let command = SmallString::from_str(&args[0]); + pub(crate) fn new(args: types::Array, kind: JobKind) -> Self { + let command = args[0].clone(); let builtin = BUILTINS.get(command.as_ref()).map(|b| b.main); Job { command, @@ -61,7 +60,7 @@ impl fmt::Debug for Job { } /// Expands a given argument and returns it as an `Array`. -fn expand_arg(arg: &str, shell: &Shell) -> Array { +fn expand_arg(arg: &str, shell: &Shell) -> types::Array { let res = expand_string(&arg, shell, false); if res.is_empty() { array![""] @@ -75,8 +74,8 @@ fn expand_arg(arg: &str, shell: &Shell) -> Array { pub(crate) enum RefinedJob { /// An external program that is executed by this shell External { - name: Identifier, - args: Array, + name: types::Str, + args: types::Array, stdin: Option<File>, stdout: Option<File>, stderr: Option<File>, @@ -84,15 +83,15 @@ pub(crate) enum RefinedJob { /// A procedure embedded into Ion Builtin { main: BuiltinFunction, - args: Array, + args: types::Array, stdin: Option<File>, stdout: Option<File>, stderr: Option<File>, }, /// Functions can act as commands too! Function { - name: Identifier, - args: Array, + name: types::Str, + args: types::Array, stdin: Option<File>, stdout: Option<File>, stderr: Option<File>, @@ -236,7 +235,7 @@ impl RefinedJob { ref stdout, ref stderr, } => { - shell.exec_builtin(main, args, stdout, stderr, stdin) + shell.exec_builtin(main, &**args, stdout, stderr, stdin) } RefinedJob::Function { ref name, @@ -288,7 +287,7 @@ impl RefinedJob { } } - pub(crate) fn function(name: Identifier, args: Array) -> Self { + pub(crate) fn function(name: types::Str, args: types::Array) -> Self { RefinedJob::Function { name, args, @@ -298,7 +297,7 @@ impl RefinedJob { } } - pub(crate) fn builtin(main: BuiltinFunction, args: Array) -> Self { + pub(crate) fn builtin(main: BuiltinFunction, args: types::Array) -> Self { RefinedJob::Builtin { main, args, @@ -308,7 +307,7 @@ impl RefinedJob { } } - pub(crate) fn external(name: Identifier, args: Array) -> Self { + pub(crate) fn external(name: types::Str, args: types::Array) -> Self { RefinedJob::External { name, args, diff --git a/src/lib/shell/mod.rs b/src/lib/shell/mod.rs index 29b0bb02571249c02b644a0ce40dfe31de918eff..c06c75b94fd05124aed646026e5de26c9f936d62 100644 --- a/src/lib/shell/mod.rs +++ b/src/lib/shell/mod.rs @@ -34,7 +34,6 @@ use self::{ VariableType, } }; -use types; use builtins::{BuiltinMap, BUILTINS}; use lexers::ArgumentSplitter; use liner::Context; @@ -49,7 +48,7 @@ use std::{ sync::{atomic::Ordering, Arc, Mutex}, time::SystemTime, }; use sys; -use types::*; +use types::{self, Array}; use xdg::BaseDirectories; #[derive(Debug, Fail)] @@ -226,7 +225,7 @@ impl Shell { } /// Obtains a variable, returning an empty string if it does not exist. - pub(crate) fn get_str_or_empty(&self, name: &str) -> String { + pub(crate) fn get_str_or_empty(&self, name: &str) -> types::Str { self.variables.get_str_or_empty(name) } @@ -260,9 +259,9 @@ impl Shell { if let Some(alias) = possible_alias { let new_args = ArgumentSplitter::new(&alias) - .map(String::from) + .map(types::Str::from) .chain(item.job.args.drain().skip(1)) - .collect::<Array>(); + .collect::<types::Array>(); if let Some(builtin) = BUILTINS.get(&new_args[0]) { item.job.builtin = Some(builtin.main); } else { @@ -285,7 +284,7 @@ impl Shell { Some(SUCCESS) } else { let borrowed = &pipeline.items[0].job.args; - Some(main(&borrowed, self)) + Some(main(borrowed, self)) } } else { Some(self.execute_pipeline(pipeline)) @@ -293,7 +292,7 @@ impl Shell { // Branch else if -> input == shell function and set the exit_status } else if let Some(function) = self.variables.get::<Function>(&pipeline.items[0].job.command) { if !pipeline.requires_piping() { - let args: &[String] = pipeline.items[0].job.args.deref(); + let args = pipeline.items[0].job.args.deref(); match function.execute(self, args) { Ok(()) => None, Err(FunctionError::InvalidArgumentCount) => { @@ -321,7 +320,7 @@ impl Shell { // pipline just executed to the the file and context histories. At the // moment, this means record how long it took. if let Some(context) = self.context.as_mut() { - if "1" == self.variables.get_str_or_empty("RECORD_SUMMARY") { + if "1" == &*self.variables.get_str_or_empty("RECORD_SUMMARY") { if let Ok(elapsed_time) = command_start_time.elapsed() { let summary = format!( "#summary# elapsed real time: {}.{:09} seconds", @@ -419,7 +418,7 @@ impl Shell { impl<'a> Expander for Shell { /// Uses a subshell to expand a given command. - fn command(&self, command: &str) -> Option<Value> { + fn command(&self, command: &str) -> Option<types::Str> { let mut output = None; match self.fork(Capture::StdoutThenIgnoreStderr, move |shell| { shell.on_command(command) @@ -440,28 +439,28 @@ impl<'a> Expander for Shell { // Ensure that the parent retains ownership of the terminal before exiting. let _ = sys::tcsetpgrp(sys::STDIN_FILENO, process::id()); - output + output.map(|s| s.into()) } /// Expand a string variable given if its quoted / unquoted - fn string(&self, name: &str, quoted: bool) -> Option<Value> { + fn string(&self, name: &str, quoted: bool) -> Option<types::Str> { use ascii_helpers::AsciiReplace; if quoted { - self.get::<Value>(name) + self.get::<types::Str>(name) } else { - self.get::<Value>(name).map(|x| x.ascii_replace('\n', ' ')) + self.get::<types::Str>(name).map(|x| x.ascii_replace('\n', ' ')) } } /// Expand an array variable with some selection - fn array(&self, name: &str, selection: Select) -> Option<Array> { - if let Some(array) = self.variables.get::<Array>(name) { + fn array(&self, name: &str, selection: Select) -> Option<types::Array> { + if let Some(array) = self.variables.get::<types::Array>(name) { match selection { Select::All => return Some(array.clone()), Select::Index(id) => return id .resolve(array.len()) .and_then(|n| array.get(n)) - .map(|x| Array::from_iter(Some(x.to_owned()))), + .map(|x| types::Array::from_iter(Some(x.to_owned()))), Select::Range(range) => if let Some((start, length)) = range.bounds(array.len()) { if array.len() > start { return Some( @@ -470,23 +469,23 @@ impl<'a> Expander for Shell { .skip(start) .take(length) .map(|x| x.to_owned()) - .collect::<Array>(), + .collect::<types::Array>(), ) } } _ => (), } - } else if let Some(hmap) = self.variables.get::<HashMap>(name) { + } else if let Some(hmap) = self.variables.get::<types::HashMap>(name) { match selection { Select::All => { - let mut array = Array::new(); + let mut array = types::Array::new(); for (_, value) in hmap.iter() { let f = format!("{}", value); match *value { - VariableType::Str(_) => array.push(f), + VariableType::Str(_) => array.push(f.into()), VariableType::Array(_) | VariableType::HashMap(_) | VariableType::BTreeMap(_) => { for split in f.split_whitespace() { - array.push(split.to_owned()); + array.push(split.into()); } } _ => (), @@ -494,22 +493,22 @@ impl<'a> Expander for Shell { } return Some(array) } - Select::Key(ref key) => { - return Some(array![format!("{}", hmap.get(key).unwrap_or(&VariableType::Str("".into())))]) + Select::Key(key) => { + return Some(array![format!("{}", hmap.get(&*key).unwrap_or(&VariableType::Str("".into())))]) } _ => (), } - } else if let Some(bmap) = self.variables.get::<BTreeMap>(name) { + } else if let Some(bmap) = self.variables.get::<types::BTreeMap>(name) { match selection { Select::All => { - let mut array = Array::new(); + let mut array = types::Array::new(); for (_, value) in bmap.iter() { let f = format!("{}", value); match *value { - VariableType::Str(_) => array.push(f), + VariableType::Str(_) => array.push(f.into()), VariableType::Array(_) | VariableType::HashMap(_) | VariableType::BTreeMap(_) => { for split in f.split_whitespace() { - array.push(split.to_owned()); + array.push(split.into()); } } _ => (), @@ -517,8 +516,8 @@ impl<'a> Expander for Shell { } return Some(array) } - Select::Key(ref key) => { - return Some(array![format!("{}", bmap.get(&(&*key).to_string()).unwrap_or(&VariableType::Str("".into())))]) + Select::Key(key) => { + return Some(array![format!("{}", bmap.get(&*key).unwrap_or(&VariableType::Str("".into())))]) } _ => (), } diff --git a/src/lib/shell/pipe_exec/mod.rs b/src/lib/shell/pipe_exec/mod.rs index 06f47d41b2cf32744da08245cbbf8b6ac02f749a..99c38d2b9848aabe0400b29431adc8fdaa9296ef 100644 --- a/src/lib/shell/pipe_exec/mod.rs +++ b/src/lib/shell/pipe_exec/mod.rs @@ -26,6 +26,7 @@ use super::{ }; use builtins::{self, BuiltinFunction}; use parser::pipelines::{Input, PipeItem, Pipeline, RedirectFrom, Redirection}; +use small; use smallvec::SmallVec; use std::{ fs::{File, OpenOptions}, @@ -94,7 +95,7 @@ fn do_redirection( macro_rules! get_infile { ($input:expr) => { match $input { - Input::File(ref filename) => match File::open(filename) { + Input::File(ref filename) => match File::open(filename.as_str()) { Ok(file) => Some(file), Err(e) => { eprintln!("ion: failed to redirect '{}' to stdin: {}", filename, e); @@ -157,9 +158,9 @@ fn do_redirection( .create(true) .write(true) .append(true) - .open(&output.file) + .open(output.file.as_str()) } else { - File::create(&output.file) + File::create(output.file.as_str()) } { Ok(f) => match output.from { RedirectFrom::Stderr => $job.stderr(f), @@ -200,9 +201,9 @@ fn do_redirection( .create(true) .write(true) .append(true) - .open(&output.file) + .open(output.file.as_str()) } else { - File::create(&output.file) + File::create(output.file.as_str()) } { Ok(f) => match output.from { RedirectFrom::$teed => tee.sinks.push(f), @@ -306,9 +307,9 @@ fn do_redirection( .create(true) .write(true) .append(true) - .open(&output.file) + .open(output.file.as_str()) } else { - File::create(&output.file) + File::create(output.file.as_str()) } { Ok(f) => match output.from { RedirectFrom::Stdout => tee_out.sinks.push(f), @@ -392,7 +393,7 @@ pub(crate) trait PipelineExecution { fn exec_builtin( &mut self, main: BuiltinFunction, - args: &[String], + args: &[small::String], stdout: &Option<File>, stderr: &Option<File>, stdin: &Option<File>, @@ -612,7 +613,7 @@ impl PipelineExecution for Shell { fn exec_builtin( &mut self, main: BuiltinFunction, - args: &[String], + args: &[small::String], stdout: &Option<File>, stderr: &Option<File>, stdin: &Option<File>, @@ -987,7 +988,7 @@ fn spawn_proc( } => match unsafe { sys::fork() } { Ok(0) => { prepare_child(block_child, pgid); - let ret = shell.exec_builtin(main, &args, stdout, stderr, stdin); + let ret = shell.exec_builtin(main, args, stdout, stderr, stdin); close(stdout); close(stderr); close(stdin); diff --git a/src/lib/shell/plugins/library_iter/redox.rs b/src/lib/shell/plugins/library_iter/redox.rs index 61fed872efafc8999de48645b17372e2241b6945..72745aab3365f273ddbdb3b88b7ef258083507b5 100644 --- a/src/lib/shell/plugins/library_iter/redox.rs +++ b/src/lib/shell/plugins/library_iter/redox.rs @@ -1,5 +1,5 @@ use std::fs::ReadDir; -use types::Identifier; +use types; pub(crate) struct Library; @@ -15,7 +15,7 @@ impl LibraryIterator { impl Iterator for LibraryIterator { // The `Identifier` is the name of the namespace for which values may be pulled. // The `Library` is a handle to dynamic library loaded into memory. - type Item = (Identifier, Library); + type Item = (types::Str, Library); - fn next(&mut self) -> Option<(Identifier, Library)> { None } + fn next(&mut self) -> Option<(types::Str, Library)> { None } } diff --git a/src/lib/shell/plugins/library_iter/unix.rs b/src/lib/shell/plugins/library_iter/unix.rs index 79e9a37de72f707f1de9d715902ca06f747944e6..45b985bf29cd84b165ee2b7016eb464e5e851ded 100644 --- a/src/lib/shell/plugins/library_iter/unix.rs +++ b/src/lib/shell/plugins/library_iter/unix.rs @@ -1,6 +1,6 @@ use libloading::Library; use std::fs::ReadDir; -use types::Identifier; +use types; /// Grabs all `Library` entries found within a given directory pub(crate) struct LibraryIterator { @@ -14,9 +14,9 @@ impl LibraryIterator { impl Iterator for LibraryIterator { // The `Identifier` is the name of the namespace for which values may be pulled. // The `Library` is a handle to dynamic library loaded into memory. - type Item = (Identifier, Library); + type Item = (types::Str, Library); - fn next(&mut self) -> Option<(Identifier, Library)> { + fn next(&mut self) -> Option<(types::Str, Library)> { while let Some(entry) = self.directory.next() { let entry = if let Ok(entry) = entry { entry @@ -28,7 +28,7 @@ impl Iterator for LibraryIterator { if path.is_file() && path.extension().map_or(false, |ext| ext == "so") { // The identifier will be the file name of that file, without the extension. let identifier = match path.file_stem().unwrap().to_str() { - Some(filename) => Identifier::from(filename), + Some(filename) => types::Str::from(filename), None => { eprintln!("ion: namespace plugin has invalid filename"); continue; diff --git a/src/lib/shell/plugins/methods/redox.rs b/src/lib/shell/plugins/methods/redox.rs index 01ed5c6609fad39f96c2f09fe7b9d6e61b27d448..655c2d143038346d29867ddf608d12cc637904f7 100644 --- a/src/lib/shell/plugins/methods/redox.rs +++ b/src/lib/shell/plugins/methods/redox.rs @@ -1,8 +1,9 @@ use super::super::StringError; +use small; pub(crate) enum MethodArguments { - StringArg(String, Vec<String>), - Array(Vec<String>, Vec<String>), + StringArg(small::String, Vec<small::String>), + Array(Vec<small::String>, Vec<small::String>), NoArgs, } @@ -13,7 +14,7 @@ impl StringMethodPlugins { &self, _function: &str, _arguments: MethodArguments, - ) -> Result<Option<String>, StringError> { + ) -> Result<Option<small::String>, StringError> { Ok(None) } diff --git a/src/lib/shell/plugins/methods/unix.rs b/src/lib/shell/plugins/methods/unix.rs index 4fb3b000984917b7ae090b778a2663ba71e95a74..65720c35f3d0ab4b5f44408813dc38bb08871ad2 100644 --- a/src/lib/shell/plugins/methods/unix.rs +++ b/src/lib/shell/plugins/methods/unix.rs @@ -1,8 +1,9 @@ use super::super::{config_dir, LibraryIterator, StringError}; use fnv::FnvHashMap; use libloading::{os::unix::Symbol as RawSymbol, Library, Symbol}; +use small; use std::{ffi::CString, fs::read_dir, mem::forget, os::raw::c_char, ptr, slice, str}; -use types::Identifier; +use types; /// Either one or the other will be set. Optional status can be conveyed by setting the /// corresponding field to `NULL`. Libraries importing this structure should check for nullness. @@ -16,8 +17,8 @@ pub(crate) struct RawMethodArguments { } pub(crate) enum MethodArguments { - StringArg(String, Vec<String>), - Array(Vec<String>, Vec<String>), + StringArg(small::String, Vec<small::String>), + Array(Vec<small::String>, Vec<small::String>), NoArgs, } @@ -100,7 +101,7 @@ pub(crate) struct StringMethodPlugins { libraries: Vec<Library>, /// A map of all the symbols that were collected from the above libraries. pub symbols: - FnvHashMap<Identifier, RawSymbol<unsafe extern "C" fn(RawMethodArguments) -> *mut c_char>>, + FnvHashMap<types::Str, RawSymbol<unsafe extern "C" fn(RawMethodArguments) -> *mut c_char>>, } impl StringMethodPlugins { @@ -162,7 +163,7 @@ impl StringMethodPlugins { // Grab a slice and ensure that the name of the function is UTF-8. let slice = &symbol_list[start..counter]; let identifier = str::from_utf8(slice) - .map(Identifier::from) + .map(types::Str::from) .map_err(|_| StringError::UTF8Function)?; // To obtain the symbol, we need to create a new `\0`-ended byte array. @@ -193,7 +194,7 @@ impl StringMethodPlugins { if counter != start { let slice = &symbol_list[start..]; let identifier = str::from_utf8(slice) - .map(Identifier::from) + .map(types::Str::from) .map_err(|_| StringError::UTF8Function)?; let mut symbol = Vec::new(); symbol.reserve_exact(slice.len() + 1); diff --git a/src/lib/shell/plugins/namespaces/redox.rs b/src/lib/shell/plugins/namespaces/redox.rs index b6667b31f65115af43583b0bb75d1a8318d42383..787565379d67e003d15990da133565c612d30b29 100644 --- a/src/lib/shell/plugins/namespaces/redox.rs +++ b/src/lib/shell/plugins/namespaces/redox.rs @@ -1,19 +1,19 @@ use fnv::FnvHashMap; use super::super::StringError; -use types::Identifier; +use types; pub(crate) struct StringNamespace; impl StringNamespace { - pub(crate) fn execute(&self, _function: Identifier) -> Result<Option<String>, StringError> { + pub(crate) fn execute(&self, _function: types::Str) -> Result<Option<types::Str>, StringError> { Ok(None) } pub(crate) fn new() -> Result<StringNamespace, StringError> { Ok(StringNamespace) } } -pub(crate) fn collect() -> FnvHashMap<Identifier, StringNamespace> { +pub(crate) fn collect() -> FnvHashMap<types::Str, StringNamespace> { eprintln!("ion: Redox doesn't support plugins yet"); FnvHashMap::default() } diff --git a/src/lib/shell/plugins/namespaces/unix.rs b/src/lib/shell/plugins/namespaces/unix.rs index 53e091cef7464ddff46d36b5a0aaba23a28eb696..9e4d5e33853ad2bc646a595c31b00ba5777cc357 100644 --- a/src/lib/shell/plugins/namespaces/unix.rs +++ b/src/lib/shell/plugins/namespaces/unix.rs @@ -2,7 +2,7 @@ use super::super::{config_dir, LibraryIterator, StringError}; use fnv::FnvHashMap; use libloading::{os::unix::Symbol as RawSymbol, Library, Symbol}; use std::{ffi::CString, fs::read_dir, os::raw::c_char, slice, str}; -use types::Identifier; +use types; /// A dynamically-loaded string namespace from an external library. /// @@ -18,7 +18,7 @@ pub(crate) struct StringNamespace { library: Library, /// A hash map of symbols collected from the `Library` stored in the `library` field. /// These are considered raw because they have their lifetimes erased. - symbols: FnvHashMap<Identifier, RawSymbol<unsafe extern "C" fn() -> *mut c_char>>, + symbols: FnvHashMap<types::Str, RawSymbol<unsafe extern "C" fn() -> *mut c_char>>, } impl StringNamespace { @@ -26,7 +26,7 @@ impl StringNamespace { /// /// If the function exists, it is executed, and it's return value is then converted into a /// proper Rusty type. - pub(crate) fn execute(&self, function: Identifier) -> Result<Option<String>, StringError> { + pub(crate) fn execute(&self, function: types::Str) -> Result<Option<String>, StringError> { let func = self .symbols .get(&function) @@ -77,7 +77,7 @@ impl StringNamespace { // Grab a slice and ensure that the name of the function is UTF-8. let slice = &symbol_list[start..counter]; let identifier = str::from_utf8(slice) - .map(Identifier::from) + .map(types::Str::from) .map_err(|_| StringError::UTF8Function)?; // To obtain the symbol, we need to create a new `\0`-ended byte array. @@ -108,7 +108,7 @@ impl StringNamespace { if counter != start { let slice = &symbol_list[start..]; let identifier = str::from_utf8(slice) - .map(Identifier::from) + .map(types::Str::from) .map_err(|_| StringError::UTF8Function)?; let mut symbol = Vec::new(); symbol.reserve_exact(slice.len() + 1); @@ -130,7 +130,7 @@ impl StringNamespace { /// /// This function is meant to be called with `lazy_static` to ensure that there isn't a /// cost to collecting all this information when the shell never uses it in the first place! -pub(crate) fn collect() -> FnvHashMap<Identifier, StringNamespace> { +pub(crate) fn collect() -> FnvHashMap<types::Str, StringNamespace> { let mut hashmap = FnvHashMap::default(); if let Some(mut path) = config_dir() { path.push("namespaces"); diff --git a/src/lib/shell/plugins/string.rs b/src/lib/shell/plugins/string.rs index 656d64252138bd3a2ef1b59d4da99632b0ae3c5e..20b90efbe2e4a08debd96f35e3b349bfda04493b 100644 --- a/src/lib/shell/plugins/string.rs +++ b/src/lib/shell/plugins/string.rs @@ -1,7 +1,7 @@ use std::{ fmt::{self, Display, Formatter}, io, }; -use types::Identifier; +use types; #[derive(Debug)] /// A possible error that can be caused when attempting to obtain or execute a @@ -18,7 +18,7 @@ pub(crate) enum StringError { UTF8Result, /// This infers that the user called a function that doesn't exist in the library. Bad /// user, bad. - FunctionMissing(Identifier), + FunctionMissing(types::Str), } impl Display for StringError { diff --git a/src/lib/shell/variables/mod.rs b/src/lib/shell/variables/mod.rs index a8290780aabc6601e037d1ad431a4b2cb6011ddf..c1b7adf7e6247ab0272cd96e315294976d141844 100644 --- a/src/lib/shell/variables/mod.rs +++ b/src/lib/shell/variables/mod.rs @@ -7,7 +7,6 @@ use super::{ }; use fnv::FnvHashMap; use liner::Context; -use smallstring::SmallString; use std::{ any::TypeId, env, @@ -17,68 +16,66 @@ use std::{ ops::{Deref, DerefMut} }; use sys::{self, geteuid, getpid, getuid, is_root, variables as self_sys, env as sys_env}; -use types::{ - self, Alias, Array, BTreeMap, HashMap, Identifier, Key, Value, -}; +use types::{self, Array}; use unicode_segmentation::UnicodeSegmentation; use xdg::BaseDirectories; lazy_static! { - static ref STRING_NAMESPACES: FnvHashMap<Identifier, StringNamespace> = namespaces::collect(); + static ref STRING_NAMESPACES: FnvHashMap<types::Str, StringNamespace> = namespaces::collect(); } #[derive(Clone, Debug, PartialEq)] pub enum VariableType { - Str(Value), - Alias(Alias), - Array(Array), - HashMap(HashMap), - BTreeMap(BTreeMap), + Str(types::Str), + Alias(types::Alias), + Array(types::Array), + HashMap(types::HashMap), + BTreeMap(types::BTreeMap), Function(Function), None, } -impl From<VariableType> for String { +impl From<VariableType> for types::Str { fn from(var: VariableType) -> Self { match var { VariableType::Str(string) => string, - _ => String::with_capacity(0), + _ => types::Str::with_capacity(0), } } } -impl From<VariableType> for Alias { +impl From<VariableType> for types::Alias { fn from(var: VariableType) -> Self { match var { VariableType::Alias(alias) => alias, - _ => Alias::empty(), + _ => types::Alias::empty(), } } } -impl From<VariableType> for Array { +impl From<VariableType> for types::Array { fn from(var: VariableType) -> Self { match var { VariableType::Array(array) => array, - _ => Array::with_capacity(0), + _ => types::Array::with_capacity(0), } } } -impl From<VariableType> for HashMap { +impl From<VariableType> for types::HashMap { fn from(var: VariableType) -> Self { match var { VariableType::HashMap(hash_map) => hash_map, - _ => HashMap::with_capacity_and_hasher(0, Default::default()), + _ => types::HashMap::with_capacity_and_hasher(0, Default::default()), } } } -impl From<VariableType> for BTreeMap { +impl From<VariableType> for types::BTreeMap { fn from(var: VariableType) -> Self { match var { VariableType::BTreeMap(btree_map) => btree_map, - _ => BTreeMap::new(), + _ => types::BTreeMap::new(), } } } @@ -92,33 +89,45 @@ impl From<VariableType> for Function { } } +impl<'a> From<&'a str> for VariableType { + fn from(string: &'a str) -> Self { + VariableType::Str(string.into()) + } +} + +impl From<types::Str> for VariableType { + fn from(string: types::Str) -> Self { + VariableType::Str(string) + } +} + impl From<String> for VariableType { fn from(string: String) -> Self { - VariableType::Str(string) + VariableType::Str(string.into()) } } -impl From<Alias> for VariableType { - fn from(alias: Alias) -> Self { +impl From<types::Alias> for VariableType { + fn from(alias: types::Alias) -> Self { VariableType::Alias(alias) } } -impl From<Array> for VariableType { - fn from(array: Array) -> Self { +impl From<types::Array> for VariableType { + fn from(array: types::Array) -> Self { VariableType::Array(array) } } -impl From<HashMap> for VariableType { - fn from(hash_map: HashMap) -> Self { - VariableType::HashMap(hash_map) +impl From<types::HashMap> for VariableType { + fn from(hmap: types::HashMap) -> Self { + VariableType::HashMap(hmap) } } -impl From<BTreeMap> for VariableType { - fn from(btree_map: BTreeMap) -> Self { - VariableType::BTreeMap(btree_map) +impl From<types::BTreeMap> for VariableType { + fn from(bmap: types::BTreeMap) -> Self { + VariableType::BTreeMap(bmap) } } @@ -159,14 +168,14 @@ impl fmt::Display for VariableType { #[derive(Clone, Debug)] pub struct Scope { - vars: FnvHashMap<Identifier, VariableType>, + vars: FnvHashMap<types::Str, VariableType>, /// This scope is on a namespace boundary. /// Any previous scopes need to be accessed through `super::`. namespace: bool } impl Deref for Scope { - type Target = FnvHashMap<Identifier, VariableType>; + type Target = FnvHashMap<types::Str, VariableType>; fn deref(&self) -> &Self::Target { &self.vars } @@ -187,7 +196,7 @@ pub struct Variables { impl Default for Variables { fn default() -> Self { - let mut map: FnvHashMap<Identifier, VariableType> = FnvHashMap::with_capacity_and_hasher(64, Default::default()); + let mut map: FnvHashMap<types::Str, VariableType> = FnvHashMap::with_capacity_and_hasher(64, Default::default()); map.insert("DIRECTORY_STACK_SIZE".into(), VariableType::Str("1000".into())); map.insert("HISTORY_SIZE".into(), VariableType::Str("1000".into())); map.insert("HISTFILE_SIZE".into(), VariableType::Str("100000".into())); @@ -204,15 +213,15 @@ impl Default for Variables { // Set the PID, UID, and EUID variables. map.insert( "PID".into(), - VariableType::Str(getpid().ok().map_or("?".into(), |id| id.to_string())), + VariableType::Str(getpid().ok().map_or("?".into(), |id| id.to_string().into())), ); map.insert( "UID".into(), - VariableType::Str(getuid().ok().map_or("?".into(), |id| id.to_string())), + VariableType::Str(getuid().ok().map_or("?".into(), |id| id.to_string().into())), ); map.insert( "EUID".into(), - VariableType::Str(geteuid().ok().map_or("?".into(), |id| id.to_string())), + VariableType::Str(geteuid().ok().map_or("?".into(), |id| id.to_string().into())), ); // Initialize the HISTFILE variable @@ -296,8 +305,8 @@ impl Variables { None } - pub fn shadow(&mut self, name: SmallString, value: VariableType) -> Option<VariableType> { - self.scopes[self.current].insert(name, value) + pub fn shadow(&mut self, name: &str, value: VariableType) -> Option<VariableType> { + self.scopes[self.current].insert(name.into(), value) } pub fn get_ref(&self, mut name: &str) -> Option<&VariableType> { @@ -353,24 +362,6 @@ impl Variables { None } - #[allow(dead_code)] - pub(crate) fn is_hashmap_reference(key: &str) -> Option<(Identifier, Key)> { - let mut key_iter = key.split('['); - - if let Some(map_name) = key_iter.next() { - if Variables::is_valid_variable_name(map_name) { - if let Some(mut inner_key) = key_iter.next() { - if inner_key.ends_with(']') { - inner_key = inner_key.split(']').next().unwrap_or(""); - inner_key = inner_key.trim_matches(|c| c == '\'' || c == '\"'); - return Some((map_name.into(), inner_key.into())); - } - } - } - } - None - } - pub(crate) fn tilde_expansion(&self, word: &str, dir_stack: &DirectoryStack) -> Option<String> { let mut chars = word.char_indices(); @@ -399,8 +390,8 @@ impl Variables { Ok(var) => var + remainder, _ => ["?", remainder].concat() }), - "-" => if let Some(oldpwd) = self.get::<Value>("OLDPWD") { - return Some(oldpwd.clone() + remainder); + "-" => if let Some(oldpwd) = self.get::<types::Str>("OLDPWD") { + return Some(oldpwd.to_string() + remainder); }, _ => { let neg; @@ -446,7 +437,7 @@ impl Variables { c.is_alphanumeric() || c == '_' || c == '?' || c == '.' || c == '-' || c == '+' } - pub fn string_vars(&self) -> impl Iterator<Item = (&SmallString, &Value)> { + pub fn string_vars(&self) -> impl Iterator<Item = (&types::Str, &types::Str)> { self.scopes() .map(|map| { map.iter() @@ -459,14 +450,14 @@ impl Variables { .flat_map(|f| f) } - pub fn get_str_or_empty(&self, name: &str) -> String { - self.get::<String>(name).unwrap_or_default() + pub fn get_str_or_empty(&self, name: &str) -> types::Str { + self.get::<types::Str>(name).unwrap_or_default() } pub fn get<T: Clone + From<VariableType> + 'static>(&self, name: &str) -> Option<T> { let specified_type = TypeId::of::<T>(); - if specified_type == TypeId::of::<types::Value>() { + if specified_type == TypeId::of::<types::Str>() { match name { "MWD" => return Some(T::from(VariableType::Str(self.get_minimal_directory()))), "SWD" => return Some(T::from(VariableType::Str(self.get_simplified_directory()))), @@ -475,9 +466,9 @@ impl Variables { // If the parsed name contains the '::' pattern, then a namespace was // designated. Find it. match name.find("::").map(|pos| (&name[..pos], &name[pos + 2..])) { - Some(("c", variable)) | Some(("color", variable)) => Colors::collect(variable).into_string().map(|s| T::from(VariableType::Str(s))), + Some(("c", variable)) | Some(("color", variable)) => Colors::collect(variable).into_string().map(|s| T::from(VariableType::Str(s.into()))), Some(("x", variable)) | Some(("hex", variable)) => match u8::from_str_radix(variable, 16) { - Ok(c) => Some(T::from(VariableType::Str((c as char).to_string()))), + Ok(c) => Some(T::from(VariableType::Str((c as char).to_string().into()))), Err(why) => { eprintln!("ion: hex parse error: {}: {}", variable, why); None @@ -488,7 +479,7 @@ impl Variables { // Otherwise, it's just a simple variable name. match self.get_ref(name) { Some(VariableType::Str(val)) => Some(T::from(VariableType::Str(val.clone()))), - _ => env::var(name).ok().map(|s| T::from(VariableType::Str(s))), + _ => env::var(name).ok().map(|s| T::from(VariableType::Str(s.into()))), } }, Some((_, variable)) => { @@ -511,7 +502,7 @@ impl Variables { // Attempt to execute the given function from that namespace, and map it's // results. match namespace.execute(variable.into()) { - Ok(value) => value.map(|s| T::from(VariableType::Str(s))), + Ok(value) => value.map(|s| T::from(VariableType::Str(s.into()))), Err(why) => { eprintln!("ion: string namespace error: {}: {}", name, why); None @@ -627,7 +618,7 @@ impl Variables { } } - pub fn aliases(&self) -> impl Iterator<Item = (&SmallString, &Value)> { + pub fn aliases(&self) -> impl Iterator<Item = (&types::Str, &types::Str)> { self.scopes.iter().rev() .map(|map| { map.iter() @@ -640,7 +631,7 @@ impl Variables { .flat_map(|f| f) } - pub fn functions(&self) -> impl Iterator<Item = (&SmallString, &Function)> { + pub fn functions(&self) -> impl Iterator<Item = (&types::Str, &Function)> { self.scopes.iter().rev() .map(|map| { map.iter() @@ -658,7 +649,7 @@ impl Variables { /// Further minimizes the directory path in the same manner that Fish does by default. /// That is, if more than two parents are visible in the path, all parent directories /// of the current directory will be reduced to a single character. - fn get_minimal_directory(&self) -> Value { + fn get_minimal_directory(&self) -> types::Str { let swd = self.get_simplified_directory(); { @@ -670,7 +661,7 @@ impl Variables { .filter(|s| !s.is_empty()) .collect::<Vec<&str>>(); if elements.len() > 2 { - let mut output = String::new(); + let mut output = types::Str::new(); for element in &elements[0..elements.len() - 1] { let mut segmenter = UnicodeSegmentation::graphemes(*element, true); let grapheme = segmenter.next().unwrap(); @@ -692,17 +683,16 @@ impl Variables { /// /// Useful for getting smaller prompts, this will produce a simplified variant of the /// working directory which the leading `HOME` prefix replaced with a tilde character. - fn get_simplified_directory(&self) -> Value { - let home = match self.get::<Value>("HOME") { + fn get_simplified_directory(&self) -> types::Str { + let home = match self.get::<types::Str>("HOME") { Some(string) => string, - None => String::from("?"), + None => "?".into(), }; - env::var("PWD") - .unwrap() - .replace(&home, "~") + + env::var("PWD").unwrap().replace(&*home, "~").into() } - pub fn arrays(&self) -> impl Iterator<Item = (&SmallString, &Array)> { + pub fn arrays(&self) -> impl Iterator<Item = (&types::Str, &types::Array)> { self.scopes.iter().rev() .map(|map| { map.iter() @@ -724,7 +714,7 @@ impl Variables { for arg in args.into_iter().skip(1) { match con.read_line(format!("{}=", arg.as_ref().trim()), None, &mut |_| {}) { Ok(buffer) => { - self.set(arg.as_ref(), buffer.trim().to_string()); + self.set(arg.as_ref(), buffer.trim()); } Err(_) => return FAILURE, } @@ -735,7 +725,7 @@ impl Variables { let mut lines = handle.lines(); for arg in args.into_iter().skip(1) { if let Some(Ok(line)) = lines.next() { - self.set(arg.as_ref(), line.trim().to_string()); + self.set(arg.as_ref(), line.trim()); } } } @@ -757,8 +747,8 @@ mod tests { struct VariableExpander(pub Variables); impl Expander for VariableExpander { - fn string(&self, var: &str, _: bool) -> Option<Value> { - self.0.get::<Value>(var) + fn string(&self, var: &str, _: bool) -> Option<types::Str> { + self.0.get::<types::Str>(var) } } @@ -772,28 +762,18 @@ mod tests { #[test] fn set_var_and_expand_a_variable() { let mut variables = Variables::default(); - variables.set("FOO", "BAR".to_string()); + variables.set("FOO", "BAR"); let expanded = expand_string("$FOO", &VariableExpander(variables), false).join(""); assert_eq!("BAR", &expanded); } - #[test] - fn decompose_map_reference() { - if let Some((map_name, inner_key)) = Variables::is_hashmap_reference("map[\'key\']") { - assert!(map_name == "map".into()); - assert!(inner_key == "key".into()); - } else { - assert!(false); - } - } - #[test] fn minimal_directory_var_should_compact_path() { let variables = Variables::default(); env::set_var("PWD", "/var/log/nix"); assert_eq!( - "v/l/nix", - match variables.get::<Value>("MWD") { + types::Str::from("v/l/nix"), + match variables.get::<types::Str>("MWD") { Some(string) => string, None => panic!("no value returned") } @@ -805,8 +785,8 @@ mod tests { let variables = Variables::default(); env::set_var("PWD", "/var/log"); assert_eq!( - "/var/log", - match variables.get::<Value>("MWD") { + types::Str::from("/var/log"), + match variables.get::<types::Str>("MWD") { Some(string) => string, None => panic!("no value returned") } diff --git a/src/lib/types.rs b/src/lib/types.rs index 3a5b6944f99d190ee8941033c58f13253bc59c68..643c57a2093fe8b135884892bcca19fa57c77909 100644 --- a/src/lib/types.rs +++ b/src/lib/types.rs @@ -1,27 +1,25 @@ use fnv::FnvHashMap; -use smallstring::SmallString; +use small; use smallvec::SmallVec; use shell::variables::VariableType; use std::{collections::BTreeMap as StdBTreeMap, ops::{Deref, DerefMut}}; -pub type Array = SmallVec<[Value; 4]>; -pub type HashMap = FnvHashMap<Key, VariableType>; -pub type BTreeMap = StdBTreeMap<String, VariableType>; -pub type Identifier = SmallString; -pub type Key = SmallString; -pub type Value = String; +pub type Array = SmallVec<[Str; 4]>; +pub type HashMap = FnvHashMap<Str, VariableType>; +pub type BTreeMap = StdBTreeMap<Str, VariableType>; +pub type Str = small::String; #[derive(Clone, Debug, PartialEq)] -pub struct Alias(pub String); +pub struct Alias(pub Str); impl Alias { pub fn empty() -> Self { - Alias(String::with_capacity(0)) + Alias(Str::with_capacity(0)) } } impl Deref for Alias { - type Target = String; + type Target = Str; fn deref(&self) -> &Self::Target { &self.0 @@ -34,8 +32,8 @@ impl DerefMut for Alias { } } -impl Into<String> for Alias { - fn into(self) -> String { +impl Into<Str> for Alias { + fn into(self) -> Str { self.0 } }