Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract uucore::line_ending::LineEnding #5120

Merged
merged 12 commits into from
Aug 20, 2023
33 changes: 1 addition & 32 deletions src/uu/comm/src/comm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use std::fs::File;
use std::io::{self, stdin, BufRead, BufReader, Stdin};
use std::path::Path;
use uucore::error::{FromIo, UResult};
use uucore::line_ending::LineEnding;
use uucore::{format_usage, help_about, help_usage};

use clap::{crate_version, Arg, ArgAction, ArgMatches, Command};
Expand Down Expand Up @@ -40,38 +41,6 @@ fn column_width(col: &str, opts: &ArgMatches) -> usize {
}
}

#[repr(u8)]
#[derive(Clone, Copy)]
enum LineEnding {
Newline = b'\n',
Nul = 0,
}

impl From<LineEnding> for u8 {
fn from(line_ending: LineEnding) -> Self {
line_ending as Self
}
}

impl From<bool> for LineEnding {
fn from(is_zero_terminated: bool) -> Self {
if is_zero_terminated {
Self::Nul
} else {
Self::Newline
}
}
}

impl Display for LineEnding {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Newline => writeln!(f),
Self::Nul => write!(f, "\0"),
}
}
}

enum Input {
Stdin(Stdin),
FileIn(BufReader<File>),
Expand Down
18 changes: 10 additions & 8 deletions src/uu/cut/src/cut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@

// spell-checker:ignore (ToDO) delim sourcefiles

use bstr::io::BufReadExt;

Check failure on line 10 in src/uu/cut/src/cut.rs

View workflow job for this annotation

GitHub Actions / Style and Lint (macos-12, unix)

ERROR: `cargo fmt`: style violation (file:'src/uu/cut/src/cut.rs', line:10; use `cargo fmt -- "src/uu/cut/src/cut.rs"`)

Check failure on line 10 in src/uu/cut/src/cut.rs

View workflow job for this annotation

GitHub Actions / Style/format (ubuntu-latest, feat_os_unix)

ERROR: `cargo fmt`: style violation (file:'src/uu/cut/src/cut.rs', line:10; use `cargo fmt -- "src/uu/cut/src/cut.rs"`)
use clap::{crate_version, Arg, ArgAction, Command};
use is_terminal::IsTerminal;
use uucore::line_ending::LineEnding;
use std::fs::File;
use std::io::{stdin, stdout, BufReader, BufWriter, Read, Write};
use std::path::Path;
use uucore::display::Quotable;

Check failure on line 17 in src/uu/cut/src/cut.rs

View workflow job for this annotation

GitHub Actions / Style and Lint (macos-12, unix)

ERROR: `cargo fmt`: style violation (file:'src/uu/cut/src/cut.rs', line:17; use `cargo fmt -- "src/uu/cut/src/cut.rs"`)

Check failure on line 17 in src/uu/cut/src/cut.rs

View workflow job for this annotation

GitHub Actions / Style/format (ubuntu-latest, feat_os_unix)

ERROR: `cargo fmt`: style violation (file:'src/uu/cut/src/cut.rs', line:17; use `cargo fmt -- "src/uu/cut/src/cut.rs"`)
use uucore::error::{FromIo, UResult, USimpleError};

use self::searcher::Searcher;
Expand All @@ -30,7 +31,7 @@

struct Options {
out_delim: Option<String>,
zero_terminated: bool,
line_ending: LineEnding,
}

enum Delimiter {
Expand All @@ -42,7 +43,7 @@
delimiter: Delimiter,
out_delimiter: Option<String>,
only_delimited: bool,
zero_terminated: bool,
line_ending: LineEnding,
}

enum Mode {
Expand All @@ -68,7 +69,7 @@
}

fn cut_bytes<R: Read>(reader: R, ranges: &[Range], opts: &Options) -> UResult<()> {
let newline_char = if opts.zero_terminated { b'\0' } else { b'\n' };
let newline_char = opts.line_ending.into();
let mut buf_in = BufReader::new(reader);
let mut out = stdout_writer();
let delim = opts
Expand Down Expand Up @@ -259,7 +260,7 @@
}

fn cut_fields<R: Read>(reader: R, ranges: &[Range], opts: &FieldOptions) -> UResult<()> {
let newline_char = if opts.zero_terminated { b'\0' } else { b'\n' };
let newline_char = opts.line_ending.into();
match opts.delimiter {
Delimiter::String(ref delim) => {
let matcher = ExactMatcher::new(delim.as_bytes());
Expand Down Expand Up @@ -376,7 +377,7 @@
.unwrap_or_default()
.to_owned(),
),
zero_terminated: matches.get_flag(options::ZERO_TERMINATED),
line_ending: LineEnding::from(matches.get_flag(options::ZERO_TERMINATED)),
},
)
}),
Expand All @@ -391,7 +392,7 @@
.unwrap_or_default()
.to_owned(),
),
zero_terminated: matches.get_flag(options::ZERO_TERMINATED),
line_ending: LineEnding::from(matches.get_flag(options::ZERO_TERMINATED)),
},
)
}),
Expand All @@ -411,6 +412,7 @@
let only_delimited = matches.get_flag(options::ONLY_DELIMITED);
let whitespace_delimited = matches.get_flag(options::WHITESPACE_DELIMITED);
let zero_terminated = matches.get_flag(options::ZERO_TERMINATED);
let line_ending = LineEnding::from(zero_terminated);

