mirror of
https://github.com/uutils/coreutils.git
synced 2026-06-10 15:48:22 -07:00
Merge branch 'master' of github.com:uutils/coreutils into refactoring_parse_size
* truncate: use "parse_size" from uucore * workaround fix for "test_reference"
This commit is contained in:
@@ -11,7 +11,7 @@ env:
|
||||
PROJECT_NAME: coreutils
|
||||
PROJECT_DESC: "Core universal (cross-platform) utilities"
|
||||
PROJECT_AUTH: "uutils"
|
||||
RUST_MIN_SRV: "1.40.0" ## v1.40.0
|
||||
RUST_MIN_SRV: "1.43.1" ## v1.43.0
|
||||
RUST_COV_SRV: "2020-08-01" ## (~v1.47.0) supported rust version for code coverage; (date required/used by 'coverage') ## !maint: refactor when code coverage support is included in the stable channel
|
||||
|
||||
on: [push, pull_request]
|
||||
@@ -84,7 +84,7 @@ jobs:
|
||||
- name: Install `rust` toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
toolchain: nightly
|
||||
default: true
|
||||
profile: minimal # minimal component installation (ie, no documentation)
|
||||
components: clippy
|
||||
@@ -94,7 +94,7 @@ jobs:
|
||||
run: |
|
||||
# `clippy` testing
|
||||
# * convert any warnings to GHA UI annotations; ref: <https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message>
|
||||
S=$(cargo clippy ${{ matrix.job.cargo-options }} ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} -- -D warnings 2>&1) && printf "%s\n" "$S" || { printf "%s\n" "$S" ; printf "%s" "$S" | sed -E -n -e '/^error:/{' -e "N; s/^error:[[:space:]]+(.*)\\n[[:space:]]+-->[[:space:]]+(.*):([0-9]+):([0-9]+).*$/::warning file=\2,line=\3,col=\4::WARNING: \`cargo clippy\`: \1/p;" -e '}' ; }
|
||||
S=$(cargo +nightly clippy --all-targets ${{ matrix.job.cargo-options }} ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} -- -D warnings 2>&1) && printf "%s\n" "$S" || { printf "%s\n" "$S" ; printf "%s" "$S" | sed -E -n -e '/^error:/{' -e "N; s/^error:[[:space:]]+(.*)\\n[[:space:]]+-->[[:space:]]+(.*):([0-9]+):([0-9]+).*$/::warning file=\2,line=\3,col=\4::WARNING: \`cargo clippy\`: \1/p;" -e '}' ; }
|
||||
|
||||
min_version:
|
||||
name: MinRustV # Minimum supported rust version
|
||||
@@ -614,3 +614,20 @@ jobs:
|
||||
flags: ${{ steps.vars.outputs.CODECOV_FLAGS }}
|
||||
name: codecov-umbrella
|
||||
fail_ci_if_error: false
|
||||
spellcheck:
|
||||
name: Spell Check
|
||||
runs-on: ${{ matrix.job.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
job:
|
||||
- { os: ubuntu-latest }
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Install/setup prerequisites
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get -y update ; sudo apt-get -y install npm ; sudo npm install cspell -g;
|
||||
- name: Run `cspell`
|
||||
shell: bash
|
||||
run: |
|
||||
cspell --config .vscode/cSpell.json --no-summary --no-progress $( git ls-files | grep "\.\(rs\|md\)" ) | sed "s/\(.*\):\(.*\):\(.*\) - \(.*\)/::warning file=\1,line=\2,col=\3::cspell: \4/" || true
|
||||
|
||||
+15
-6
@@ -1,8 +1,17 @@
|
||||
# https://pre-commit.com
|
||||
repos:
|
||||
- repo: https://github.com/doublify/pre-commit-rust
|
||||
rev: v1.0
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: cargo-check
|
||||
- id: clippy
|
||||
- id: fmt
|
||||
- id: rust-linting
|
||||
name: Rust linting
|
||||
description: Run cargo fmt on files included in the commit.
|
||||
entry: cargo +nightly fmt --
|
||||
pass_filenames: true
|
||||
types: [file, rust]
|
||||
language: system
|
||||
- id: rust-clippy
|
||||
name: Rust clippy
|
||||
description: Run cargo clippy on files included in the commit.
|
||||
entry: cargo +nightly clippy --all-targets --all-features --
|
||||
pass_filenames: false
|
||||
types: [file, rust]
|
||||
language: system
|
||||
|
||||
Generated
+212
-332
File diff suppressed because it is too large
Load Diff
+4
-5
@@ -325,7 +325,8 @@ who = { optional=true, version="0.0.6", package="uu_who", path="src/uu/who"
|
||||
whoami = { optional=true, version="0.0.6", package="uu_whoami", path="src/uu/whoami" }
|
||||
yes = { optional=true, version="0.0.6", package="uu_yes", path="src/uu/yes" }
|
||||
|
||||
factor_benches = { optional = true, version = "0.0.0", package = "uu_factor_benches", path = "tests/benches/factor" }
|
||||
# this breaks clippy linting with: "tests/by-util/test_factor_benches.rs: No such file or directory (os error 2)"
|
||||
# factor_benches = { optional = true, version = "0.0.0", package = "uu_factor_benches", path = "tests/benches/factor" }
|
||||
|
||||
#
|
||||
# * pinned transitive dependencies
|
||||
@@ -342,14 +343,12 @@ pretty_assertions = "0.7.2"
|
||||
rand = "0.7"
|
||||
regex = "1.0"
|
||||
sha1 = { version="0.6", features=["std"] }
|
||||
## tempfile 3.2 depends on recent version of rand which depends on getrandom v0.2 which has compiler errors for MinRustV v1.32.0
|
||||
## min dep for tempfile = Rustc 1.40
|
||||
tempfile = "= 3.1.0"
|
||||
tempfile = "3.2.0"
|
||||
time = "0.1"
|
||||
unindent = "0.1"
|
||||
uucore = { version=">=0.0.8", package="uucore", path="src/uucore", features=["entries"] }
|
||||
walkdir = "2.2"
|
||||
tempdir = "0.3"
|
||||
atty = "0.2.14"
|
||||
|
||||
[target.'cfg(unix)'.dev-dependencies]
|
||||
rust-users = { version="0.10", package="users" }
|
||||
|
||||
@@ -21,7 +21,7 @@ if changes are not reflected in the report then run `cargo clean` and run the a
|
||||
|
||||
### Using Stable Rust
|
||||
|
||||
If you are using stable version of Rust that doesn't enable code coverage instrumentation by default
|
||||
If you are using stable version of Rust that doesn't enable code coverage instrumentation by default
|
||||
then add `-Z-Zinstrument-coverage` flag to `RUSTFLAGS` env variable specified above.
|
||||
|
||||
|
||||
@@ -36,3 +36,7 @@ To use the provided hook:
|
||||
2. Run `pre-commit install` while in the repository directory
|
||||
|
||||
Your git commits will then automatically be checked. If a check fails, an error message will explain why, and your commit will be canceled. You can then make the suggested changes, and run `git commit ...` again.
|
||||
|
||||
### Using Clippy
|
||||
|
||||
The `msrv` key in the clippy configuration file `clippy.toml` is used to disable lints pertaining to newer features by specifying the minimum supported Rust version (MSRV). However, this key is only supported on `nightly`. To invoke clippy without errors, use `cargo +nightly clippy`. In order to also check tests and non-default crate features, use `cargo +nightly clippy --all-targets --all-features`.
|
||||
|
||||
@@ -39,7 +39,7 @@ to compile anywhere, and this is as good a way as any to try and learn it.
|
||||
### Rust Version
|
||||
|
||||
uutils follows Rust's release channels and is tested against stable, beta and nightly.
|
||||
The current oldest supported version of the Rust compiler is `1.40.0`.
|
||||
The current oldest supported version of the Rust compiler is `1.43.1`.
|
||||
|
||||
On both Windows and Redox, only the nightly version is tested currently.
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
msrv = "1.43.1"
|
||||
@@ -136,7 +136,8 @@ fn basename(fullname: &str, suffix: &str) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::manual_strip)] // can be replaced with strip_suffix once the minimum rust version is 1.45
|
||||
// can be replaced with strip_suffix once MSRV is 1.45
|
||||
#[allow(clippy::manual_strip)]
|
||||
fn strip_suffix(name: &str, suffix: &str) -> String {
|
||||
if name == suffix {
|
||||
return name.to_owned();
|
||||
|
||||
+10
-6
@@ -232,6 +232,7 @@ fn get_usage() -> String {
|
||||
static OPT_ARCHIVE: &str = "archive";
|
||||
static OPT_ATTRIBUTES_ONLY: &str = "attributes-only";
|
||||
static OPT_BACKUP: &str = "backup";
|
||||
static OPT_BACKUP_NO_ARG: &str = "b";
|
||||
static OPT_CLI_SYMBOLIC_LINKS: &str = "cli-symbolic-links";
|
||||
static OPT_CONTEXT: &str = "context";
|
||||
static OPT_COPY_CONTENTS: &str = "copy-contents";
|
||||
@@ -357,7 +358,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||
.help("remove each existing destination file before attempting to open it \
|
||||
(contrast with --force). On Windows, current only works for writeable files."))
|
||||
.arg(Arg::with_name(OPT_BACKUP)
|
||||
.short("b")
|
||||
.long(OPT_BACKUP)
|
||||
.help("make a backup of each existing destination file")
|
||||
.takes_value(true)
|
||||
@@ -366,6 +366,10 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||
.possible_values(backup_control::BACKUP_CONTROL_VALUES)
|
||||
.value_name("CONTROL")
|
||||
)
|
||||
.arg(Arg::with_name(OPT_BACKUP_NO_ARG)
|
||||
.short(OPT_BACKUP_NO_ARG)
|
||||
.help("like --backup but does not accept an argument")
|
||||
)
|
||||
.arg(Arg::with_name(OPT_SUFFIX)
|
||||
.short("S")
|
||||
.long(OPT_SUFFIX)
|
||||
@@ -592,7 +596,7 @@ impl Options {
|
||||
|| matches.is_present(OPT_ARCHIVE);
|
||||
|
||||
let backup_mode = backup_control::determine_backup_mode(
|
||||
matches.is_present(OPT_BACKUP),
|
||||
matches.is_present(OPT_BACKUP_NO_ARG) || matches.is_present(OPT_BACKUP),
|
||||
matches.value_of(OPT_BACKUP),
|
||||
);
|
||||
let backup_suffix = backup_control::determine_backup_suffix(matches.value_of(OPT_SUFFIX));
|
||||
@@ -665,8 +669,8 @@ impl Options {
|
||||
}
|
||||
},
|
||||
backup: backup_mode,
|
||||
backup_suffix: backup_suffix,
|
||||
overwrite: overwrite,
|
||||
backup_suffix,
|
||||
overwrite,
|
||||
no_target_dir,
|
||||
preserve_attributes,
|
||||
recursive,
|
||||
@@ -1085,7 +1089,7 @@ fn copy_attribute(source: &Path, dest: &Path, attribute: &Attribute) -> CopyResu
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
#[allow(clippy::unnecessary_wraps)] // needed for windows version
|
||||
#[allow(clippy::unnecessary_unwrap)] // needed for windows version
|
||||
fn symlink_file(source: &Path, dest: &Path, context: &str) -> CopyResult<()> {
|
||||
match std::os::unix::fs::symlink(source, dest).context(context) {
|
||||
Ok(_) => Ok(()),
|
||||
@@ -1104,7 +1108,7 @@ fn context_for(src: &Path, dest: &Path) -> String {
|
||||
|
||||
/// Implements a simple backup copy for the destination file.
|
||||
/// TODO: for the backup, should this function be replaced by `copy_file(...)`?
|
||||
fn backup_dest(dest: &Path, backup_path: &PathBuf) -> CopyResult<PathBuf> {
|
||||
fn backup_dest(dest: &Path, backup_path: &Path) -> CopyResult<PathBuf> {
|
||||
fs::copy(dest, &backup_path)?;
|
||||
Ok(backup_path.into())
|
||||
}
|
||||
|
||||
@@ -124,12 +124,7 @@ where
|
||||
// split the file based on patterns
|
||||
for pattern in patterns.into_iter() {
|
||||
let pattern_as_str = pattern.to_string();
|
||||
#[allow(clippy::match_like_matches_macro)]
|
||||
let is_skip = if let patterns::Pattern::SkipToMatch(_, _, _) = pattern {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let is_skip = matches!(pattern, patterns::Pattern::SkipToMatch(_, _, _));
|
||||
match pattern {
|
||||
patterns::Pattern::UpToLine(n, ex) => {
|
||||
let mut up_to_line = n;
|
||||
@@ -488,10 +483,11 @@ where
|
||||
/// Shrink the buffer so that its length is equal to the set size, returning an iterator for
|
||||
/// the elements that were too much.
|
||||
fn shrink_buffer_to_size(&mut self) -> impl Iterator<Item = String> + '_ {
|
||||
let mut shrink_offset = 0;
|
||||
if self.buffer.len() > self.size {
|
||||
shrink_offset = self.buffer.len() - self.size;
|
||||
}
|
||||
let shrink_offset = if self.buffer.len() > self.size {
|
||||
self.buffer.len() - self.size
|
||||
} else {
|
||||
0
|
||||
};
|
||||
self.buffer
|
||||
.drain(..shrink_offset)
|
||||
.map(|(_, line)| line.unwrap())
|
||||
|
||||
@@ -16,6 +16,8 @@ path = "src/expr.rs"
|
||||
|
||||
[dependencies]
|
||||
libc = "0.2.42"
|
||||
num-bigint = "0.4.0"
|
||||
num-traits = "0.2.14"
|
||||
onig = "~4.3.2"
|
||||
uucore = { version=">=0.0.8", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
|
||||
// spell-checker:ignore (ToDO) binop binops ints paren prec
|
||||
|
||||
use num_bigint::BigInt;
|
||||
use num_traits::{One, Zero};
|
||||
use onig::{Regex, RegexOptions, Syntax};
|
||||
|
||||
use crate::tokens::Token;
|
||||
@@ -39,20 +41,17 @@ impl AstNode {
|
||||
for _ in 0..depth {
|
||||
print!("\t",);
|
||||
}
|
||||
match *self {
|
||||
AstNode::Leaf {
|
||||
ref token_idx,
|
||||
ref value,
|
||||
} => println!(
|
||||
match self {
|
||||
AstNode::Leaf { token_idx, value } => println!(
|
||||
"Leaf( {} ) at #{} ( evaluate -> {:?} )",
|
||||
value,
|
||||
token_idx,
|
||||
self.evaluate()
|
||||
),
|
||||
AstNode::Node {
|
||||
ref token_idx,
|
||||
ref op_type,
|
||||
ref operands,
|
||||
token_idx,
|
||||
op_type,
|
||||
operands,
|
||||
} => {
|
||||
println!(
|
||||
"Node( {} ) at #{} (evaluate -> {:?})",
|
||||
@@ -81,36 +80,33 @@ impl AstNode {
|
||||
})
|
||||
}
|
||||
pub fn evaluate(&self) -> Result<String, String> {
|
||||
match *self {
|
||||
AstNode::Leaf { ref value, .. } => Ok(value.clone()),
|
||||
AstNode::Node { ref op_type, .. } => match self.operand_values() {
|
||||
match self {
|
||||
AstNode::Leaf { value, .. } => Ok(value.clone()),
|
||||
AstNode::Node { op_type, .. } => match self.operand_values() {
|
||||
Err(reason) => Err(reason),
|
||||
Ok(operand_values) => match op_type.as_ref() {
|
||||
"+" => infix_operator_two_ints(
|
||||
|a: i64, b: i64| checked_binop(|| a.checked_add(b), "+"),
|
||||
&operand_values,
|
||||
),
|
||||
"-" => infix_operator_two_ints(
|
||||
|a: i64, b: i64| checked_binop(|| a.checked_sub(b), "-"),
|
||||
&operand_values,
|
||||
),
|
||||
"*" => infix_operator_two_ints(
|
||||
|a: i64, b: i64| checked_binop(|| a.checked_mul(b), "*"),
|
||||
&operand_values,
|
||||
),
|
||||
"+" => {
|
||||
infix_operator_two_ints(|a: BigInt, b: BigInt| Ok(a + b), &operand_values)
|
||||
}
|
||||
"-" => {
|
||||
infix_operator_two_ints(|a: BigInt, b: BigInt| Ok(a - b), &operand_values)
|
||||
}
|
||||
"*" => {
|
||||
infix_operator_two_ints(|a: BigInt, b: BigInt| Ok(a * b), &operand_values)
|
||||
}
|
||||
"/" => infix_operator_two_ints(
|
||||
|a: i64, b: i64| {
|
||||
if b == 0 {
|
||||
|a: BigInt, b: BigInt| {
|
||||
if b.is_zero() {
|
||||
Err("division by zero".to_owned())
|
||||
} else {
|
||||
checked_binop(|| a.checked_div(b), "/")
|
||||
Ok(a / b)
|
||||
}
|
||||
},
|
||||
&operand_values,
|
||||
),
|
||||
"%" => infix_operator_two_ints(
|
||||
|a: i64, b: i64| {
|
||||
if b == 0 {
|
||||
|a: BigInt, b: BigInt| {
|
||||
if b.is_zero() {
|
||||
Err("division by zero".to_owned())
|
||||
} else {
|
||||
Ok(a % b)
|
||||
@@ -119,32 +115,32 @@ impl AstNode {
|
||||
&operand_values,
|
||||
),
|
||||
"=" => infix_operator_two_ints_or_two_strings(
|
||||
|a: i64, b: i64| Ok(bool_as_int(a == b)),
|
||||
|a: BigInt, b: BigInt| Ok(bool_as_int(a == b)),
|
||||
|a: &String, b: &String| Ok(bool_as_string(a == b)),
|
||||
&operand_values,
|
||||
),
|
||||
"!=" => infix_operator_two_ints_or_two_strings(
|
||||
|a: i64, b: i64| Ok(bool_as_int(a != b)),
|
||||
|a: BigInt, b: BigInt| Ok(bool_as_int(a != b)),
|
||||
|a: &String, b: &String| Ok(bool_as_string(a != b)),
|
||||
&operand_values,
|
||||
),
|
||||
"<" => infix_operator_two_ints_or_two_strings(
|
||||
|a: i64, b: i64| Ok(bool_as_int(a < b)),
|
||||
|a: BigInt, b: BigInt| Ok(bool_as_int(a < b)),
|
||||
|a: &String, b: &String| Ok(bool_as_string(a < b)),
|
||||
&operand_values,
|
||||
),
|
||||
">" => infix_operator_two_ints_or_two_strings(
|
||||
|a: i64, b: i64| Ok(bool_as_int(a > b)),
|
||||
|a: BigInt, b: BigInt| Ok(bool_as_int(a > b)),
|
||||
|a: &String, b: &String| Ok(bool_as_string(a > b)),
|
||||
&operand_values,
|
||||
),
|
||||
"<=" => infix_operator_two_ints_or_two_strings(
|
||||
|a: i64, b: i64| Ok(bool_as_int(a <= b)),
|
||||
|a: BigInt, b: BigInt| Ok(bool_as_int(a <= b)),
|
||||
|a: &String, b: &String| Ok(bool_as_string(a <= b)),
|
||||
&operand_values,
|
||||
),
|
||||
">=" => infix_operator_two_ints_or_two_strings(
|
||||
|a: i64, b: i64| Ok(bool_as_int(a >= b)),
|
||||
|a: BigInt, b: BigInt| Ok(bool_as_int(a >= b)),
|
||||
|a: &String, b: &String| Ok(bool_as_string(a >= b)),
|
||||
&operand_values,
|
||||
),
|
||||
@@ -161,7 +157,7 @@ impl AstNode {
|
||||
}
|
||||
}
|
||||
pub fn operand_values(&self) -> Result<Vec<String>, String> {
|
||||
if let AstNode::Node { ref operands, .. } = *self {
|
||||
if let AstNode::Node { operands, .. } = self {
|
||||
let mut out = Vec::with_capacity(operands.len());
|
||||
for operand in operands {
|
||||
match operand.evaluate() {
|
||||
@@ -217,9 +213,9 @@ fn maybe_dump_ast(result: &Result<Box<AstNode>, String>) {
|
||||
if let Ok(debug_var) = env::var("EXPR_DEBUG_AST") {
|
||||
if debug_var == "1" {
|
||||
println!("EXPR_DEBUG_AST");
|
||||
match *result {
|
||||
Ok(ref ast) => ast.debug_dump(),
|
||||
Err(ref reason) => println!("\terr: {:?}", reason),
|
||||
match result {
|
||||
Ok(ast) => ast.debug_dump(),
|
||||
Err(reason) => println!("\terr: {:?}", reason),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -304,7 +300,7 @@ fn push_token_to_either_stack(
|
||||
out_stack: &mut TokenStack,
|
||||
op_stack: &mut TokenStack,
|
||||
) -> Result<(), String> {
|
||||
let result = match *token {
|
||||
let result = match token {
|
||||
Token::Value { .. } => {
|
||||
out_stack.push((token_idx, token.clone()));
|
||||
Ok(())
|
||||
@@ -420,24 +416,14 @@ fn move_till_match_paren(
|
||||
}
|
||||
}
|
||||
|
||||
fn checked_binop<F: Fn() -> Option<T>, T>(cb: F, op: &str) -> Result<T, String> {
|
||||
match cb() {
|
||||
Some(v) => Ok(v),
|
||||
None => Err(format!("{}: Numerical result out of range", op)),
|
||||
}
|
||||
}
|
||||
|
||||
fn infix_operator_two_ints<F>(f: F, values: &[String]) -> Result<String, String>
|
||||
where
|
||||
F: Fn(i64, i64) -> Result<i64, String>,
|
||||
F: Fn(BigInt, BigInt) -> Result<BigInt, String>,
|
||||
{
|
||||
assert!(values.len() == 2);
|
||||
if let Ok(left) = values[0].parse::<i64>() {
|
||||
if let Ok(right) = values[1].parse::<i64>() {
|
||||
return match f(left, right) {
|
||||
Ok(result) => Ok(result.to_string()),
|
||||
Err(reason) => Err(reason),
|
||||
};
|
||||
if let Ok(left) = values[0].parse::<BigInt>() {
|
||||
if let Ok(right) = values[1].parse::<BigInt>() {
|
||||
return f(left, right).map(|big_int| big_int.to_string());
|
||||
}
|
||||
}
|
||||
Err("Expected an integer operand".to_string())
|
||||
@@ -449,13 +435,14 @@ fn infix_operator_two_ints_or_two_strings<FI, FS>(
|
||||
values: &[String],
|
||||
) -> Result<String, String>
|
||||
where
|
||||
FI: Fn(i64, i64) -> Result<i64, String>,
|
||||
FI: Fn(BigInt, BigInt) -> Result<u8, String>,
|
||||
FS: Fn(&String, &String) -> Result<String, String>,
|
||||
{
|
||||
assert!(values.len() == 2);
|
||||
if let (Some(a_int), Some(b_int)) =
|
||||
(values[0].parse::<i64>().ok(), values[1].parse::<i64>().ok())
|
||||
{
|
||||
if let (Some(a_int), Some(b_int)) = (
|
||||
values[0].parse::<BigInt>().ok(),
|
||||
values[1].parse::<BigInt>().ok(),
|
||||
) {
|
||||
match fi(a_int, b_int) {
|
||||
Ok(result) => Ok(result.to_string()),
|
||||
Err(reason) => Err(reason),
|
||||
@@ -541,7 +528,7 @@ fn prefix_operator_substr(values: &[String]) -> String {
|
||||
subj.chars().skip(idx).take(len).collect()
|
||||
}
|
||||
|
||||
fn bool_as_int(b: bool) -> i64 {
|
||||
fn bool_as_int(b: bool) -> u8 {
|
||||
if b {
|
||||
1
|
||||
} else {
|
||||
@@ -559,8 +546,8 @@ fn value_as_bool(s: &str) -> bool {
|
||||
if s.is_empty() {
|
||||
return false;
|
||||
}
|
||||
match s.parse::<i64>() {
|
||||
Ok(n) => n != 0,
|
||||
match s.parse::<BigInt>() {
|
||||
Ok(n) => n.is_one(),
|
||||
Err(_) => true,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
// spell-checker:ignore (ToDO) paren
|
||||
|
||||
use num_bigint::BigInt;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Token {
|
||||
Value {
|
||||
@@ -51,24 +53,19 @@ impl Token {
|
||||
}
|
||||
|
||||
fn is_infix_plus(&self) -> bool {
|
||||
match *self {
|
||||
Token::InfixOp { ref value, .. } => value == "+",
|
||||
match self {
|
||||
Token::InfixOp { value, .. } => value == "+",
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
fn is_a_number(&self) -> bool {
|
||||
match *self {
|
||||
Token::Value { ref value, .. } => value.parse::<i64>().is_ok(),
|
||||
match self {
|
||||
Token::Value { value, .. } => value.parse::<BigInt>().is_ok(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
fn is_a_close_paren(&self) -> bool {
|
||||
#[allow(clippy::match_like_matches_macro)]
|
||||
// `matches!(...)` macro not stabilized until rust v1.42
|
||||
match *self {
|
||||
Token::ParClose => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(*self, Token::ParClose)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +144,7 @@ fn push_token_if_not_escaped(acc: &mut Vec<(usize, Token)>, tok_idx: usize, toke
|
||||
// Smells heuristics... :(
|
||||
let prev_is_plus = match acc.last() {
|
||||
None => false,
|
||||
Some(ref t) => t.1.is_infix_plus(),
|
||||
Some(t) => t.1.is_infix_plus(),
|
||||
};
|
||||
let should_use_as_escaped = if prev_is_plus && acc.len() >= 2 {
|
||||
let pre_prev = &acc[acc.len() - 2];
|
||||
|
||||
@@ -21,6 +21,7 @@ rand = { version = "0.7", features = ["small_rng"] }
|
||||
smallvec = { version = "0.6.14, < 1.0" }
|
||||
uucore = { version = ">=0.0.8", package = "uucore", path = "../../uucore" }
|
||||
uucore_procs = { version = ">=0.0.5", package = "uucore_procs", path = "../../uucore_procs" }
|
||||
clap = "2.33"
|
||||
|
||||
[dev-dependencies]
|
||||
paste = "0.1.18"
|
||||
|
||||
@@ -30,7 +30,7 @@ impl Iterator for Sieve {
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<u64> {
|
||||
while let Some(n) = self.inner.next() {
|
||||
for n in &mut self.inner {
|
||||
let mut prime = true;
|
||||
while let Some((next, inc)) = self.filts.peek() {
|
||||
// need to keep checking the min element of the heap
|
||||
|
||||
+20
-16
@@ -13,18 +13,21 @@ use std::error::Error;
|
||||
use std::io::{self, stdin, stdout, BufRead, Write};
|
||||
|
||||
mod factor;
|
||||
use clap::{App, Arg};
|
||||
pub use factor::*;
|
||||
use uucore::InvalidEncodingHandling;
|
||||
|
||||
mod miller_rabin;
|
||||
pub mod numeric;
|
||||
mod rho;
|
||||
pub mod table;
|
||||
|
||||
static SYNTAX: &str = "[OPTION] [NUMBER]...";
|
||||
static SUMMARY: &str = "Print the prime factors of the given number(s).
|
||||
If none are specified, read from standard input.";
|
||||
static LONG_HELP: &str = "";
|
||||
static VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
static SUMMARY: &str = "Print the prime factors of the given NUMBER(s).
|
||||
If none are specified, read from standard input.";
|
||||
|
||||
mod options {
|
||||
pub static NUMBER: &str = "NUMBER";
|
||||
}
|
||||
|
||||
fn print_factors_str(num_str: &str, w: &mut impl io::Write) -> Result<(), Box<dyn Error>> {
|
||||
num_str
|
||||
@@ -34,14 +37,21 @@ fn print_factors_str(num_str: &str, w: &mut impl io::Write) -> Result<(), Box<dy
|
||||
}
|
||||
|
||||
pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||
let matches = app!(SYNTAX, SUMMARY, LONG_HELP).parse(
|
||||
args.collect_str(InvalidEncodingHandling::Ignore)
|
||||
.accept_any(),
|
||||
);
|
||||
let matches = App::new(executable!())
|
||||
.version(VERSION)
|
||||
.about(SUMMARY)
|
||||
.arg(Arg::with_name(options::NUMBER).multiple(true))
|
||||
.get_matches_from(args);
|
||||
let stdout = stdout();
|
||||
let mut w = io::BufWriter::new(stdout.lock());
|
||||
|
||||
if matches.free.is_empty() {
|
||||
if let Some(values) = matches.values_of(options::NUMBER) {
|
||||
for number in values {
|
||||
if let Err(e) = print_factors_str(number, &mut w) {
|
||||
show_warning!("{}: {}", number, e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let stdin = stdin();
|
||||
|
||||
for line in stdin.lock().lines() {
|
||||
@@ -51,12 +61,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for number in &matches.free {
|
||||
if let Err(e) = print_factors_str(number, &mut w) {
|
||||
show_warning!("{}: {}", number, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(e) = w.flush() {
|
||||
|
||||
@@ -264,12 +264,9 @@ impl<'a> ParagraphStream<'a> {
|
||||
return false;
|
||||
}
|
||||
|
||||
#[allow(clippy::match_like_matches_macro)]
|
||||
// `matches!(...)` macro not stabilized until rust v1.42
|
||||
l_slice[..colon_posn].chars().all(|x| match x as usize {
|
||||
y if !(33..=126).contains(&y) => false,
|
||||
_ => true,
|
||||
})
|
||||
l_slice[..colon_posn]
|
||||
.chars()
|
||||
.all(|x| !matches!(x as usize, y if !(33..=126).contains(&y)))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -541,12 +538,7 @@ impl<'a> WordSplit<'a> {
|
||||
}
|
||||
|
||||
fn is_punctuation(c: char) -> bool {
|
||||
#[allow(clippy::match_like_matches_macro)]
|
||||
// `matches!(...)` macro not stabilized until rust v1.42
|
||||
match c {
|
||||
'!' | '.' | '?' => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(c, '!' | '.' | '?')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,14 +51,23 @@ struct Options {
|
||||
}
|
||||
|
||||
fn is_custom_binary(program: &str) -> bool {
|
||||
#[allow(clippy::match_like_matches_macro)]
|
||||
// `matches!(...)` macro not stabilized until rust v1.42
|
||||
match program {
|
||||
"md5sum" | "sha1sum" | "sha224sum" | "sha256sum" | "sha384sum" | "sha512sum"
|
||||
| "sha3sum" | "sha3-224sum" | "sha3-256sum" | "sha3-384sum" | "sha3-512sum"
|
||||
| "shake128sum" | "shake256sum" | "b2sum" => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(
|
||||
program,
|
||||
"md5sum"
|
||||
| "sha1sum"
|
||||
| "sha224sum"
|
||||
| "sha256sum"
|
||||
| "sha384sum"
|
||||
| "sha512sum"
|
||||
| "sha3sum"
|
||||
| "sha3-224sum"
|
||||
| "sha3-256sum"
|
||||
| "sha3-384sum"
|
||||
| "sha3-512sum"
|
||||
| "shake128sum"
|
||||
| "shake256sum"
|
||||
| "b2sum"
|
||||
)
|
||||
}
|
||||
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
|
||||
@@ -14,7 +14,7 @@ pub fn parse_obsolete(src: &str) -> Option<Result<impl Iterator<Item = OsString>
|
||||
let mut num_end = 0usize;
|
||||
let mut has_num = false;
|
||||
let mut last_char = 0 as char;
|
||||
while let Some((n, c)) = chars.next() {
|
||||
for (n, c) in &mut chars {
|
||||
if c.is_numeric() {
|
||||
has_num = true;
|
||||
num_end = n;
|
||||
@@ -109,7 +109,7 @@ pub fn parse_num(src: &str) -> Result<(usize, bool), ParseError> {
|
||||
let mut num_end = 0usize;
|
||||
let mut last_char = 0 as char;
|
||||
let mut num_count = 0usize;
|
||||
while let Some((n, c)) = chars.next() {
|
||||
for (n, c) in &mut chars {
|
||||
if c.is_numeric() {
|
||||
num_end = n;
|
||||
num_count += 1;
|
||||
|
||||
@@ -520,6 +520,7 @@ fn copy_file_to_file(file: &Path, target: &Path, b: &Behavior) -> i32 {
|
||||
///
|
||||
/// If the copy system call fails, we print a verbose error and return an empty error value.
|
||||
///
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
fn copy(from: &Path, to: &Path, b: &Behavior) -> Result<(), ()> {
|
||||
if b.compare && !need_copy(from, to, b) {
|
||||
return Ok(());
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user