Commit d8a6a3b5 authored by stratact's avatar stratact Committed by Michael Aaron Murphy
Browse files

Use `small::String` for every string type

parent a7516959
......@@ -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"
......
......@@ -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" }
......
......@@ -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"] }
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"),
]
);
}
}
......@@ -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"
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() {
......
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
......
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);
......
......@@ -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;
......
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 {
......
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!(
......
......@@ -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"] }
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(),