match matches.get_one::<String>(options::DELIMITER).map(|s| s.as_str()) {
Some(_) if whitespace_delimited => {
Expand Down Expand Up @@ -441,7 +443,7 @@
delimiter: Delimiter::String(delim),
out_delimiter: out_delim,
only_delimited,
zero_terminated,
line_ending,
},
))
}
Expand All @@ -455,7 +457,7 @@
},
out_delimiter: out_delim,
only_delimited,
zero_terminated,
line_ending,
},
)),
}
Expand Down
15 changes: 8 additions & 7 deletions src/uu/env/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use std::os::unix::process::ExitStatusExt;
use std::process;
use uucore::display::Quotable;
use uucore::error::{UClapError, UResult, USimpleError, UUsageError};
use uucore::line_ending::LineEnding;
use uucore::{format_usage, help_about, help_section, help_usage, show_warning};

const ABOUT: &str = help_about!("env.md");
Expand All @@ -31,7 +32,7 @@ const AFTER_HELP: &str = help_section!("after help", "env.md");

struct Options<'a> {
ignore_env: bool,
null: bool,
line_ending: LineEnding,
running_directory: Option<&'a str>,
files: Vec<&'a str>,
unsets: Vec<&'a str>,
Expand All @@ -41,11 +42,11 @@ struct Options<'a> {

// print name=value env pairs on screen
// if null is true, separate pairs with a \0, \n otherwise
fn print_env(null: bool) {
fn print_env(line_ending: LineEnding) {
let stdout_raw = io::stdout();
let mut stdout = stdout_raw.lock();
for (n, v) in env::vars() {
write!(stdout, "{}={}{}", n, v, if null { '\0' } else { '\n' }).unwrap();
write!(stdout, "{}={}{}", n, v, line_ending).unwrap();
}
}

Expand All @@ -64,7 +65,7 @@ fn parse_name_value_opt<'a>(opts: &mut Options<'a>, opt: &'a str) -> UResult<boo
}

