From 3b94762e1eace5a854b423c2528951900fac91d2 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Thu, 10 Apr 2025 12:56:41 -0700 Subject: [PATCH] clippy --- rust/pspp/src/format/display.rs | 4 +- rust/pspp/src/format/mod.rs | 11 +++-- rust/pspp/src/format/parse.rs | 10 ++-- rust/pspp/src/identifier.rs | 12 ++--- rust/pspp/src/lex/lexer.rs | 7 ++- rust/pspp/src/lex/scan/mod.rs | 20 ++++---- rust/pspp/src/lex/scan/test.rs | 2 +- rust/pspp/src/lex/segment/mod.rs | 65 +++++++++++++------------ rust/pspp/src/lex/segment/test.rs | 18 +++---- rust/pspp/src/lex/token.rs | 4 +- rust/pspp/src/macros.rs | 45 +++++++++--------- rust/pspp/src/message.rs | 6 +-- rust/pspp/src/output/csv.rs | 10 ++-- rust/pspp/src/output/pivot/look_xml.rs | 2 +- rust/pspp/src/output/pivot/mod.rs | 66 +++++++++++++------------- rust/pspp/src/output/pivot/output.rs | 16 +++---- rust/pspp/src/output/pivot/tlo.rs | 2 +- rust/pspp/src/output/render.rs | 22 ++++----- rust/pspp/src/output/table.rs | 8 ++-- rust/pspp/src/output/text.rs | 20 +++++--- rust/pspp/src/output/text_line.rs | 23 +++++---- rust/pspp/src/raw.rs | 2 +- 22 files changed, 188 insertions(+), 187 deletions(-) diff --git a/rust/pspp/src/format/display.rs b/rust/pspp/src/format/display.rs index b490e5fe39..8955d6b7b9 100644 --- a/rust/pspp/src/format/display.rs +++ b/rust/pspp/src/format/display.rs @@ -1079,7 +1079,7 @@ mod test { let mut value_name = String::new(); for (line, line_number) in input.lines().map(|r| r.unwrap()).zip(1..) { let line = line.trim(); - let tokens = StringScanner::new(&line, Syntax::Interactive, true) + let tokens = StringScanner::new(line, Syntax::Interactive, true) .unwrapped() .collect::>(); match &tokens[0] { @@ -1276,7 +1276,7 @@ mod test { let endian = EndianSettings::new(Endian::Big); for (line, line_number) in input.lines().map(|r| r.unwrap()).zip(1..) { let line = line.trim(); - let tokens = StringScanner::new(&line, Syntax::Interactive, true) + let tokens = StringScanner::new(line, Syntax::Interactive, true) .unwrapped() .collect::>(); match &tokens[0] { diff --git a/rust/pspp/src/format/mod.rs b/rust/pspp/src/format/mod.rs index 13df780d52..14a6209de1 100644 --- a/rust/pspp/src/format/mod.rs +++ b/rust/pspp/src/format/mod.rs @@ -866,7 +866,7 @@ impl Settings { static F: LazyLock = LazyLock::new(|| { StyleSet::new(|p| NumberStyle::new("", "", p.decimal, None, p.leading_zero)) }); - &F.get(self) + F.get(self) } Type::Comma => { static COMMA: LazyLock = LazyLock::new(|| { @@ -874,7 +874,7 @@ impl Settings { NumberStyle::new("", "", p.decimal, Some(!p.decimal), p.leading_zero) }) }); - &COMMA.get(self) + COMMA.get(self) } Type::Dot => { static DOT: LazyLock = LazyLock::new(|| { @@ -882,19 +882,19 @@ impl Settings { NumberStyle::new("", "", !p.decimal, Some(p.decimal), p.leading_zero) }) }); - &DOT.get(self) + DOT.get(self) } Type::Dollar => { static DOLLAR: LazyLock = LazyLock::new(|| { StyleSet::new(|p| NumberStyle::new("$", "", p.decimal, Some(!p.decimal), false)) }); - &DOLLAR.get(self) + DOLLAR.get(self) } Type::Pct => { static PCT: LazyLock = LazyLock::new(|| { StyleSet::new(|p| NumberStyle::new("", "%", p.decimal, None, false)) }); - &PCT.get(self) + PCT.get(self) } Type::CC(cc) => self.ccs[cc].as_deref().unwrap_or(&DEFAULT), Type::N @@ -1148,6 +1148,7 @@ impl DateTemplate { Self::new(format.type_(), format.w()) } + #[allow(clippy::len_without_is_empty)] pub fn len(&self) -> usize { self.0.len() } diff --git a/rust/pspp/src/format/parse.rs b/rust/pspp/src/format/parse.rs index 6aa4463c57..1344f71343 100644 --- a/rust/pspp/src/format/parse.rs +++ b/rust/pspp/src/format/parse.rs @@ -787,7 +787,7 @@ fn parse_year( Ok(settings.epoch.apply(year)) } -fn parse_int<'a, T>(p: &mut StrParser<'_>) -> Result +fn parse_int(p: &mut StrParser<'_>) -> Result where T: FromStr, { @@ -1047,7 +1047,7 @@ mod test { type_: Type, } - impl<'a> DateTester<'a> { + impl DateTester<'_> { fn visit(&self, extra: &str, mut expected: ExpectDate) { let formatted = format!("{}{extra}", self.formatted); if !self.template.is_empty() { @@ -1368,7 +1368,7 @@ mod test { type_: Type, } - impl<'a> TimeTester<'a> { + impl TimeTester<'_> { fn visit(&self, extra: &str, mut expected: f64, sign: Sign) { let formatted = format!("{}{extra}", self.formatted); if !self.template.is_empty() { @@ -1402,7 +1402,7 @@ mod test { next.visit(&format!("{:02}", self.time.minutes), expected, sign); } 'S' => { - expected += self.time.seconds as f64; + expected += self.time.seconds; next.visit(&format!("{}", self.time.seconds), expected, sign); next.visit(&format!("{:02}", self.time.seconds), expected, sign); } @@ -1430,7 +1430,7 @@ mod test { .as_number() .unwrap() .unwrap(); - assert_eq!((parsed * 1000.0).round(), (expected as f64) * 1000.0); + assert_eq!((parsed * 1000.0).round(), expected * 1000.0); } } diff --git a/rust/pspp/src/identifier.rs b/rust/pspp/src/identifier.rs index c4e21544ff..032fc730d6 100644 --- a/rust/pspp/src/identifier.rs +++ b/rust/pspp/src/identifier.rs @@ -160,16 +160,12 @@ impl TryFrom<&str> for ReservedWord { (2, b'L', b'T') => Ok(Self::Lt), (2, b'L', b'E') => Ok(Self::Le), (2, b'N', b'E') => Ok(Self::Ne), - (3, b'N', b'O') if b[2].to_ascii_uppercase() == b'T' => Ok(Self::Not), + (3, b'N', b'O') if b[2].eq_ignore_ascii_case(&b'T') => Ok(Self::Not), (2, b'O', b'R') => Ok(Self::Or), (2, b'T', b'O') => Ok(Self::To), - (3, b'A', b'L') if b[2].to_ascii_uppercase() == b'L' => Ok(Self::All), - (3, b'A', b'N') if b[2].to_ascii_uppercase() == b'D' => Ok(Self::And), - (4, b'W', b'I') - if b[2].to_ascii_uppercase() == b'T' && b[3].to_ascii_uppercase() == b'H' => - { - Ok(Self::With) - } + (3, b'A', b'L') if b[2].eq_ignore_ascii_case(&b'L') => Ok(Self::All), + (3, b'A', b'N') if b[2].eq_ignore_ascii_case(&b'D') => Ok(Self::And), + (4, b'W', b'I') if b[2..4].eq_ignore_ascii_case(b"TH") => Ok(Self::With), _ => Err(()), } } diff --git a/rust/pspp/src/lex/lexer.rs b/rust/pspp/src/lex/lexer.rs index 96d47e7a8e..34e6ae850c 100644 --- a/rust/pspp/src/lex/lexer.rs +++ b/rust/pspp/src/lex/lexer.rs @@ -454,7 +454,7 @@ impl TokenSlice { F: Fn(&Token) -> bool, { let mut iter = self.iter(); - if iter.next().map_or(false, |token| f(&token.token)) { + if iter.next().is_some_and(|token| f(&token.token)) { Some(iter.remainder()) } else { None @@ -660,8 +660,7 @@ impl Source { dst.push_back(src.pop_front().unwrap()); return; }; - for ofs in 1.. { - let token = &src[ofs]; + for token in src.range(1..) { if parser.push(&token.token, &self.file.buffer[token.pos.clone()], &|e| { println!("{e:?}") }) == ParseStatus::Complete @@ -670,7 +669,7 @@ impl Source { } } let call = parser.finish(); - if call.len() == 0 { + if call.is_empty() { // False alarm: no macro to expand after all. dst.push_back(src.pop_front().unwrap()); return; diff --git a/rust/pspp/src/lex/scan/mod.rs b/rust/pspp/src/lex/scan/mod.rs index 6612d12c8a..4b665437c7 100644 --- a/rust/pspp/src/lex/scan/mod.rs +++ b/rust/pspp/src/lex/scan/mod.rs @@ -267,17 +267,17 @@ impl ScanToken { /// /// This performs two different kinds of token merging: /// - /// - String concatenation, where syntax like `"a" + "b"` is converted into a + /// - String concatenation, where syntax like `"a" + "b"` is converted into a /// single string token. This is definitely needed because the parser relies /// on it. /// - /// - Negative number merging, where syntax like `-5` is converted from a pair - /// of tokens (a dash and a positive number) into a single token (a negative - /// number). This might not be needed anymore because the segmenter - /// directly treats a dash followed by a number, with optional intervening - /// white space, as a negative number. It's only needed if we want - /// intervening comments to be allowed or for part of the negative number - /// token to be produced by macro expansion. + /// - Negative number merging, where syntax like `-5` is converted from a pair + /// of tokens (a dash and a positive number) into a single token (a negative + /// number). This might not be needed anymore because the segmenter + /// directly treats a dash followed by a number, with optional intervening + /// white space, as a negative number. It's only needed if we want + /// intervening comments to be allowed or for part of the negative number + /// token to be produced by macro expansion. pub fn merge<'a, F>(get_token: F) -> Result, Incomplete> where F: Fn(usize) -> Result, Incomplete>, @@ -311,7 +311,7 @@ impl ScanToken { let Token::String(s) = get_token(i * 2).unwrap().unwrap() else { unreachable!() }; - output.push_str(&s); + output.push_str(s); } Ok(Some(MergeResult::Expand { n: i * 2 + 1, @@ -395,7 +395,7 @@ impl<'a> StringScanner<'a> { } } -impl<'a> Iterator for StringScanner<'a> { +impl Iterator for StringScanner<'_> { type Item = ScanToken; fn next(&mut self) -> Option { diff --git a/rust/pspp/src/lex/scan/test.rs b/rust/pspp/src/lex/scan/test.rs index a3c5f18b37..99041fe4bb 100644 --- a/rust/pspp/src/lex/scan/test.rs +++ b/rust/pspp/src/lex/scan/test.rs @@ -22,7 +22,7 @@ fn print_token(token: &Token) { fn check_scan(input: &str, mode: Syntax, expected: &[ScanToken]) { let tokens = StringScanner::new(input, mode, false).collect::>(); - if &tokens != expected { + if tokens != expected { for token in &tokens { match token { ScanToken::Token(token) => { diff --git a/rust/pspp/src/lex/segment/mod.rs b/rust/pspp/src/lex/segment/mod.rs index 43a4ff8708..5964e0f69d 100644 --- a/rust/pspp/src/lex/segment/mod.rs +++ b/rust/pspp/src/lex/segment/mod.rs @@ -19,6 +19,8 @@ //! ignored (e.g. [Segment::Spaces]) or trigger special behavior such as error //! messages later in tokenization (e.g. [Segment::ExpectedQuote]). +use std::cmp::Ordering; + #[cfg(doc)] use crate::lex::token::Token; @@ -536,10 +538,10 @@ impl Segmenter { '/' => { if let (Some('*'), rest) = take(rest, eof)? { let rest = skip_comment(rest, eof)?; - return Ok(Some((rest, Segment::Comment))); + Ok(Some((rest, Segment::Comment))) } else { self.state.1 = Substate::empty(); - return Ok(Some((rest, Segment::Punct))); + Ok(Some((rest, Segment::Punct))) } } '-' => { @@ -558,11 +560,11 @@ impl Segmenter { None | Some(_) => (), } self.state.1 = Substate::empty(); - return Ok(Some((rest, Segment::Punct))); + Ok(Some((rest, Segment::Punct))) } '(' | ')' | '[' | ']' | '{' | '}' | ',' | '=' | ';' | ':' | '&' | '|' | '+' => { self.state.1 = Substate::empty(); - return Ok(Some((rest, Segment::Punct))); + Ok(Some((rest, Segment::Punct))) } '*' => { if self.state.1.contains(Substate::START_OF_COMMAND) { @@ -1051,8 +1053,8 @@ impl Segmenter { input = take(input, eof).unwrap().1; } } - fn check_repeat_command<'a>(&mut self, input: &'a str, eof: bool) -> Result { - let input = input.strip_prefix(&['-', '+']).unwrap_or(input); + fn check_repeat_command(&mut self, input: &str, eof: bool) -> Result { + let input = input.strip_prefix(['-', '+']).unwrap_or(input); let (id1, input) = self.next_id_in_command(input, eof)?; if id_match("DO", id1) && id_match("REPEAT", self.next_id_in_command(input, eof)?.0) { Ok(1) @@ -1079,26 +1081,29 @@ impl Segmenter { return Ok(Some((rest, Segment::Newline))); } let rest = self.parse_full_line(input, eof)?; - let direction = self.check_repeat_command(input, eof)?; - if direction > 0 { - if let Some(nest) = self.nest.checked_add(1) { - self.nest = nest; - } else { - self.state.0 = State::DoRepeat4; + match self.check_repeat_command(input, eof)?.cmp(&0) { + Ordering::Greater => { + if let Some(nest) = self.nest.checked_add(1) { + self.nest = nest; + } else { + self.state.0 = State::DoRepeat4; + } } - } else if direction < 0 { - self.nest -= 1; - if self.nest == 0 { - // Nesting level dropped to 0, so we've finished reading the `DO - // REPEAT` body. - self.state = ( - State::General, - Substate::START_OF_COMMAND | Substate::START_OF_LINE, - ); - return self.push_rest(input, eof); + Ordering::Less => { + self.nest -= 1; + if self.nest == 0 { + // Nesting level dropped to 0, so we've finished reading the `DO + // REPEAT` body. + self.state = ( + State::General, + Substate::START_OF_COMMAND | Substate::START_OF_LINE, + ); + return self.push_rest(input, eof); + } } + Ordering::Equal => (), } - return Ok(Some((rest, Segment::DoRepeatCommand))); + Ok(Some((rest, Segment::DoRepeatCommand))) } fn parse_do_repeat_4<'a>( &mut self, @@ -1175,7 +1180,7 @@ impl Segmenter { } Ok(Some((rest, segment))) } - fn find_enddefine<'a>(mut input: &'a str) -> Option<&'a str> { + fn find_enddefine(mut input: &str) -> Option<&str> { loop { input = skip_spaces_and_comments(input, true).unwrap(); let (Some(c), rest) = take(input, true).unwrap() else { @@ -1328,13 +1333,11 @@ impl Segmenter { } fn strip_prefix_ignore_ascii_case<'a>(line: &'a str, pattern: &str) -> Option<&'a str> { - line.get(..pattern.len()) - .map(|prefix| { - prefix - .eq_ignore_ascii_case(pattern) - .then(|| &line[pattern.len()..]) - }) - .flatten() + line.get(..pattern.len()).and_then(|prefix| { + prefix + .eq_ignore_ascii_case(pattern) + .then(|| &line[pattern.len()..]) + }) } #[cfg(test)] diff --git a/rust/pspp/src/lex/segment/test.rs b/rust/pspp/src/lex/segment/test.rs index 3c36186a14..be13cdd074 100644 --- a/rust/pspp/src/lex/segment/test.rs +++ b/rust/pspp/src/lex/segment/test.rs @@ -2,9 +2,9 @@ use crate::prompt::PromptStyle; use super::{Segment, Segmenter, Syntax}; -fn push_segment<'a>( +fn push_segment( segmenter: &mut Segmenter, - input: &'a str, + input: &str, one_byte: bool, ) -> Option<(usize, Segment)> { if one_byte { @@ -36,7 +36,7 @@ fn _check_segmentation( input = rest; } - if &segments != expect_segments { + if segments != expect_segments { eprintln!("segments differ from expected:"); let difference = diff::slice(expect_segments, &segments); for result in difference { @@ -49,7 +49,7 @@ fn _check_segmentation( panic!(); } - if &prompts != expect_prompts { + if prompts != expect_prompts { eprintln!("prompts differ from expected:"); let difference = diff::slice(expect_prompts, &prompts); for result in difference { @@ -90,7 +90,7 @@ fn check_segmentation( if let Some(input) = input.strip_suffix('\n') { println!("running {one_byte_name} segmentation test without final newline..."); - let mut expect_segments: Vec<_> = expect_segments.iter().copied().collect(); + let mut expect_segments: Vec<_> = expect_segments.to_vec(); assert_eq!(expect_segments.pop(), Some((Segment::Newline, "\n"))); while let Some((Segment::SeparateCommands | Segment::EndCommand, "")) = expect_segments.last() @@ -1389,15 +1389,15 @@ fn test_do_repeat_overflow() { (Segment::EndCommand, "."), (Segment::Newline, "\n"), ]; - for i in 1..N { - expect_output.push((Segment::DoRepeatCommand, &do_repeat[i].trim_end())); + for (i, line) in do_repeat.iter().enumerate().take(N).skip(1) { + expect_output.push((Segment::DoRepeatCommand, do_repeat[i].trim_end())); if i >= 255 { expect_output.push((Segment::DoRepeatOverflow, "")); } expect_output.push((Segment::Newline, "\n")); } - for i in 0..254 { - expect_output.push((Segment::DoRepeatCommand, &end_repeat[i].trim_end())); + for line in &end_repeat[..254] { + expect_output.push((Segment::DoRepeatCommand, line.trim_end())); expect_output.push((Segment::Newline, "\n")); } let comments: Vec = (0..(N - 254)).rev().map(|i| format!("/* {i}")).collect(); diff --git a/rust/pspp/src/lex/token.rs b/rust/pspp/src/lex/token.rs index bf2d7e87c2..e58c37ee38 100644 --- a/rust/pspp/src/lex/token.rs +++ b/rust/pspp/src/lex/token.rs @@ -32,7 +32,7 @@ impl Token { } pub fn matches_keyword(&self, keyword: &str) -> bool { - self.id().map_or(false, |id| id.matches_keyword(keyword)) + self.id().is_some_and(|id| id.matches_keyword(keyword)) } pub fn as_number(&self) -> Option { @@ -99,7 +99,7 @@ impl Display for Token { } } Token::String(s) => { - if s.chars().all(|c| is_printable(c)) { + if s.chars().all(is_printable) { if s.contains('"') { string_representation(s, '\'', f) } else { diff --git a/rust/pspp/src/macros.rs b/rust/pspp/src/macros.rs index 57abc4ec36..bd07bcdaeb 100644 --- a/rust/pspp/src/macros.rs +++ b/rust/pspp/src/macros.rs @@ -276,13 +276,13 @@ fn tokenize_string(s: &str, mode: Syntax, error: &impl Fn(MacroError)) -> Vec Option { +fn try_unquote_string(input: &str, mode: Syntax) -> Option { let mut scanner = StringScanner::new(input, mode, true); let Some(ScanToken::Token(Token::String(unquoted))) = scanner.next() else { return None; }; let None = scanner.next() else { return None }; - return Some(unquoted); + Some(unquoted) } fn unquote_string(input: String, mode: Syntax) -> String { @@ -292,7 +292,7 @@ fn unquote_string(input: String, mode: Syntax) -> String { #[derive(Clone)] struct MacroTokens<'a>(&'a [MacroToken]); -impl<'a> MacroTokens<'a> { +impl MacroTokens<'_> { fn is_empty(&self) -> bool { self.0.is_empty() } @@ -315,10 +315,10 @@ impl<'a> MacroTokens<'a> { None } fn macro_id(&self) -> Option<&Identifier> { - self.0.get(0).map(|mt| mt.token.macro_id()).flatten() + self.0.first().and_then(|mt| mt.token.macro_id()) } fn take_macro_id(&mut self) -> Option<&Identifier> { - let result = self.0.get(0).map(|mt| mt.token.macro_id()).flatten(); + let result = self.0.first().and_then(|mt| mt.token.macro_id()); if result.is_some() { self.advance(); } @@ -848,7 +848,7 @@ impl DoInput { fn from_by(first: f64, last: f64, by: f64) -> Self { if by > 0.0 && first <= last { Self::Up { first, last, by } - } else if by > 0.0 && first <= last { + } else if by < 0.0 && first <= last { Self::Down { first, last, by } } else { Self::Empty @@ -885,7 +885,7 @@ impl Iterator for DoInput { } } -impl<'a> Expander<'a> { +impl Expander<'_> { fn may_expand(&self) -> bool { *self.expand.borrow() } @@ -925,7 +925,7 @@ impl<'a> Expander<'a> { args: None, ..*self }; - let mut arg_tokens = MacroTokens(&arg); + let mut arg_tokens = MacroTokens(arg); subexpander.expand(&mut arg_tokens, output); self.stack = subexpander.stack; self.stack.pop(); @@ -968,7 +968,7 @@ impl<'a> Expander<'a> { (e.error)(MacroError::InvalidBlanks(args[0].clone())); return None; }; - Some(std::iter::repeat(' ').take(n).collect()) + Some(" ".repeat(n)) } fn expand_concat(e: &mut Expander, args: Vec) -> Option { @@ -1059,11 +1059,7 @@ impl<'a> Expander<'a> { fn expand_tail(e: &mut Expander, mut args: Vec) -> Option { let arg = unquote_string(args.remove(0), e.mode); let mut output = tokenize_string(&arg, e.mode, e.error); - Some( - output - .pop() - .map_or_else(|| String::new(), |tail| tail.syntax), - ) + Some(output.pop().map_or_else(String::new, |tail| tail.syntax)) } fn expand_unquote(e: &mut Expander, mut args: Vec) -> Option { @@ -1157,7 +1153,7 @@ impl<'a> Expander<'a> { /// quoted string is an important special case. fn parse_function_arg(&mut self, input: &mut MacroTokens) -> Option { if let Some(macro_) = self.macro_ { - match &input.0.get(0)?.token { + match &input.0.first()?.token { Token::Id(id) if id.0.starts_with('!') => { if let Some(param_idx) = macro_.find_parameter(id) { input.advance(); @@ -1273,7 +1269,7 @@ impl<'a> Expander<'a> { .. }), 1, - ) = (tokens.get(0), tokens.len()) + ) = (tokens.first(), tokens.len()) else { (self.error)(MacroError::BadNumericMacroExpression(s)); return None; @@ -1307,7 +1303,7 @@ impl<'a> Expander<'a> { input.advance(); } } - return None; + None } fn expand_if(&mut self, orig_input: &mut MacroTokens, output: &mut Vec) -> bool { let mut input = orig_input.clone(); @@ -1367,8 +1363,7 @@ impl<'a> Expander<'a> { if is_macro_keyword(var_name) || self .macro_ - .map(|m| m.find_parameter(var_name)) - .flatten() + .and_then(|m| m.find_parameter(var_name)) .is_some() { (self.error)(MacroError::BadMacroVarName { @@ -1423,7 +1418,7 @@ impl<'a> Expander<'a> { } } (self.error)(MacroError::MissingDoEnd); - return None; + None } fn expand_do(&mut self, orig_input: &mut MacroTokens, output: &mut Vec) -> bool { @@ -1517,7 +1512,7 @@ impl<'a> Expander<'a> { fn expand__(&mut self, input: &mut MacroTokens, output: &mut Vec) { // Recursive macro calls. if self.may_expand() { - if let Some(call) = Call::for_tokens(self.macros, &input.0, &self.error) { + if let Some(call) = Call::for_tokens(self.macros, input.0, &self.error) { let vars = RefCell::new(BTreeMap::new()); let mut stack = take(&mut self.stack); stack.push(Frame { @@ -1613,7 +1608,7 @@ impl<'a> Call<'a> { where F: Fn(MacroError), { - let mut parser = Parser::new(macros, &tokens.get(0)?.token)?; + let mut parser = Parser::new(macros, &tokens.first()?.token)?; for token in tokens[1..].iter().chain(&[MacroToken { token: Token::End, syntax: String::from(""), @@ -1622,7 +1617,7 @@ impl<'a> Call<'a> { return Some(parser.finish()); } } - return None; + None } pub fn expand( @@ -1668,4 +1663,8 @@ impl<'a> Call<'a> { pub fn len(&self) -> usize { self.0.n_tokens } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } } diff --git a/rust/pspp/src/message.rs b/rust/pspp/src/message.rs index 8942223a32..b128b5ac0d 100644 --- a/rust/pspp/src/message.rs +++ b/rust/pspp/src/message.rs @@ -107,9 +107,7 @@ impl Location { let span = match (&a.span, &b.span) { (None, None) => None, (Some(r), None) | (None, Some(r)) => Some(r.clone()), - (Some(ar), Some(br)) => { - Some(min(ar.start, br.start).clone()..max(ar.end, br.end).clone()) - } + (Some(ar), Some(br)) => Some(min(ar.start, br.start)..max(ar.end, br.end)), }; Some(Self { file_name: a.file_name, @@ -183,7 +181,7 @@ impl Display for Diagnostic { description, } in &self.stack { - if !!location.is_empty() { + if !location.is_empty() { write!(f, "{location}: ")?; } writeln!(f, "{description}")?; diff --git a/rust/pspp/src/output/csv.rs b/rust/pspp/src/output/csv.rs index 4dd38f2a15..5832b98c4c 100644 --- a/rust/pspp/src/output/csv.rs +++ b/rust/pspp/src/output/csv.rs @@ -39,7 +39,7 @@ impl CsvOptions { } fn string_needs_quoting(&self, s: &str) -> bool { - s.bytes().find(|&b| self.byte_needs_quoting(b)).is_some() + s.bytes().any(|b| self.byte_needs_quoting(b)) } } @@ -54,7 +54,7 @@ impl<'a> CsvField<'a> { } } -impl<'a> Display for CsvField<'a> { +impl Display for CsvField<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { if self.options.string_needs_quoting(self.text) { let quote = self.options.quote as char; @@ -83,7 +83,7 @@ impl CsvDriver { fn start_item(&mut self) { if self.n_items > 0 { - write!(&mut self.file, "\n").unwrap(); + writeln!(&mut self.file).unwrap(); } self.n_items += 1; } @@ -150,12 +150,12 @@ impl Driver for CsvDriver { } Details::Table(pivot_table) => { for layer in pivot_table.layers(true) { - self.output_table_layer(&*pivot_table, &layer).unwrap(); + self.output_table_layer(pivot_table, &layer).unwrap(); } } Details::PageBreak => { self.start_item(); - write!(&mut self.file, "\n").unwrap(); + writeln!(&mut self.file).unwrap(); } Details::Text(text) => match text.type_ { TextType::Syntax | TextType::PageTitle => (), diff --git a/rust/pspp/src/output/pivot/look_xml.rs b/rust/pspp/src/output/pivot/look_xml.rs index d72e89b6f7..e6fbbb057f 100644 --- a/rust/pspp/src/output/pivot/look_xml.rs +++ b/rust/pspp/src/output/pivot/look_xml.rs @@ -80,7 +80,7 @@ impl From for Look { .continuation_text_at_bottom, continuation: { let text = table_properties.printing_properties.continuation_text; - if text == "" { + if text.is_empty() { None } else { Some(text) diff --git a/rust/pspp/src/output/pivot/mod.rs b/rust/pspp/src/output/pivot/mod.rs index 7da87d5153..1fe7e56eaa 100644 --- a/rust/pspp/src/output/pivot/mod.rs +++ b/rust/pspp/src/output/pivot/mod.rs @@ -1294,30 +1294,30 @@ impl Default for ValueOptions { } } -pub trait AsValueOptions { - fn as_value_options(self) -> ValueOptions; +pub trait IntoValueOptions { + fn into_value_options(self) -> ValueOptions; } -impl AsValueOptions for () { - fn as_value_options(self) -> ValueOptions { +impl IntoValueOptions for () { + fn into_value_options(self) -> ValueOptions { ValueOptions::default() } } -impl AsValueOptions for &PivotTable { - fn as_value_options(self) -> ValueOptions { +impl IntoValueOptions for &PivotTable { + fn into_value_options(self) -> ValueOptions { self.value_options() } } -impl AsValueOptions for &ValueOptions { - fn as_value_options(self) -> ValueOptions { +impl IntoValueOptions for &ValueOptions { + fn into_value_options(self) -> ValueOptions { *self } } -impl AsValueOptions for ValueOptions { - fn as_value_options(self) -> ValueOptions { +impl IntoValueOptions for ValueOptions { + fn into_value_options(self) -> ValueOptions { self } } @@ -1430,10 +1430,11 @@ where impl PivotTable { fn new(title: Box, look: Arc) -> Self { - let mut this = Self::default(); - this.title = Some(title); - this.look = look; - this + Self { + title: Some(title), + look, + ..Self::default() + } } fn cell_index(&self, data_indexes: &[usize]) -> usize { cell_index(data_indexes, self.dimensions.iter().map(|d| d.len())) @@ -1496,7 +1497,7 @@ impl PivotTable { fn axis_dimensions( &self, axis: Axis3, - ) -> impl Iterator + DoubleEndedIterator + ExactSizeIterator { + ) -> impl DoubleEndedIterator + ExactSizeIterator { self.axes[axis] .dimensions .iter() @@ -1561,14 +1562,14 @@ pub struct Footnote { } impl Footnote { - pub fn display_marker<'a, 'b>(&'a self, options: impl AsValueOptions) -> DisplayMarker<'a> { + pub fn display_marker(&self, options: impl IntoValueOptions) -> DisplayMarker<'_> { DisplayMarker { footnote: self, - options: options.as_value_options(), + options: options.into_value_options(), } } - pub fn display_content<'a, 'b>(&'a self, options: impl AsValueOptions) -> DisplayValue<'a> { + pub fn display_content(&self, options: impl IntoValueOptions) -> DisplayValue<'_> { self.content.display(options) } } @@ -1578,7 +1579,7 @@ pub struct DisplayMarker<'a> { options: ValueOptions, } -impl<'a> Display for DisplayMarker<'a> { +impl Display for DisplayMarker<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { if let Some(marker) = &self.footnote.marker { write!(f, "{}", marker.display(self.options).without_suffixes()) @@ -1749,7 +1750,7 @@ impl<'a> DisplayValue<'a> { &self, f: &mut std::fmt::Formatter<'_>, template: &str, - args: &Vec>, + args: &[Vec], ) -> std::fmt::Result { let mut iter = template.as_bytes().iter(); while let Some(c) = iter.next() { @@ -1765,7 +1766,7 @@ impl<'a> DisplayValue<'a> { let Some(arg) = args.get(index.wrapping_sub(1)) else { continue; }; - if let Some(arg) = arg.get(0) { + if let Some(arg) = arg.first() { write!(f, "{}", arg.display(self.options))?; } } @@ -1799,7 +1800,7 @@ impl<'a> DisplayValue<'a> { Ok(()) } - fn inner_template<'c>( + fn inner_template( &self, f: &mut std::fmt::Formatter<'_>, template: &[u8], @@ -1864,7 +1865,7 @@ fn interpret_show( } } -impl<'a, 'b> Display for DisplayValue<'a> { +impl Display for DisplayValue<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self.inner { ValueInner::Number { @@ -1919,7 +1920,7 @@ impl<'a, 'b> Display for DisplayValue<'a> { { todo!(); }*/ - f.write_str(&local) + f.write_str(local) } ValueInner::Template { args, local, .. } => self.template(f, &local, args), @@ -1943,10 +1944,10 @@ impl Value { // Returns an object that will format this value, including subscripts and // superscripts and footnotes. `options` controls whether variable and // value labels are included. - pub fn display<'a, 'b>(&'a self, options: impl AsValueOptions) -> DisplayValue<'a> { - let display = self.inner.display(options.as_value_options()); + pub fn display(&self, options: impl IntoValueOptions) -> DisplayValue<'_> { + let display = self.inner.display(options.into_value_options()); match &self.styling { - Some(styling) => display.with_styling(&*styling), + Some(styling) => display.with_styling(styling), None => display, } } @@ -2004,10 +2005,7 @@ pub enum ValueInner { impl ValueInner { pub fn is_empty(&self) -> bool { - match self { - Self::Empty => true, - _ => false, - } + matches!(self, Self::Empty) } fn show(&self) -> Option { match self { @@ -2051,8 +2049,8 @@ pub struct ValueStyle { impl ValueInner { // Returns an object that will format this value. Settings on `options` // control whether variable and value labels are included. - pub fn display<'a>(&'a self, options: impl AsValueOptions) -> DisplayValue<'a> { - let options = options.as_value_options(); + pub fn display(&self, options: impl IntoValueOptions) -> DisplayValue<'_> { + let options = options.into_value_options(); let (show_value, show_label) = if let Some(value_label) = self.value_label() { interpret_show( || Settings::global().show_values, @@ -2071,7 +2069,7 @@ impl ValueInner { (true, None) }; DisplayValue { - inner: &self, + inner: self, markup: false, subscripts: &[], footnotes: &[], diff --git a/rust/pspp/src/output/pivot/output.rs b/rust/pspp/src/output/pivot/output.rs index 8e9db75836..24ae41ee96 100644 --- a/rust/pspp/src/output/pivot/output.rs +++ b/rust/pspp/src/output/pivot/output.rs @@ -10,8 +10,8 @@ use crate::output::{ }; use super::{ - Area, AsValueOptions, Axis2, Axis3, Border, BorderStyle, BoxBorder, Color, Coord2, Dimension, - Footnote, PivotTable, Rect2, RowColBorder, Stroke, Value, + Area, Axis2, Axis3, Border, BorderStyle, BoxBorder, Color, Coord2, Dimension, Footnote, + IntoValueOptions, PivotTable, Rect2, RowColBorder, Stroke, Value, }; /// All of the combinations of dimensions along an axis. @@ -36,7 +36,7 @@ impl AxisEnumeration { fn iter(&self) -> AxisEnumerationIter { AxisEnumerationIter { - enumeration: &self, + enumeration: self, position: 0, } } @@ -128,7 +128,7 @@ impl PivotTable { Coord2::new(0, 0), self.look.areas.clone(), self.borders(false), - self.as_value_options(), + self.into_value_options(), ); for (y, row) in rows.enumerate() { table.put( @@ -169,7 +169,7 @@ impl PivotTable { stub, self.look.areas.clone(), self.borders(printing), - self.as_value_options(), + self.into_value_options(), ); for h in [Axis2::X, Axis2::Y] { @@ -248,10 +248,10 @@ impl PivotTable { Some(self.create_aux_table3(Area::Caption, [self.caption.as_ref()?.clone()].into_iter())) } - pub fn output_footnotes<'a>(&self, footnotes: &[Arc]) -> Option { + pub fn output_footnotes(&self, footnotes: &[Arc]) -> Option
{ self.create_aux_table_if_nonempty( Area::Footer, - footnotes.into_iter().map(|f| { + footnotes.iter().map(|f| { Box::new(Value::new_user_text(format!( "{}. {}", f.display_marker(self), @@ -328,7 +328,7 @@ struct HeadingColumn<'a> { groups: SmallVec<[Arc; 4]>, } -impl<'a> HeadingColumn<'a> { +impl HeadingColumn<'_> { pub fn get(&self, y: usize, height: usize) -> Option<&Value> { if y + 1 == height { Some(&self.leaf.name) diff --git a/rust/pspp/src/output/pivot/tlo.rs b/rust/pspp/src/output/pivot/tlo.rs index 512024635f..85eed639a0 100644 --- a/rust/pspp/src/output/pivot/tlo.rs +++ b/rust/pspp/src/output/pivot/tlo.rs @@ -378,7 +378,7 @@ impl super::AreaStyle { markup: false, font: style.font_name.string.clone(), fg: { - let fg = style.text_color.into(); + let fg = style.text_color; [fg, fg] }, bg: [bg, bg], diff --git a/rust/pspp/src/output/render.rs b/rust/pspp/src/output/render.rs index 1870a1f1d4..e4cd3ec3d6 100644 --- a/rust/pspp/src/output/render.rs +++ b/rust/pspp/src/output/render.rs @@ -381,7 +381,7 @@ impl Page { // `rules[Y]` is horizontal rules. let rules = EnumMap::from_fn(|axis| { (0..=n[axis]) - .map(|z| measure_rule(&*device, &*table, axis, z)) + .map(|z| measure_rule(device, &*table, axis, z)) .collect::>() }); @@ -426,7 +426,7 @@ impl Page { for cell in table.cells().filter(|cell| cell.col_span() > 1) { let rect = cell.rect(); - let w = device.measure_cell_width(&DrawCell::new(cell.inner(), &*table)); + let w = device.measure_cell_width(&DrawCell::new(cell.inner(), &table)); for i in 0..2 { distribute_spanned_width( w[i], @@ -489,7 +489,7 @@ impl Page { let rect = cell.rect(); let w = joined_width(&cp_x, rect[X].clone()); - let h = device.measure_cell_height(&DrawCell::new(cell.inner(), &*table), w); + let h = device.measure_cell_height(&DrawCell::new(cell.inner(), &table), w); let row = &mut unspanned_rows[cell.coord.y()]; if h > *row { @@ -502,7 +502,7 @@ impl Page { for cell in table.cells().filter(|cell| cell.row_span() > 1) { let rect = cell.rect(); let w = joined_width(&cp_x, rect[X].clone()); - let h = device.measure_cell_height(&DrawCell::new(cell.inner(), &*table), w); + let h = device.measure_cell_height(&DrawCell::new(cell.inner(), &table), w); distribute_spanned_width( h, &unspanned_rows[rect[Y].clone()], @@ -515,7 +515,7 @@ impl Page { let cp_y = Self::use_row_widths(&rows, &rules[Y]); // Measure headers. If they are "too big", get rid of them. - let mut h = table.h.clone(); + let mut h = table.h; for (axis, cp) in [(X, cp_x.as_slice()), (Y, cp_y.as_slice())] { let header_width = axis_width(cp, 0..table.h[axis]); let max_cell_width = (table.h[axis]..n[axis]) @@ -573,7 +573,7 @@ impl Page { min + extra }) .collect::>(); - return Self::use_row_widths(&rows_mid, rules); + Self::use_row_widths(&rows_mid, rules) } /// Returns the width of `extent` along `axis`. @@ -716,7 +716,7 @@ impl Page { // An edge is cut off if it was cut off in `self` or if we're trimming // pixels off that side of the page and there are no headers. - let mut is_edge_cutoff = self.is_edge_cutoff.clone(); + let mut is_edge_cutoff = self.is_edge_cutoff; is_edge_cutoff[a][0] = h[a] == 0 && (pixel0 > 0 || (z0 == 0 && self.is_edge_cutoff[a][0])); is_edge_cutoff[a][1] = pixel1 > 0 || (z1 == self.n[a] && self.is_edge_cutoff[a][1]); @@ -797,9 +797,7 @@ impl Page { let cell = self.get_cell(d); if cell.rect[a].end > z1 || (cell.rect[a].end == z1 && pixel1 > 0) - && overflows - .get(&s.coord_to_subpage(cell.rect.top_left())) - .is_none() + && overflows.contains_key(&s.coord_to_subpage(cell.rect.top_left())) { let mut overflow = self.overflows.get(&d).cloned().unwrap_or_default(); overflow[a][1] += @@ -819,7 +817,7 @@ impl Page { if rect[a].end > z0 && rect[a].start < z1 { overflows .entry(s.coord_to_subpage(rect.top_left())) - .or_insert(overflow.clone()); + .or_insert(*overflow); } } @@ -977,7 +975,7 @@ impl Page { let alternate_row = usize::checked_sub(cell.rect[Y].start, self.h[Y]).is_some_and(|row| row % 2 == 1); - let draw_cell = DrawCell::new(cell.content.inner(), &*self.table); + let draw_cell = DrawCell::new(cell.content.inner(), &self.table); let valign_offset = match draw_cell.style.cell_style.vert_align { VertAlign::Top => 0, VertAlign::Middle => self.extra_height(device, &bb, &draw_cell) / 2, diff --git a/rust/pspp/src/output/table.rs b/rust/pspp/src/output/table.rs index 4a774404fd..501a5e3905 100644 --- a/rust/pspp/src/output/table.rs +++ b/rust/pspp/src/output/table.rs @@ -27,7 +27,7 @@ pub struct CellRef<'a> { pub content: &'a Content, } -impl<'a> CellRef<'a> { +impl CellRef<'_> { pub fn inner(&self) -> &CellInner { self.content.inner() } @@ -68,7 +68,7 @@ pub enum Content { impl Content { pub fn inner(&self) -> &CellInner { match self { - Content::Value(cell_inner) => &cell_inner, + Content::Value(cell_inner) => cell_inner, Content::Join(cell) => &cell.inner, } } @@ -102,7 +102,7 @@ impl Content { } pub fn is_top_left(&self, coord: Coord2) -> bool { - self.joined_rect().map_or(true, |r| coord == r.top_left()) + self.joined_rect().is_none_or(|r| coord == r.top_left()) } pub fn span(&self, axis: Axis2) -> usize { @@ -301,7 +301,7 @@ pub struct XIter<'a> { y: usize, } -impl<'a> Iterator for XIter<'a> { +impl Iterator for XIter<'_> { type Item = usize; fn next(&mut self) -> Option { diff --git a/rust/pspp/src/output/text.rs b/rust/pspp/src/output/text.rs index 226e92d036..6489fd2a60 100644 --- a/rust/pspp/src/output/text.rs +++ b/rust/pspp/src/output/text.rs @@ -39,6 +39,12 @@ pub struct TextRenderer { lines: Vec, } +impl Default for TextRenderer { + fn default() -> Self { + Self::new() + } +} + impl TextRenderer { pub fn new() -> Self { let width = 80; @@ -260,7 +266,7 @@ static UNICODE_BOX: LazyLock = LazyLock::new(|| { }); impl PivotTable { - pub fn display<'a>(&'a self) -> DisplayPivotTable<'a> { + pub fn display(&self) -> DisplayPivotTable<'_> { DisplayPivotTable::new(self) } } @@ -281,10 +287,10 @@ impl<'a> DisplayPivotTable<'a> { } } -impl<'a> Display for DisplayPivotTable<'a> { +impl Display for DisplayPivotTable<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { for line in TextRenderer::new().render(self.pt) { - write!(f, "{}\n", line)?; + writeln!(f, "{}", line)?; } Ok(()) } @@ -413,10 +419,10 @@ where } } -fn new_line_breaks<'a>( - text: &'a str, +fn new_line_breaks( + text: &str, width: usize, -) -> LineBreaks<'a, impl Iterator + Clone + 'a> { +) -> LineBreaks<'_, impl Iterator + Clone + '_> { LineBreaks { text, max_width: width, @@ -487,7 +493,7 @@ impl Driver for TextDriver { Details::Message(_diagnostic) => todo!(), Details::PageBreak => (), Details::Table(pivot_table) => { - for line in self.renderer.render(&pivot_table) { + for line in self.renderer.render(pivot_table) { writeln!(self.file, "{}", line.str()).unwrap(); } } diff --git a/rust/pspp/src/output/text_line.rs b/rust/pspp/src/output/text_line.rs index 9a81402280..00cd44c7d7 100644 --- a/rust/pspp/src/output/text_line.rs +++ b/rust/pspp/src/output/text_line.rs @@ -1,6 +1,7 @@ use enum_iterator::Sequence; use std::{ borrow::Cow, + cmp::Ordering, fmt::{Debug, Display}, ops::Range, }; @@ -37,14 +38,16 @@ impl TextLine { /// the current width, extends the line with spaces. If `x` is shorter than /// the current width, removes trailing characters. pub fn resize(&mut self, x: usize) { - if x > self.width { - self.string.extend((self.width..x).map(|_| ' ')); - } else if x < self.width { - let pos = self.find_pos(x); - self.string.truncate(pos.offsets.start); - if x > pos.offsets.start { - self.string.extend((pos.offsets.start..x).map(|_| '?')); + match x.cmp(&self.width) { + Ordering::Greater => self.string.extend((self.width..x).map(|_| ' ')), + Ordering::Less => { + let pos = self.find_pos(x); + self.string.truncate(pos.offsets.start); + if x > pos.offsets.start { + self.string.extend((pos.offsets.start..x).map(|_| '?')); + } } + Ordering::Equal => return, } self.width = x; } @@ -170,7 +173,7 @@ impl<'a> Widths<'a> { } } -impl<'a> Iterator for Widths<'a> { +impl Iterator for Widths<'_> { type Item = usize; fn next(&mut self) -> Option { @@ -193,13 +196,13 @@ impl<'a> Iterator for Widths<'a> { return Some(0); } - while let Some((index, c)) = iter.next() { + for (index, c) in iter { if c.width().is_some_and(|width| width > 0) { self.s = &self.s[index..]; return Some(w); } } - self.s = iter.as_str(); + self.s = ""; Some(w) } } diff --git a/rust/pspp/src/raw.rs b/rust/pspp/src/raw.rs index 8db959052b..b8d0ea2cb9 100644 --- a/rust/pspp/src/raw.rs +++ b/rust/pspp/src/raw.rs @@ -450,7 +450,7 @@ impl HeaderRecord { let layout_code: [u8; 4] = read_bytes(r)?; let endian = Endian::identify_u32(2, layout_code) .or_else(|| Endian::identify_u32(2, layout_code)) - .ok_or_else(|| Error::NotASystemFile)?; + .ok_or(Error::NotASystemFile)?; let layout_code = endian.parse(layout_code); let nominal_case_size: u32 = endian.parse(read_bytes(r)?); -- 2.30.2