This is an automated email from the ASF dual-hosted git repository.
Jefffrey pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
The following commit(s) were added to refs/heads/main by this push:
new f5aba4f86e More workspace lints: fill out `[workspace.lints.clippy]`
(#10552)
f5aba4f86e is described below
commit f5aba4f86efa5dfe1856ce14a5e829fa9304448d
Author: Emil Ernerfeldt <[email protected]>
AuthorDate: Wed Aug 5 08:26:12 2026 -0700
More workspace lints: fill out `[workspace.lints.clippy]` (#10552)
# Which issue does this PR close?
No issue in particular
- Follow-up to #10533
# Rationale for this change
#10533 added `[workspace.lints]` with a minimal set of lints.
This fills out PR `[workspace.lints.clippy]` with more lints that I've
hand-picked over the years.
Some stylistic changes, but also a lot of things that improve
performance.
Let me know if you disagree with any of them and I'll revert them.
More coming in later PRs :)
# What changes are included in this PR?
Best reviewed commit by commit!
# Are these changes tested?
By CI
# Are there any user-facing changes?
No public API changed.
---------
Co-authored-by: Jeffrey Vo <[email protected]>
Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
---
Cargo.toml | 62 +++++++++++++++++
arrow-array/src/array/byte_array.rs | 2 +-
arrow-array/src/array/byte_view_array.rs | 2 +-
arrow-array/src/array/fixed_size_binary_array.rs | 2 +-
arrow-array/src/builder/generic_bytes_builder.rs | 2 +-
arrow-array/src/ffi.rs | 2 +-
arrow-array/src/iterator.rs | 2 +-
arrow-array/src/trusted_len.rs | 2 +-
arrow-avro/src/codec.rs | 4 +-
arrow-avro/src/reader/record.rs | 5 +-
arrow-buffer/src/bigint/mod.rs | 6 +-
arrow-buffer/src/buffer/mutable.rs | 8 +--
arrow-buffer/src/buffer/run.rs | 4 +-
arrow-buffer/src/bytes.rs | 4 +-
arrow-csv/src/writer.rs | 4 ++
arrow-data/src/data.rs | 2 +-
arrow-flight/gen/src/main.rs | 20 +-----
arrow-flight/src/sql/client.rs | 4 ++
arrow-integration-test/src/lib.rs | 7 +-
.../flight_server_scenarios/auth_basic_proto.rs | 24 +++----
.../flight_server_scenarios/integration_test.rs | 10 ++-
arrow-ipc/src/reader.rs | 3 +-
arrow-ipc/src/writer.rs | 17 +++--
arrow-ord/src/sort.rs | 10 +--
arrow-schema/src/ffi.rs | 4 +-
arrow-select/src/take.rs | 4 +-
arrow-string/src/concat_elements.rs | 2 +-
arrow/benches/builder.rs | 4 ++
arrow/benches/cast_kernels.rs | 2 +-
parquet-variant/src/builder/metadata.rs | 2 +-
parquet-variant/src/decoder.rs | 2 +-
parquet-variant/tests/variant_interop.rs | 2 +-
parquet/src/arrow/mod.rs | 2 +-
.../src/arrow/record_reader/definition_levels.rs | 14 +---
parquet/src/arrow/record_reader/mod.rs | 2 +-
parquet/src/column/chunker/cdc.rs | 37 +++++-----
parquet/src/file/metadata/thrift/mod.rs | 79 ++++++++++------------
parquet/src/file/page_index/column_index.rs | 2 +-
parquet/src/file/serialized_reader.rs | 51 +++++++-------
parquet/src/record/reader.rs | 5 +-
parquet_derive_test/src/lib.rs | 4 ++
41 files changed, 235 insertions(+), 191 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
index 7f7d98cf10..39ec344fcd 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -154,37 +154,99 @@ broken_intra_doc_links = "warn"
missing_crate_level_docs = "warn"
[workspace.lints.clippy]
+as_ptr_cast_mut = "warn"
+assigning_clones = "warn"
bool_to_int_with_if = "warn"
+checked_conversions = "warn"
+clear_with_drain = "warn"
+comparison_chain = "warn"
dbg_macro = "warn"
debug_assert_with_mut_call = "warn"
+default_union_representation = "warn"
+disallowed_script_idents = "warn"
doc_comment_double_space_linebreaks = "warn"
doc_include_without_cfg = "warn"
+empty_enum_variants_with_brackets = "warn"
+exit = "warn"
+expl_impl_clone_on_copy = "warn"
+explicit_deref_methods = "warn"
+filter_map_next = "warn"
flat_map_option = "warn"
+float_cmp_const = "warn"
+fn_params_excessive_bools = "warn"
+fn_to_numeric_cast_any = "warn"
format_push_string = "warn"
+imprecise_flops = "warn"
+inconsistent_struct_constructor = "warn"
+index_refutable_slice = "warn"
+inefficient_to_string = "warn"
+infinite_loop = "warn"
+into_iter_without_iter = "warn"
invalid_upcast_comparisons = "warn"
+iter_filter_is_ok = "warn"
iter_filter_is_some = "warn"
+iter_not_returning_iterator = "warn"
+iter_on_empty_collections = "warn"
iter_with_drain = "warn"
+large_digit_groups = "warn"
+large_futures = "warn"
+large_include_file = "warn"
+large_stack_arrays = "warn"
+large_stack_frames = "warn"
+large_types_passed_by_value = "warn"
+linkedlist = "warn"
literal_string_with_formatting_args = "warn"
+lossy_float_literal = "warn"
+macro_use_imports = "warn"
manual_instant_elapsed = "warn"
+manual_is_power_of_two = "warn"
+manual_midpoint = "warn"
match_wild_err_arm = "warn"
+mismatching_type_param_order = "warn"
mut_mut = "warn"
mutex_integer = "warn"
+negative_feature_names = "warn"
+non_zero_suggestions = "warn"
+nonstandard_macro_braces = "warn"
option_as_ref_cloned = "warn"
+option_option = "warn"
path_buf_push_overwrite = "warn"
pathbuf_init_then_push = "warn"
+ptr_cast_constness = "warn"
ptr_offset_by_literal = "warn"
+pub_without_shorthand = "warn"
rc_mutex = "warn"
ref_binding_to_reference = "warn"
+ref_option_ref = "warn"
+rest_pat_in_fully_bound_structs = "warn"
+same_functions_in_if_condition = "warn"
same_length_and_capacity = "warn"
+set_contains_or_insert = "warn"
should_panic_without_expect = "warn"
single_char_pattern = "warn"
+single_option_map = "warn"
stable_sort_primitive = "warn"
+str_split_at_newline = "warn"
+string_add_assign = "warn"
+string_lit_chars_any = "warn"
+suspicious_xor_used_as_pow = "warn"
+todo = "warn"
trailing_empty_array = "warn"
trait_duplication_in_bounds = "warn"
+transmute_ptr_to_ptr = "warn"
+tuple_array_conversions = "warn"
+uninhabited_references = "warn"
unnecessary_box_returns = "warn"
+unnecessary_literal_bound = "warn"
+unnecessary_safety_doc = "warn"
unnecessary_self_imports = "warn"
unnecessary_struct_initialization = "warn"
+unused_async = "warn"
unused_peekable = "warn"
+unused_rounding = "warn"
+useless_let_if_seq = "warn"
+verbose_file_reads = "warn"
+wildcard_dependencies = "warn"
zero_sized_map_values = "warn"
# release inherited profile keeping debug information and symbols
diff --git a/arrow-array/src/array/byte_array.rs
b/arrow-array/src/array/byte_array.rs
index e582968174..cd9d446f4d 100644
--- a/arrow-array/src/array/byte_array.rs
+++ b/arrow-array/src/array/byte_array.rs
@@ -574,9 +574,9 @@ impl<T: ByteArrayType> From<ArrayData> for
GenericByteArray<T> {
// ArrayData is valid, and verified type above
let value_offsets = unsafe { get_offsets_from_buffer(offset_buffer,
offset, len) };
Self {
+ data_type,
value_offsets,
value_data,
- data_type,
nulls,
}
}
diff --git a/arrow-array/src/array/byte_view_array.rs
b/arrow-array/src/array/byte_view_array.rs
index 256c5996f2..d1b1721034 100644
--- a/arrow-array/src/array/byte_view_array.rs
+++ b/arrow-array/src/array/byte_view_array.rs
@@ -618,7 +618,7 @@ impl<T: ByteViewType + ?Sized> GenericByteViewArray<T> {
total_len: current_elements,
});
}
- debug_assert!(groups.len() <= i32::MAX as usize);
+ debug_assert!(i32::try_from(groups.len()).is_ok());
// Second pass: copy each group into an exactly-sized buffer.
let mut views_buf = Vec::with_capacity(len);
diff --git a/arrow-array/src/array/fixed_size_binary_array.rs
b/arrow-array/src/array/fixed_size_binary_array.rs
index 98a812460b..254e00cd6a 100644
--- a/arrow-array/src/array/fixed_size_binary_array.rs
+++ b/arrow-array/src/array/fixed_size_binary_array.rs
@@ -694,9 +694,9 @@ impl From<ArrayData> for FixedSizeBinaryArray {
Self {
data_type,
+ value_data,
nulls,
len,
- value_data,
value_size,
}
}
diff --git a/arrow-array/src/builder/generic_bytes_builder.rs
b/arrow-array/src/builder/generic_bytes_builder.rs
index a2d044e808..f449219c6b 100644
--- a/arrow-array/src/builder/generic_bytes_builder.rs
+++ b/arrow-array/src/builder/generic_bytes_builder.rs
@@ -76,8 +76,8 @@ impl<T: ByteArrayType> GenericByteBuilder<T> {
.unwrap_or_else(||
NullBufferBuilder::new_with_len(offsets_builder.len() - 1));
Self {
- offsets_builder,
value_builder,
+ offsets_builder,
null_buffer_builder,
}
}
diff --git a/arrow-array/src/ffi.rs b/arrow-array/src/ffi.rs
index e1761beb2b..970419c633 100644
--- a/arrow-array/src/ffi.rs
+++ b/arrow-array/src/ffi.rs
@@ -234,7 +234,7 @@ unsafe fn create_buffer(
if array.num_buffers() == 0 {
return None;
}
- NonNull::new(array.buffer(index) as _)
+ NonNull::new(array.buffer(index).cast_mut())
.map(|ptr| unsafe { Buffer::from_custom_allocation(ptr, len, owner) })
}
diff --git a/arrow-array/src/iterator.rs b/arrow-array/src/iterator.rs
index 9f72313b9a..156e296cf1 100644
--- a/arrow-array/src/iterator.rs
+++ b/arrow-array/src/iterator.rs
@@ -895,7 +895,7 @@ mod tests {
let mut items = Vec::with_capacity(iter.len());
let cb = |acc, item| {
- items.push(CallArgs { item, acc });
+ items.push(CallArgs { acc, item });
item.map(|val| val + 100)
};
diff --git a/arrow-array/src/trusted_len.rs b/arrow-array/src/trusted_len.rs
index b2e1948ccc..8a3c3edec0 100644
--- a/arrow-array/src/trusted_len.rs
+++ b/arrow-array/src/trusted_len.rs
@@ -49,7 +49,7 @@ where
dst = unsafe { dst.add(1) };
}
assert_eq!(
- unsafe { dst.offset_from(buffer.as_ptr() as *mut T) as usize },
+ unsafe { dst.offset_from(buffer.as_ptr().cast::<T>()) as usize },
upper,
"Trusted iterator length was not accurately reported"
);
diff --git a/arrow-avro/src/codec.rs b/arrow-avro/src/codec.rs
index c4df569ba0..5618539c50 100644
--- a/arrow-avro/src/codec.rs
+++ b/arrow-avro/src/codec.rs
@@ -208,9 +208,9 @@ impl AvroDataType {
resolution: Option<ResolutionInfo>,
) -> Self {
Self {
- codec,
- metadata,
nullability,
+ metadata,
+ codec,
resolution,
}
}
diff --git a/arrow-avro/src/reader/record.rs b/arrow-avro/src/reader/record.rs
index 13382557ee..beb4102de1 100644
--- a/arrow-avro/src/reader/record.rs
+++ b/arrow-avro/src/reader/record.rs
@@ -2330,7 +2330,10 @@ fn process_block_items(
total: usize,
on_item: &mut impl FnMut(&mut AvroCursor) -> Result<(), AvroError>,
) -> Result<usize, AvroError> {
- let Some(new_total) = total.checked_add(count).filter(|&t| t <= i32::MAX
as usize) else {
+ let Some(new_total) = total
+ .checked_add(count)
+ .filter(|&t| i32::try_from(t).is_ok())
+ else {
return Err(AvroError::ParseError(
"Capacity overflow when decoding array/map item
blocks".to_string(),
));
diff --git a/arrow-buffer/src/bigint/mod.rs b/arrow-buffer/src/bigint/mod.rs
index 81392c3c3a..d8328cb06f 100644
--- a/arrow-buffer/src/bigint/mod.rs
+++ b/arrow-buffer/src/bigint/mod.rs
@@ -768,7 +768,7 @@ impl i256 {
.wrapping_add(rhs.high as u128)
.wrapping_add(carry as u128) as i128;
- let result = Self { high, low };
+ let result = Self { low, high };
// Signed overflow occurs when:
// - both operands have the same sign, and
@@ -792,7 +792,7 @@ impl i256 {
.wrapping_sub(rhs.high as u128)
.wrapping_sub(borrow as u128) as i128;
- let result = Self { high, low };
+ let result = Self { low, high };
// Signed overflow occurs when:
// - operands have opposite signs, and
@@ -1812,7 +1812,7 @@ mod tests {
assert_eq!(v.to_f64().unwrap(), 42.0);
let v = i256::from_i128(-123456789012345678i128);
- assert_eq!(v.to_f64().unwrap(), -123456789012345678.0);
+ assert_eq!(v.to_f64().unwrap(), -123_456_789_012_345_680.0);
let v = i256::from_string("0").unwrap();
assert_eq!(v.to_f64().unwrap(), 0.0);
diff --git a/arrow-buffer/src/buffer/mutable.rs
b/arrow-buffer/src/buffer/mutable.rs
index b30a932b35..e83b0c4708 100644
--- a/arrow-buffer/src/buffer/mutable.rs
+++ b/arrow-buffer/src/buffer/mutable.rs
@@ -381,7 +381,7 @@ impl MutableBuffer {
let byte_count = to_copy * bytes_per_copy;
unsafe {
// Get to the start of the data before we started copying
anything
- let src = self.data.as_ptr().add(length_before) as *const u8;
+ let src = self.data.as_ptr().add(length_before).cast_const();
// Go to the current location to copy to (end of current data)
let dst = self.data.as_ptr().add(self.len);
// SAFETY: the pointers are not overlapping as there is
`byte_count` or less between them
@@ -963,10 +963,10 @@ impl<A: ArrowNativeType> Extend<A> for MutableBuffer {
}
impl<T: ArrowNativeType> From<Vec<T>> for MutableBuffer {
- fn from(value: Vec<T>) -> Self {
+ fn from(mut value: Vec<T>) -> Self {
// Safety
- // Vec::as_ptr guaranteed to not be null and ArrowNativeType are
trivially transmutable
- let data = unsafe { NonNull::new_unchecked(value.as_ptr() as _) };
+ // Vec::as_mut_ptr guaranteed to not be null and ArrowNativeType are
trivially transmutable
+ let data = unsafe { NonNull::new_unchecked(value.as_mut_ptr().cast())
};
let len = value.len() * mem::size_of::<T>();
// Safety
// Vec guaranteed to have a valid layout matching that of
`Layout::array`
diff --git a/arrow-buffer/src/buffer/run.rs b/arrow-buffer/src/buffer/run.rs
index 703ae91380..c65e3b5cc6 100644
--- a/arrow-buffer/src/buffer/run.rs
+++ b/arrow-buffer/src/buffer/run.rs
@@ -132,8 +132,8 @@ where
Self {
run_ends,
- logical_offset,
logical_length,
+ logical_offset,
}
}
@@ -151,8 +151,8 @@ where
) -> Self {
Self {
run_ends,
- logical_offset,
logical_length,
+ logical_offset,
}
}
diff --git a/arrow-buffer/src/bytes.rs b/arrow-buffer/src/bytes.rs
index a80a347fa1..d473f13dac 100644
--- a/arrow-buffer/src/bytes.rs
+++ b/arrow-buffer/src/bytes.rs
@@ -231,7 +231,9 @@ impl From<bytes::Bytes> for Bytes {
let len = value.len();
Self {
len,
- ptr: NonNull::new(value.as_ptr() as _).unwrap(),
+ // `bytes::Bytes` is shared and immutable, so the buffer is never
written
+ // through this pointer; the cast only changes constness.
+ ptr: NonNull::new(value.as_ptr().cast_mut()).unwrap(),
deallocation: Deallocation::Custom(std::sync::Arc::new(value),
len),
#[cfg(feature = "pool")]
reservation: Mutex::new(None),
diff --git a/arrow-csv/src/writer.rs b/arrow-csv/src/writer.rs
index 72dcb640e1..5236775b68 100644
--- a/arrow-csv/src/writer.rs
+++ b/arrow-csv/src/writer.rs
@@ -666,6 +666,10 @@ impl WriterBuilder {
}
#[cfg(test)]
+#[expect(
+ clippy::verbose_file_reads,
+ reason = "`tempfile::tempfile()` has no path, so the contents can only be
read back through the handle"
+)]
mod tests {
use super::*;
diff --git a/arrow-data/src/data.rs b/arrow-data/src/data.rs
index 13e5f730e6..b1ce4f22b4 100644
--- a/arrow-data/src/data.rs
+++ b/arrow-data/src/data.rs
@@ -2222,7 +2222,7 @@ impl ArrayDataBuilder {
/// Creates an `ArrayData`, consuming `self`
///
- /// # Safety
+ /// # Undefined behavior
///
/// By default the underlying buffers are checked to ensure they are valid
/// Arrow data. However, if the [`Self::skip_validation`] flag has been set
diff --git a/arrow-flight/gen/src/main.rs b/arrow-flight/gen/src/main.rs
index cd50214f1c..08254ff2b2 100644
--- a/arrow-flight/gen/src/main.rs
+++ b/arrow-flight/gen/src/main.rs
@@ -17,11 +17,7 @@
//! Generates the Rust bindings for the Arrow Flight protobuf definitions.
-use std::{
- fs::OpenOptions,
- io::{Read, Write},
- path::Path,
-};
+use std::{fs::OpenOptions, io::Write, path::Path};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let proto_dir = Path::new("../format");
@@ -33,12 +29,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.out_dir("src")
.compile_with_config(prost_config(), &[proto_path], &[proto_dir])?;
- // read file contents to string
- let mut file = OpenOptions::new()
- .read(true)
- .open("src/arrow.flight.protocol.rs")?;
- let mut buffer = String::new();
- file.read_to_string(&mut buffer)?;
+ let buffer = std::fs::read_to_string("src/arrow.flight.protocol.rs")?;
// append warning that file was auto-generated
let mut file = OpenOptions::new()
.write(true)
@@ -56,12 +47,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.out_dir("src/sql")
.compile_with_config(prost_config(), &[proto_path], &[proto_dir])?;
- // read file contents to string
- let mut file = OpenOptions::new()
- .read(true)
- .open("src/sql/arrow.flight.protocol.sql.rs")?;
- let mut buffer = String::new();
- file.read_to_string(&mut buffer)?;
+ let buffer =
std::fs::read_to_string("src/sql/arrow.flight.protocol.sql.rs")?;
// append warning that file was auto-generate
let mut file = OpenOptions::new()
.write(true)
diff --git a/arrow-flight/src/sql/client.rs b/arrow-flight/src/sql/client.rs
index 28a4a7f972..8ef80da50b 100644
--- a/arrow-flight/src/sql/client.rs
+++ b/arrow-flight/src/sql/client.rs
@@ -441,6 +441,10 @@ where
}
/// Explicitly shut down and clean up the client.
+ #[expect(
+ clippy::unused_async,
+ reason = "public API: dropping `async` would break callers that
`.await` it"
+ )]
pub async fn close(&mut self) -> Result<()> {
// TODO: consume self instead of &mut self to explicitly prevent reuse?
Ok(())
diff --git a/arrow-integration-test/src/lib.rs
b/arrow-integration-test/src/lib.rs
index ac027554b2..0d5477e955 100644
--- a/arrow-integration-test/src/lib.rs
+++ b/arrow-integration-test/src/lib.rs
@@ -1272,9 +1272,6 @@ impl ArrowJsonBatch {
mod tests {
use super::*;
- use std::fs::File;
- use std::io::Read;
-
#[test]
fn test_schema_equality() {
let json = r#"
@@ -1596,9 +1593,7 @@ mod tests {
],
)
.unwrap();
- let mut file = File::open("data/integration.json").unwrap();
- let mut json = String::new();
- file.read_to_string(&mut json).unwrap();
+ let json = std::fs::read_to_string("data/integration.json").unwrap();
let arrow_json: ArrowJson = serde_json::from_str(&json).unwrap();
// test schemas
assert!(arrow_json.schema.equals_schema(&schema));
diff --git
a/arrow-integration-testing/src/flight_server_scenarios/auth_basic_proto.rs
b/arrow-integration-testing/src/flight_server_scenarios/auth_basic_proto.rs
index 38582e6fef..65466c171b 100644
--- a/arrow-integration-testing/src/flight_server_scenarios/auth_basic_proto.rs
+++ b/arrow-integration-testing/src/flight_server_scenarios/auth_basic_proto.rs
@@ -65,15 +65,15 @@ pub struct AuthBasicProtoScenarioImpl {
}
impl AuthBasicProtoScenarioImpl {
- async fn check_auth(&self, metadata: &MetadataMap) ->
Result<GrpcServerCallContext, Status> {
+ fn check_auth(&self, metadata: &MetadataMap) ->
Result<GrpcServerCallContext, Status> {
let token = metadata
.get_bin("auth-token-bin")
.and_then(|v| v.to_bytes().ok())
.and_then(|b| String::from_utf8(b.to_vec()).ok());
- self.is_valid(token).await
+ self.is_valid(token)
}
- async fn is_valid(&self, token: Option<String>) ->
Result<GrpcServerCallContext, Status> {
+ fn is_valid(&self, token: Option<String>) -> Result<GrpcServerCallContext,
Status> {
match token {
Some(t) if t == *self.username => Ok(GrpcServerCallContext {
peer_identity: self.username.to_string(),
@@ -107,7 +107,7 @@ impl FlightService for AuthBasicProtoScenarioImpl {
&self,
request: Request<FlightDescriptor>,
) -> Result<Response<SchemaResult>, Status> {
- self.check_auth(request.metadata()).await?;
+ self.check_auth(request.metadata())?;
Err(Status::unimplemented("Not yet implemented"))
}
@@ -115,7 +115,7 @@ impl FlightService for AuthBasicProtoScenarioImpl {
&self,
request: Request<Ticket>,
) -> Result<Response<Self::DoGetStream>, Status> {
- self.check_auth(request.metadata()).await?;
+ self.check_auth(request.metadata())?;
Err(Status::unimplemented("Not yet implemented"))
}
@@ -170,7 +170,7 @@ impl FlightService for AuthBasicProtoScenarioImpl {
&self,
request: Request<Criteria>,
) -> Result<Response<Self::ListFlightsStream>, Status> {
- self.check_auth(request.metadata()).await?;
+ self.check_auth(request.metadata())?;
Err(Status::unimplemented("Not yet implemented"))
}
@@ -178,7 +178,7 @@ impl FlightService for AuthBasicProtoScenarioImpl {
&self,
request: Request<FlightDescriptor>,
) -> Result<Response<FlightInfo>, Status> {
- self.check_auth(request.metadata()).await?;
+ self.check_auth(request.metadata())?;
Err(Status::unimplemented("Not yet implemented"))
}
@@ -186,7 +186,7 @@ impl FlightService for AuthBasicProtoScenarioImpl {
&self,
request: Request<FlightDescriptor>,
) -> Result<Response<PollInfo>, Status> {
- self.check_auth(request.metadata()).await?;
+ self.check_auth(request.metadata())?;
Err(Status::unimplemented("Not yet implemented"))
}
@@ -195,7 +195,7 @@ impl FlightService for AuthBasicProtoScenarioImpl {
request: Request<Streaming<FlightData>>,
) -> Result<Response<Self::DoPutStream>, Status> {
let metadata = request.metadata();
- self.check_auth(metadata).await?;
+ self.check_auth(metadata)?;
Err(Status::unimplemented("Not yet implemented"))
}
@@ -203,7 +203,7 @@ impl FlightService for AuthBasicProtoScenarioImpl {
&self,
request: Request<Action>,
) -> Result<Response<Self::DoActionStream>, Status> {
- let flight_context = self.check_auth(request.metadata()).await?;
+ let flight_context = self.check_auth(request.metadata())?;
// Respond with the authenticated username.
let buf = flight_context.peer_identity().as_bytes().to_vec().into();
let result = arrow_flight::Result { body: buf };
@@ -215,7 +215,7 @@ impl FlightService for AuthBasicProtoScenarioImpl {
&self,
request: Request<Empty>,
) -> Result<Response<Self::ListActionsStream>, Status> {
- self.check_auth(request.metadata()).await?;
+ self.check_auth(request.metadata())?;
Err(Status::unimplemented("Not yet implemented"))
}
@@ -224,7 +224,7 @@ impl FlightService for AuthBasicProtoScenarioImpl {
request: Request<Streaming<FlightData>>,
) -> Result<Response<Self::DoExchangeStream>, Status> {
let metadata = request.metadata();
- self.check_auth(metadata).await?;
+ self.check_auth(metadata)?;
Err(Status::unimplemented("Not yet implemented"))
}
}
diff --git
a/arrow-integration-testing/src/flight_server_scenarios/integration_test.rs
b/arrow-integration-testing/src/flight_server_scenarios/integration_test.rs
index ae31688638..42227b5c09 100644
--- a/arrow-integration-testing/src/flight_server_scenarios/integration_test.rs
+++ b/arrow-integration-testing/src/flight_server_scenarios/integration_test.rs
@@ -318,7 +318,7 @@ async fn send_app_metadata(
.map_err(|e| Status::internal(format!("Could not send PutResult: {e:?}")))
}
-async fn record_batch_from_message(
+fn record_batch_from_message(
message: ipc::Message<'_>,
data_body: &Buffer,
schema_ref: SchemaRef,
@@ -341,7 +341,7 @@ async fn record_batch_from_message(
.map_err(|e| Status::internal(format!("Could not convert to
RecordBatch: {e:?}")))
}
-async fn dictionary_from_message(
+fn dictionary_from_message(
message: ipc::Message<'_>,
data_body: &Buffer,
schema_ref: SchemaRef,
@@ -393,8 +393,7 @@ async fn save_uploaded_chunks(
&Buffer::from(data.data_body.as_ref()),
schema_ref.clone(),
&dictionaries_by_id,
- )
- .await?;
+ )?;
chunks.push(batch);
}
@@ -404,8 +403,7 @@ async fn save_uploaded_chunks(
&Buffer::from(data.data_body.as_ref()),
schema_ref.clone(),
&mut dictionaries_by_id,
- )
- .await?;
+ )?;
}
t => {
return Err(Status::internal(format!(
diff --git a/arrow-ipc/src/reader.rs b/arrow-ipc/src/reader.rs
index 3cd11adda0..6e2a35690d 100644
--- a/arrow-ipc/src/reader.rs
+++ b/arrow-ipc/src/reader.rs
@@ -534,7 +534,8 @@ impl<'a> RecordBatchDecoder<'a> {
/// - Offset bounds (e.g. list/string offsets pointing past the end of
their value buffer)
/// - UTF-8 validity of string columns (`Utf8` / `LargeUtf8`)
/// - Null count consistency and buffer length checks
- /// # Safety
+ ///
+ /// # Undefined behavior
///
/// Relies on the caller only passing a flag with `true` value if they are
/// certain that the data is valid. Invalid data that bypasses these checks
diff --git a/arrow-ipc/src/writer.rs b/arrow-ipc/src/writer.rs
index 6d0d9a7eee..ae2c261324 100644
--- a/arrow-ipc/src/writer.rs
+++ b/arrow-ipc/src/writer.rs
@@ -2275,18 +2275,19 @@ fn reencode_offsets<O: OffsetSizeTrait>(
/// In particular, this handles re-encoding the offsets if they don't start at
`0`,
/// slicing the values buffer as appropriate. This helps reduce the encoded
/// size of sliced arrays, as values that have been sliced away are not encoded
-fn get_byte_array_buffers<O: OffsetSizeTrait>(data: &ArrayData) -> (Buffer,
Buffer) {
+/// Returns the offsets and values buffers, in that order.
+fn get_byte_array_buffers<O: OffsetSizeTrait>(data: &ArrayData) -> [Buffer; 2]
{
if data.is_empty() {
// As per specification, offsets buffer has N+1 elements.
// So an empty array should still be encoded with a single 0 offset.
let mut offsets = MutableBuffer::new(size_of::<O>());
offsets.extend_from_slice(O::usize_as(0).to_byte_slice());
- return (offsets.into(), MutableBuffer::new(0).into());
+ return [offsets.into(), MutableBuffer::new(0).into()];
}
let (offsets, original_start_offset, len) =
reencode_offsets::<O>(&data.buffers()[0], data);
let values = data.buffers()[1].slice_with_length(original_start_offset,
len);
- (offsets, values)
+ [offsets, values]
}
/// Similar logic as [`get_byte_array_buffers()`] but slices the child array
instead
@@ -2409,8 +2410,7 @@ fn write_array_data(
let data_type = array_data.data_type();
if matches!(data_type, DataType::Binary | DataType::Utf8) {
- let (offsets, values) = get_byte_array_buffers::<i32>(array_data);
- for buffer in [offsets, values] {
+ for buffer in get_byte_array_buffers::<i32>(array_data) {
offset = encode_sink_buffer(
buffer,
meta,
@@ -2451,8 +2451,7 @@ fn write_array_data(
)?;
}
} else if matches!(data_type, DataType::LargeBinary | DataType::LargeUtf8)
{
- let (offsets, values) = get_byte_array_buffers::<i64>(array_data);
- for buffer in [offsets, values] {
+ for buffer in get_byte_array_buffers::<i64>(array_data) {
offset = encode_sink_buffer(
buffer,
meta,
@@ -3089,7 +3088,7 @@ mod tests {
#[test]
fn test_empty_utf8_ipc_writes_nonempty_offsets_buffer() {
let name = StringArray::from(Vec::<String>::new());
- let (offsets, values) = get_byte_array_buffers::<i32>(&name.to_data());
+ let [offsets, values] = get_byte_array_buffers::<i32>(&name.to_data());
assert_eq!(name.len(), 0);
assert_eq!(
@@ -3103,7 +3102,7 @@ mod tests {
#[test]
fn test_empty_large_utf8_ipc_writes_nonempty_offsets_buffer() {
let name = LargeStringArray::from(Vec::<String>::new());
- let (offsets, values) = get_byte_array_buffers::<i64>(&name.to_data());
+ let [offsets, values] = get_byte_array_buffers::<i64>(&name.to_data());
assert_eq!(name.len(), 0);
assert_eq!(
diff --git a/arrow-ord/src/sort.rs b/arrow-ord/src/sort.rs
index 0c6720e8f2..fea43dc1a7 100644
--- a/arrow-ord/src/sort.rs
+++ b/arrow-ord/src/sort.rs
@@ -1095,11 +1095,11 @@ fn sift_down_worst_heap(
}
let right = left + 1;
- let mut worst = left;
-
- if right < heap.len() && compare(heap[left], heap[right]) ==
Ordering::Less {
- worst = right;
- }
+ let worst = if right < heap.len() && compare(heap[left], heap[right])
== Ordering::Less {
+ right
+ } else {
+ left
+ };
if compare(heap[pos], heap[worst]) != Ordering::Less {
break;
diff --git a/arrow-schema/src/ffi.rs b/arrow-schema/src/ffi.rs
index d8f779c364..7b6332632e 100644
--- a/arrow-schema/src/ffi.rs
+++ b/arrow-schema/src/ffi.rs
@@ -110,9 +110,9 @@ unsafe extern "C" fn release_schema(schema: *mut
FFI_ArrowSchema) {
let schema = unsafe { &mut *schema };
// take ownership back to release it.
- drop(unsafe { CString::from_raw(schema.format as *mut c_char) });
+ drop(unsafe { CString::from_raw(schema.format.cast_mut()) });
if !schema.name.is_null() {
- drop(unsafe { CString::from_raw(schema.name as *mut c_char) });
+ drop(unsafe { CString::from_raw(schema.name.cast_mut()) });
}
if !schema.private_data.is_null() {
let private_data = unsafe { Box::from_raw(schema.private_data as *mut
SchemaPrivateData) };
diff --git a/arrow-select/src/take.rs b/arrow-select/src/take.rs
index 0c550ea0b8..fccf354b94 100644
--- a/arrow-select/src/take.rs
+++ b/arrow-select/src/take.rs
@@ -63,7 +63,7 @@ use num_traits::Zero;
/// * An index cannot be casted to `usize` (typically 32 bit architectures)
/// * An index is out of bounds and `options` is set to check bounds.
///
-/// # Safety
+/// # Panics
///
/// When `options` is not set to check bounds, taking indexes after `len` will
panic.
///
@@ -132,7 +132,7 @@ pub fn take(
/// * An index cannot be casted to `usize` (typically 32 bit architectures)
/// * An index is out of bounds and `options` is set to check bounds.
///
-/// # Safety
+/// # Panics
///
/// When `options` is not set to check bounds, taking indexes after `len` will
panic.
///
diff --git a/arrow-string/src/concat_elements.rs
b/arrow-string/src/concat_elements.rs
index 72898793b8..cbba7fbec6 100644
--- a/arrow-string/src/concat_elements.rs
+++ b/arrow-string/src/concat_elements.rs
@@ -318,7 +318,7 @@ where
// in `concat_elements_view_array`, so offset cannot exceed it.
// Not using `u32::try_from` on each insertion makes a ~5%
difference
// in benchmarking
- debug_assert!(offset <= i32::MAX as usize);
+ debug_assert!(i32::try_from(offset).is_ok());
let view_offset: u32 = offset as u32;
self.data.extend_from_slice(left);
diff --git a/arrow/benches/builder.rs b/arrow/benches/builder.rs
index 21d4c3baaa..16d082bf37 100644
--- a/arrow/benches/builder.rs
+++ b/arrow/benches/builder.rs
@@ -31,6 +31,10 @@ const BATCH_SIZE: usize = 8 << 10;
const NUM_BATCHES: usize = 64;
fn bench_primitive(c: &mut Criterion) {
+ #[expect(
+ clippy::large_stack_arrays,
+ reason = "kept on the stack so the benchmark measures what it always
has"
+ )]
let data: [i64; BATCH_SIZE] = [100; BATCH_SIZE];
let mut group = c.benchmark_group("bench_primitive");
diff --git a/arrow/benches/cast_kernels.rs b/arrow/benches/cast_kernels.rs
index 30c6b86137..9ffcde2643 100644
--- a/arrow/benches/cast_kernels.rs
+++ b/arrow/benches/cast_kernels.rs
@@ -135,7 +135,7 @@ fn build_string_float_array(size: usize, null_density: f32)
-> ArrayRef {
builder.append_null()
} else {
builder.append_value(
- rng.random_range(-999_999_999f32..999_999_999f32)
+ rng.random_range(-1_000_000_000_f32..1_000_000_000_f32)
.to_string(),
)
}
diff --git a/parquet-variant/src/builder/metadata.rs
b/parquet-variant/src/builder/metadata.rs
index 10b34ced03..ea1a6d4694 100644
--- a/parquet-variant/src/builder/metadata.rs
+++ b/parquet-variant/src/builder/metadata.rs
@@ -178,7 +178,7 @@ impl WritableMetadataBuilder {
/// If the number of field names exceeds the maximum allowed value for
`u32`.
fn num_field_names(&self) -> usize {
let n = self.field_names.len();
- assert!(n <= u32::MAX as usize);
+ assert!(u32::try_from(n).is_ok());
n
}
diff --git a/parquet-variant/src/decoder.rs b/parquet-variant/src/decoder.rs
index d75f51e7cb..ea03f2e2a4 100644
--- a/parquet-variant/src/decoder.rs
+++ b/parquet-variant/src/decoder.rs
@@ -446,7 +446,7 @@ mod tests {
test_float,
[0x06, 0x2c, 0x93, 0x4e],
decode_float,
- 1234567890.1234
+ 1_234_568_000.0
);
test_decoder_bounds!(
diff --git a/parquet-variant/tests/variant_interop.rs
b/parquet-variant/tests/variant_interop.rs
index 4c7c10d51a..26efcd0dc9 100644
--- a/parquet-variant/tests/variant_interop.rs
+++ b/parquet-variant/tests/variant_interop.rs
@@ -132,7 +132,7 @@ fn get_primitive_cases() -> Vec<(&'static str,
Variant<'static, 'static>)> {
"primitive_decimal16",
Variant::Decimal16(VariantDecimal16::try_new(1234567891234567890,
2).unwrap()),
),
- ("primitive_float", Variant::Float(1234567890.1234)),
+ ("primitive_float", Variant::Float(1_234_568_000.0)),
("primitive_double", Variant::Double(1234567890.1234)),
("primitive_int8", Variant::Int8(42)),
("primitive_int16", Variant::Int16(1234)),
diff --git a/parquet/src/arrow/mod.rs b/parquet/src/arrow/mod.rs
index b89db361ed..9414337739 100644
--- a/parquet/src/arrow/mod.rs
+++ b/parquet/src/arrow/mod.rs
@@ -410,7 +410,7 @@ impl ProjectionMask {
/// ```
pub fn intersect(&mut self, other: &Self) {
match (self.mask.as_ref(), other.mask.as_ref()) {
- (None, _) => self.mask = other.mask.clone(),
+ (None, _) => self.mask.clone_from(&other.mask),
(_, None) => {}
(Some(a), Some(b)) => {
debug_assert_eq!(a.len(), b.len());
diff --git a/parquet/src/arrow/record_reader/definition_levels.rs
b/parquet/src/arrow/record_reader/definition_levels.rs
index b4182b166e..c48c326980 100644
--- a/parquet/src/arrow/record_reader/definition_levels.rs
+++ b/parquet/src/arrow/record_reader/definition_levels.rs
@@ -172,18 +172,8 @@ pub(crate) fn build_filtered_validity_bitmap(
let mut include_mask: u64 = 0;
let mut value_mask: u64 = 0;
for (i, &d) in chunk.iter().enumerate() {
- let mut include = true;
- if let Some(threshold) = include_threshold
- && d < threshold
- {
- include = false;
- }
- if include
- && let Some((reps, max_rep)) = rep_filter
- && reps[base + i] > max_rep
- {
- include = false;
- }
+ let include = include_threshold.is_none_or(|threshold| threshold
<= d)
+ && rep_filter.is_none_or(|(reps, max_rep)| reps[base + i] <=
max_rep);
include_mask |= (include as u64) << i;
value_mask |= ((d >= value_level) as u64) << i;
}
diff --git a/parquet/src/arrow/record_reader/mod.rs
b/parquet/src/arrow/record_reader/mod.rs
index cdb8084eb4..ba3c525b4a 100644
--- a/parquet/src/arrow/record_reader/mod.rs
+++ b/parquet/src/arrow/record_reader/mod.rs
@@ -835,7 +835,7 @@ mod tests {
let mut record_reader = RecordReader::<Int32Type>::new(desc.clone(),
DEFAULT_BATCH_SIZE);
{
- let values = [100; 5000];
+ let values = vec![100; 5000];
let def_levels = [1i16; 5000];
let mut rep_levels = [1i16; 5000];
for idx in 0..1000 {
diff --git a/parquet/src/column/chunker/cdc.rs
b/parquet/src/column/chunker/cdc.rs
index 2627d8921b..ca59913701 100644
--- a/parquet/src/column/chunker/cdc.rs
+++ b/parquet/src/column/chunker/cdc.rs
@@ -156,7 +156,7 @@ impl ContentDefinedChunker {
));
}
- let avg_chunk_size = (min_chunk_size + max_chunk_size) / 2;
+ let avg_chunk_size = min_chunk_size.midpoint(max_chunk_size);
// Target size after subtracting the min-size skip window and dividing
by the
// number of hash tables (for central-limit-theorem normalization).
let target_size = (avg_chunk_size - min_chunk_size) /
NUM_GEARHASH_TABLES as i64;
@@ -742,6 +742,7 @@ mod tests {
#[cfg(all(test, feature = "arrow"))]
mod arrow_tests {
use std::borrow::Borrow;
+ use std::cmp::Ordering;
use std::sync::Arc;
use arrow::util::data_gen::create_random_batch;
@@ -1261,22 +1262,24 @@ mod arrow_tests {
for (left, right) in &diffs {
let left_sum: i64 = left.iter().sum();
let right_sum: i64 = right.iter().sum();
- if left_sum == right_sum {
- eq += 1;
- } else if left_sum < right_sum {
- larger += 1;
- assert_eq!(
- left_sum + edit_length,
- right_sum,
- "Larger diff mismatch: {left_sum} + {edit_length} !=
{right_sum}"
- );
- } else {
- smaller += 1;
- assert_eq!(
- left_sum,
- right_sum + edit_length,
- "Smaller diff mismatch: {left_sum} != {right_sum} +
{edit_length}"
- );
+ match left_sum.cmp(&right_sum) {
+ Ordering::Equal => eq += 1,
+ Ordering::Less => {
+ larger += 1;
+ assert_eq!(
+ left_sum + edit_length,
+ right_sum,
+ "Larger diff mismatch: {left_sum} + {edit_length} !=
{right_sum}"
+ );
+ }
+ Ordering::Greater => {
+ smaller += 1;
+ assert_eq!(
+ left_sum,
+ right_sum + edit_length,
+ "Smaller diff mismatch: {left_sum} != {right_sum} +
{edit_length}"
+ );
+ }
}
}
diff --git a/parquet/src/file/metadata/thrift/mod.rs
b/parquet/src/file/metadata/thrift/mod.rs
index bd60de4177..eb5dc9e689 100644
--- a/parquet/src/file/metadata/thrift/mod.rs
+++ b/parquet/src/file/metadata/thrift/mod.rs
@@ -146,43 +146,34 @@ struct SizeStatistics {
);
fn convert_geo_stats(
- stats: Option<GeospatialStatistics>,
-) -> Option<Box<crate::geospatial::statistics::GeospatialStatistics>> {
- stats.map(|st| {
- let bbox = convert_bounding_box(st.bbox);
- let geospatial_types: Option<Vec<i32>> =
st.geospatial_types.filter(|v| !v.is_empty());
- Box::new(crate::geospatial::statistics::GeospatialStatistics::new(
- bbox,
- geospatial_types,
- ))
- })
+ st: GeospatialStatistics,
+) -> crate::geospatial::statistics::GeospatialStatistics {
+ let bbox = st.bbox.map(convert_bounding_box);
+ let geospatial_types: Option<Vec<i32>> = st.geospatial_types.filter(|v|
!v.is_empty());
+ crate::geospatial::statistics::GeospatialStatistics::new(bbox,
geospatial_types)
}
-fn convert_bounding_box(
- bbox: Option<BoundingBox>,
-) -> Option<crate::geospatial::bounding_box::BoundingBox> {
- bbox.map(|bb| {
- let mut newbb = crate::geospatial::bounding_box::BoundingBox::new(
- bb.xmin.into(),
- bb.xmax.into(),
- bb.ymin.into(),
- bb.ymax.into(),
- );
+fn convert_bounding_box(bb: BoundingBox) ->
crate::geospatial::bounding_box::BoundingBox {
+ let mut newbb = crate::geospatial::bounding_box::BoundingBox::new(
+ bb.xmin.into(),
+ bb.xmax.into(),
+ bb.ymin.into(),
+ bb.ymax.into(),
+ );
- newbb = match (bb.zmin, bb.zmax) {
- (Some(zmin), Some(zmax)) => newbb.with_zrange(zmin.into(),
zmax.into()),
- // If either None or mismatch, leave it as None and don't error
- _ => newbb,
- };
+ newbb = match (bb.zmin, bb.zmax) {
+ (Some(zmin), Some(zmax)) => newbb.with_zrange(zmin.into(),
zmax.into()),
+ // If either None or mismatch, leave it as None and don't error
+ _ => newbb,
+ };
- newbb = match (bb.mmin, bb.mmax) {
- (Some(mmin), Some(mmax)) => newbb.with_mrange(mmin.into(),
mmax.into()),
- // If either None or mismatch, leave it as None and don't error
- _ => newbb,
- };
+ newbb = match (bb.mmin, bb.mmax) {
+ (Some(mmin), Some(mmax)) => newbb.with_mrange(mmin.into(),
mmax.into()),
+ // If either None or mismatch, leave it as None and don't error
+ _ => newbb,
+ };
- newbb
- })
+ newbb
}
/// Create a [`crate::file::statistics::Statistics`] from a thrift
[`Statistics`] object.
@@ -236,7 +227,7 @@ fn convert_stats(
stats.max_value
};
- fn check_len(min: &Option<&[u8]>, max: &Option<&[u8]>, len: usize)
-> Result<()> {
+ fn check_len(min: Option<&[u8]>, max: Option<&[u8]>, len: usize)
-> Result<()> {
if let Some(min) = min
&& min.len() < len
{
@@ -252,10 +243,10 @@ fn convert_stats(
let physical_type = column_descr.physical_type();
match physical_type {
- Type::BOOLEAN => check_len(&min, &max, 1),
- Type::INT32 | Type::FLOAT => check_len(&min, &max, 4),
- Type::INT64 | Type::DOUBLE => check_len(&min, &max, 8),
- Type::INT96 => check_len(&min, &max, 12),
+ Type::BOOLEAN => check_len(min, max, 1),
+ Type::INT32 | Type::FLOAT => check_len(min, max, 4),
+ Type::INT64 | Type::DOUBLE => check_len(min, max, 8),
+ Type::INT96 => check_len(min, max, 12),
_ => Ok(()),
}?;
@@ -427,6 +418,7 @@ fn read_encoding_stats_as_mask<'a>(
// Decode `ColumnMetaData`. Returns a mask of all required fields that were
observed.
// This mask can be passed to `validate_column_metadata`.
+#[expect(clippy::useless_let_if_seq)] // the `let mut … if let …` below is
more readable than the suggestion
fn read_column_metadata<'a>(
prot: &mut ThriftSliceInputProtocol<'a>,
column: &mut ColumnChunkMetaData,
@@ -544,7 +536,7 @@ fn read_column_metadata<'a>(
}
17 => {
let val = GeospatialStatistics::read_thrift(&mut *prot)?;
- column.geo_statistics = convert_geo_stats(Some(val));
+ column.geo_statistics = Some(Box::new(convert_geo_stats(val)));
}
_ => {
prot.skip(field_ident.field_type)?;
@@ -781,13 +773,10 @@ pub(crate) fn parquet_metadata_from_bytes(
#[cfg(feature = "encryption")]
let mut footer_signing_key_metadata: Option<&[u8]> = None;
- // this will need to be set before parsing row groups
- let mut schema_descr: Option<Arc<SchemaDescriptor>> = None;
-
+ // this will need to be set before parsing row groups.
// see if we already have a schema.
- if let Some(options) = options {
- schema_descr = options.schema().cloned();
- }
+ let mut schema_descr: Option<Arc<SchemaDescriptor>> =
+ options.and_then(|options| options.schema().cloned());
// struct FileMetaData {
// 1: required i32 version
@@ -1459,7 +1448,7 @@ impl<'a> WriteThrift for FileMeta<'a> {
fn write_thrift<W: Write>(&self, writer: &mut
ThriftCompactOutputProtocol<W>) -> Result<()> {
writer.set_write_path_in_schema(self.write_path_in_schema);
// only write ordinal if all values will fit in an i16
- writer.set_write_row_group_ordinal(self.row_groups.len() <= i16::MAX
as usize);
+
writer.set_write_row_group_ordinal(i16::try_from(self.row_groups.len()).is_ok());
self.file_metadata
.version
diff --git a/parquet/src/file/page_index/column_index.rs
b/parquet/src/file/page_index/column_index.rs
index 4b766cc972..665b4bc454 100644
--- a/parquet/src/file/page_index/column_index.rs
+++ b/parquet/src/file/page_index/column_index.rs
@@ -405,9 +405,9 @@ impl ByteArrayColumnIndex {
null_pages,
boundary_order,
null_counts,
- nan_counts,
repetition_level_histograms,
definition_level_histograms,
+ nan_counts,
},
min_bytes,
min_offsets,
diff --git a/parquet/src/file/serialized_reader.rs
b/parquet/src/file/serialized_reader.rs
index 7c9b33132e..b52aac367b 100644
--- a/parquet/src/file/serialized_reader.rs
+++ b/parquet/src/file/serialized_reader.rs
@@ -411,31 +411,34 @@ pub(crate) fn decode_page(
//
// We always use 0 offset for other pages other than v2, `true` flag means
// that compression will be applied if decompressor is defined
- let mut offset: usize = 0;
- let mut can_decompress = true;
-
- if let Some(ref header_v2) = page_header.data_page_header_v2 {
- if header_v2.definition_levels_byte_length < 0
- || header_v2.repetition_levels_byte_length < 0
- || header_v2.definition_levels_byte_length +
header_v2.repetition_levels_byte_length
- > page_header.uncompressed_page_size
- {
- return Err(general_err!(
- "DataPage v2 header contains implausible values \
- for definition_levels_byte_length ({}) \
- and repetition_levels_byte_length ({}) \
- given DataPage header provides uncompressed_page_size
({})",
- header_v2.definition_levels_byte_length,
- header_v2.repetition_levels_byte_length,
- page_header.uncompressed_page_size
- ));
+ let (offset, can_decompress): (usize, bool) = match
page_header.data_page_header_v2 {
+ Some(ref header_v2) => {
+ if header_v2.definition_levels_byte_length < 0
+ || header_v2.repetition_levels_byte_length < 0
+ || header_v2.definition_levels_byte_length +
header_v2.repetition_levels_byte_length
+ > page_header.uncompressed_page_size
+ {
+ return Err(general_err!(
+ "DataPage v2 header contains implausible values \
+ for definition_levels_byte_length ({}) \
+ and repetition_levels_byte_length ({}) \
+ given DataPage header provides uncompressed_page_size
({})",
+ header_v2.definition_levels_byte_length,
+ header_v2.repetition_levels_byte_length,
+ page_header.uncompressed_page_size
+ ));
+ }
+ (
+ usize::try_from(
+ header_v2.definition_levels_byte_length
+ + header_v2.repetition_levels_byte_length,
+ )?,
+ // When is_compressed flag is missing the page is considered
compressed
+ header_v2.is_compressed.unwrap_or(true),
+ )
}
- offset = usize::try_from(
- header_v2.definition_levels_byte_length +
header_v2.repetition_levels_byte_length,
- )?;
- // When is_compressed flag is missing the page is considered compressed
- can_decompress = header_v2.is_compressed.unwrap_or(true);
- }
+ None => (0, true),
+ };
let buffer = match decompressor {
Some(decompressor) if can_decompress => {
diff --git a/parquet/src/record/reader.rs b/parquet/src/record/reader.rs
index bee49c70d8..f1a262250c 100644
--- a/parquet/src/record/reader.rs
+++ b/parquet/src/record/reader.rs
@@ -785,10 +785,7 @@ impl Iterator for RowIter<'_> {
type Item = Result<Row>;
fn next(&mut self) -> Option<Result<Row>> {
- let mut row = None;
- if let Some(ref mut iter) = self.row_iter {
- row = iter.next();
- }
+ let mut row = self.row_iter.as_mut().and_then(|iter| iter.next());
while row.is_none() && self.current_row_group < self.num_row_groups {
// We do not expect any failures when accessing a row group, and
file reader
diff --git a/parquet_derive_test/src/lib.rs b/parquet_derive_test/src/lib.rs
index c18b1c1c49..106e0b4732 100644
--- a/parquet_derive_test/src/lib.rs
+++ b/parquet_derive_test/src/lib.rs
@@ -28,6 +28,10 @@ use parquet_derive::{ParquetRecordReader,
ParquetRecordWriter};
use std::sync::Arc;
#[derive(ParquetRecordWriter)]
+#[expect(
+ clippy::ref_option_ref,
+ reason = "the point of this struct is to cover every field type the derive
supports, including `&Option<&T>`"
+)]
struct ACompleteRecord<'a> {
pub a_bool: bool,
pub a_str: &'a str,