fn parse_program_opt<'a>(opts: &mut Options<'a>, opt: &'a str) -> UResult<()> {
if opts.null {
if opts.line_ending == LineEnding::Nul {
Err(UUsageError::new(
125,
"cannot specify --null (-0) with command".to_string(),
Expand Down Expand Up @@ -181,7 +182,7 @@ fn run_env(args: impl uucore::Args) -> UResult<()> {
let matches = app.try_get_matches_from(args).with_exit_code(125)?;

let ignore_env = matches.get_flag("ignore-environment");
let null = matches.get_flag("null");
let line_ending = LineEnding::from(matches.get_flag("null"));
let running_directory = matches.get_one::<String>("chdir").map(|s| s.as_str());
let files = match matches.get_many::<String>("file") {
Some(v) => v.map(|s| s.as_str()).collect(),
Expand All @@ -194,7 +195,7 @@ fn run_env(args: impl uucore::Args) -> UResult<()> {

let mut opts = Options {
ignore_env,
null,
line_ending,
running_directory,
files,
unsets,
Expand Down Expand Up @@ -302,7 +303,7 @@ fn run_env(args: impl uucore::Args) -> UResult<()> {

if opts.program.is_empty() {
// no program provided, so just dump all env vars to stdout
print_env(opts.null);
print_env(opts.line_ending);
} else {
// we need to execute a command
let (prog, args) = build_command(&mut opts.program);
Expand Down
68 changes: 27 additions & 41 deletions src/uu/head/src/head.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
// * For the full copyright and license information, please view the LICENSE
// * file that was distributed with this source code.

// spell-checker:ignore (vars) zlines BUFWRITER seekable

Check failure on line 6 in src/uu/head/src/head.rs

View workflow job for this annotation

GitHub Actions / Style and Lint (macos-12, unix)

ERROR: `cargo fmt`: style violation (file:'src/uu/head/src/head.rs', line:6; use `cargo fmt -- "src/uu/head/src/head.rs"`)

Check failure on line 6 in src/uu/head/src/head.rs

View workflow job for this annotation

GitHub Actions / Style/format (ubuntu-latest, feat_os_unix)

ERROR: `cargo fmt`: style violation (file:'src/uu/head/src/head.rs', line:6; use `cargo fmt -- "src/uu/head/src/head.rs"`)

use clap::{crate_version, Arg, ArgAction, ArgMatches, Command};
use uucore::line_ending::LineEnding;
use std::ffi::OsString;
use std::io::{self, BufWriter, ErrorKind, Read, Seek, SeekFrom, Write};
use uucore::display::Quotable;
use uucore::error::{FromIo, UError, UResult, USimpleError};

Check failure on line 13 in src/uu/head/src/head.rs

View workflow job for this annotation

GitHub Actions / Style and Lint (macos-12, unix)

ERROR: `cargo fmt`: style violation (file:'src/uu/head/src/head.rs', line:13; use `cargo fmt -- "src/uu/head/src/head.rs"`)

Check failure on line 13 in src/uu/head/src/head.rs

View workflow job for this annotation

GitHub Actions / Style/format (ubuntu-latest, feat_os_unix)

ERROR: `cargo fmt`: style violation (file:'src/uu/head/src/head.rs', line:13; use `cargo fmt -- "src/uu/head/src/head.rs"`)
use uucore::lines::lines;
use uucore::{format_usage, help_about, help_usage, show};

Expand Down Expand Up @@ -184,7 +185,7 @@
struct HeadOptions {
pub quiet: bool,
pub verbose: bool,
pub zeroed: bool,
pub line_ending: LineEnding,
pub presume_input_pipe: bool,
pub mode: Mode,
pub files: Vec<String>,
Expand All @@ -197,7 +198,7 @@

options.quiet = matches.get_flag(options::QUIET_NAME);
options.verbose = matches.get_flag(options::VERBOSE_NAME);
options.zeroed = matches.get_flag(options::ZERO_NAME);
options.line_ending = LineEnding::from(matches.get_flag(options::ZERO_NAME));
options.presume_input_pipe = matches.get_flag(options::PRESUME_INPUT_PIPE);

options.mode = Mode::from(matches)?;
Expand Down Expand Up @@ -227,9 +228,8 @@
Ok(())
}

fn read_n_lines(input: &mut impl std::io::BufRead, n: u64, zero: bool) -> std::io::Result<()> {
fn read_n_lines(input: &mut impl std::io::BufRead, n: u64, separator: u8) -> std::io::Result<()> {
// Read the first `n` lines from the `input` reader.
let separator = if zero { b'\0' } else { b'\n' };
let mut reader = take_lines(input, n, separator);

// Write those bytes to `stdout`.
Expand Down Expand Up @@ -293,20 +293,12 @@
fn read_but_last_n_lines(
input: impl std::io::BufRead,
n: usize,
zero: bool,
separator: u8,
) -> std::io::Result<()> {
if zero {
let stdout = std::io::stdout();
let mut stdout = stdout.lock();
for bytes in take_all_but(lines(input, b'\0'), n) {
stdout.write_all(&bytes?)?;
}
} else {
let stdout = std::io::stdout();
let mut stdout = stdout.lock();
for bytes in take_all_but(lines(input, b'\n'), n) {
stdout.write_all(&bytes?)?;
}
let stdout = std::io::stdout();
let mut stdout = stdout.lock();
for bytes in take_all_but(lines(input, separator), n) {
stdout.write_all(&bytes?)?;
}
Ok(())
}
Expand Down Expand Up @@ -350,7 +342,7 @@
/// assert_eq!(find_nth_line_from_end(&mut input, 4, false).unwrap(), 0);
/// assert_eq!(find_nth_line_from_end(&mut input, 1000, false).unwrap(), 0);
/// ```
fn find_nth_line_from_end<R>(input: &mut R, n: u64, zeroed: bool) -> std::io::Result<u64>
fn find_nth_line_from_end<R>(input: &mut R, n: u64, separator: u8) -> std::io::Result<u64>
where
R: Read + Seek,
{
Expand All @@ -370,14 +362,8 @@
))?;
input.read_exact(buffer)?;
for byte in buffer.iter().rev() {
match byte {
b'\n' if !zeroed => {
lines += 1;
}
0u8 if zeroed => {
lines += 1;
}
_ => {}
if byte == &separator {
lines += 1;
}
// if it were just `n`,
if lines == n + 1 {
Expand Down Expand Up @@ -407,7 +393,7 @@
}
}
Mode::AllButLastLines(n) => {
let found = find_nth_line_from_end(input, n, options.zeroed)?;
let found = find_nth_line_from_end(input, n, options.line_ending.into())?;
read_n_bytes(
&mut std::io::BufReader::with_capacity(BUF_SIZE, input),
found,
Expand All @@ -426,7 +412,7 @@
Mode::FirstLines(n) => read_n_lines(
&mut std::io::BufReader::with_capacity(BUF_SIZE, input),
n,
options.zeroed,
options.line_ending.into(),
),
Mode::AllButLastBytes(_) | Mode::AllButLastLines(_) => head_backwards_file(input, options),
}
Expand Down Expand Up @@ -465,11 +451,11 @@
// unwrap is guaranteed to succeed because we checked the value of n above
Mode::AllButLastBytes(n) => {
read_but_last_n_bytes(&mut stdin, n.try_into().unwrap())
}

Check failure on line 454 in src/uu/head/src/head.rs

View workflow job for this annotation

GitHub Actions / Style and Lint (macos-12, unix)

ERROR: `cargo fmt`: style violation (file:'src/uu/head/src/head.rs', line:454; use `cargo fmt -- "src/uu/head/src/head.rs"`)

Check failure on line 454 in src/uu/head/src/head.rs

View workflow job for this annotation

GitHub Actions / Style/format (ubuntu-latest, feat_os_unix)

ERROR: `cargo fmt`: style violation (file:'src/uu/head/src/head.rs', line:454; use `cargo fmt -- "src/uu/head/src/head.rs"`)
Mode::FirstLines(n) => read_n_lines(&mut stdin, n, options.zeroed),
Mode::FirstLines(n) => read_n_lines(&mut stdin, n, options.line_ending.into()),
// unwrap is guaranteed to succeed because we checked the value of n above
Mode::AllButLastLines(n) => {
read_but_last_n_lines(&mut stdin, n.try_into().unwrap(), options.zeroed)
read_but_last_n_lines(&mut stdin, n.try_into().unwrap(), options.line_ending.into())
}
}
}
Expand Down Expand Up @@ -541,7 +527,7 @@
#[test]
fn test_args_modes() {
let args = options("-n -10M -vz").unwrap();
assert!(args.zeroed);
assert!(args.line_ending == LineEnding::Nul);
simon04 marked this conversation as resolved.
Show resolved Hide resolved
assert!(args.verbose);
assert_eq!(args.mode, Mode::AllButLastLines(10 * 1024 * 1024));
}
Expand All @@ -561,8 +547,8 @@
assert!(options("-q").unwrap().quiet);
assert!(options("--verbose").unwrap().verbose);
assert!(options("-v").unwrap().verbose);
assert!(options("--zero-terminated").unwrap().zeroed);
assert!(options("-z").unwrap().zeroed);
assert!(options("--zero-terminated").unwrap().line_ending == LineEnding::Nul);
assert!(options("-z").unwrap().line_ending == LineEnding::Nul);
simon04 marked this conversation as resolved.
Show resolved Hide resolved
assert_eq!(options("--lines 15").unwrap().mode, Mode::FirstLines(15));
assert_eq!(options("-n 15").unwrap().mode, Mode::FirstLines(15));
assert_eq!(options("--bytes 15").unwrap().mode, Mode::FirstBytes(15));
Expand All @@ -579,7 +565,7 @@

assert!(!opts.verbose);
assert!(!opts.quiet);
assert!(!opts.zeroed);
assert!(opts.line_ending == LineEnding::Newline);
simon04 marked this conversation as resolved.
Show resolved Hide resolved
assert_eq!(opts.mode, Mode::FirstLines(10));
assert!(opts.files.is_empty());
}
Expand Down Expand Up @@ -631,17 +617,17 @@
fn read_early_exit() {
let mut empty = std::io::BufReader::new(std::io::Cursor::new(Vec::new()));
assert!(read_n_bytes(&mut empty, 0).is_ok());
assert!(read_n_lines(&mut empty, 0, false).is_ok());
assert!(read_n_lines(&mut empty, 0, b'\n').is_ok());
}

#[test]
fn test_find_nth_line_from_end() {
let mut input = Cursor::new("x\ny\nz\n");
assert_eq!(find_nth_line_from_end(&mut input, 0, false).unwrap(), 6);
assert_eq!(find_nth_line_from_end(&mut input, 1, false).unwrap(), 4);
assert_eq!(find_nth_line_from_end(&mut input, 2, false).unwrap(), 2);
assert_eq!(find_nth_line_from_end(&mut input, 3, false).unwrap(), 0);
assert_eq!(find_nth_line_from_end(&mut input, 4, false).unwrap(), 0);
assert_eq!(find_nth_line_from_end(&mut input, 1000, false).unwrap(), 0);
assert_eq!(find_nth_line_from_end(&mut input, 0, b'\n').unwrap(), 6);
assert_eq!(find_nth_line_from_end(&mut input, 1, b'\n').unwrap(), 4);
assert_eq!(find_nth_line_from_end(&mut input, 2, b'\n').unwrap(), 2);
assert_eq!(find_nth_line_from_end(&mut input, 3, b'\n').unwrap(), 0);
assert_eq!(find_nth_line_from_end(&mut input, 4, b'\n').unwrap(), 0);
assert_eq!(find_nth_line_from_end(&mut input, 1000, b'\n').unwrap(), 0);
}
}
9 changes: 2 additions & 7 deletions src/uu/id/src/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ use uucore::error::UResult;
use uucore::error::{set_exit_code, USimpleError};
pub use uucore::libc;
use uucore::libc::{getlogin, uid_t};
use uucore::line_ending::LineEnding;
use uucore::process::{getegid, geteuid, getgid, getuid};
use uucore::{format_usage, help_about, help_section, help_usage, show_error};

Expand Down Expand Up @@ -174,13 +175,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
" ".to_string()
}
};
let line_ending = {
if state.zflag {
'\0'
} else {
'\n'
}
};
let line_ending = LineEnding::from(state.zflag);

if state.cflag {
if state.selinux_supported {
Expand Down
Loading
Loading