diff --git a/src/uu/wc/src/wc.rs b/src/uu/wc/src/wc.rs index cc2fd28af..9a33cc946 100644 --- a/src/uu/wc/src/wc.rs +++ b/src/uu/wc/src/wc.rs @@ -565,7 +565,65 @@ fn word_count_from_reader( } } -#[allow(clippy::cognitive_complexity)] +fn process_chunk< + const SHOW_CHARS: bool, + const SHOW_LINES: bool, + const SHOW_MAX_LINE_LENGTH: bool, + const SHOW_WORDS: bool, +>( + total: &mut WordCount, + text: &str, + current_len: &mut usize, + in_word: &mut bool, +) { + for ch in text.chars() { + if SHOW_WORDS { + if ch.is_whitespace() { + *in_word = false; + } else if ch.is_ascii_control() { + // These count as characters but do not affect the word state + } else if !(*in_word) { + *in_word = true; + total.words += 1; + } + } + if SHOW_MAX_LINE_LENGTH { + match ch { + '\n' | '\r' | '\x0c' => { + total.max_line_length = max(*current_len, total.max_line_length); + *current_len = 0; + } + '\t' => { + *current_len -= *current_len % 8; + *current_len += 8; + } + _ => { + *current_len += ch.width().unwrap_or(0); + } + } + } + if SHOW_LINES && ch == '\n' { + total.lines += 1; + } + if SHOW_CHARS { + total.chars += 1; + } + } + total.bytes += text.len(); + + total.max_line_length = max(*current_len, total.max_line_length); +} + +fn handle_error(error: BufReadDecoderError<'_>, total: &mut WordCount) -> Option { + match error { + BufReadDecoderError::InvalidByteSequence(bytes) => { + total.bytes += bytes.len(); + } + BufReadDecoderError::Io(e) => return Some(e), + } + None +} + fn word_count_from_reader_specialized< T: WordCountable, const SHOW_CHARS: bool, @@ -579,58 +637,24 @@ fn word_count_from_reader_specialized< let mut reader = BufReadDecoder::new(reader.buffered()); let mut in_word = false; let mut current_len = 0; - while let Some(chunk) = reader.next_strict() { match chunk { Ok(text) => { - for ch in text.chars() { - if SHOW_WORDS { - if ch.is_whitespace() { - in_word = false; - } else if ch.is_ascii_control() { - // These count as characters but do not affect the word state - } else if !in_word { - in_word = true; - total.words += 1; - } - } - if SHOW_MAX_LINE_LENGTH { - match ch { - '\n' | '\r' | '\x0c' => { - total.max_line_length = max(current_len, total.max_line_length); - current_len = 0; - } - '\t' => { - current_len -= current_len % 8; - current_len += 8; - } - _ => { - current_len += ch.width().unwrap_or(0); - } - } - } - if SHOW_LINES && ch == '\n' { - total.lines += 1; - } - if SHOW_CHARS { - total.chars += 1; - } + process_chunk::( + &mut total, + text, + &mut current_len, + &mut in_word, + ); + } + Err(e) => { + if let Some(e) = handle_error(e, &mut total) { + return (total, Some(e)); } - total.bytes += text.len(); - } - Err(BufReadDecoderError::InvalidByteSequence(bytes)) => { - // GNU wc treats invalid data as neither word nor char nor whitespace, - // so no other counters are affected - total.bytes += bytes.len(); - } - Err(BufReadDecoderError::Io(e)) => { - return (total, Some(e)); } } } - total.max_line_length = max(current_len, total.max_line_length); - (total, None) }