commit 252537987245126b023dce4bd53009fb5e19fb0e from: witcher date: Sat Feb 25 20:48:22 2023 UTC Clippy: Add lints and fix them commit - e1a93e31476b246bf5441e71ed1898da757959c3 commit + 252537987245126b023dce4bd53009fb5e19fb0e blob - 1a53c1dd8f0a7ceec6928e50052b03960fb4a47c blob + 60ab36366809a795e750e2ccc04f94b17386de4c --- src/main.rs +++ src/main.rs @@ -1,7 +1,57 @@ +#![deny( + clippy::pedantic, + clippy::nursery, + clippy::unwrap_used, + //clippy::expect_used, + clippy::style, + clippy::complexity, + clippy::correctness, + clippy::unseparated_literal_suffix, + clippy::try_err, + clippy::almost_swapped, + clippy::approx_constant, + clippy::arithmetic_side_effects, + clippy::integer_arithmetic, + clippy::complexity, + clippy::correctness, + clippy::perf, + clippy::alloc_instead_of_core, + clippy::as_conversions, + clippy::as_underscore, + clippy::decimal_literal_representation, + clippy::empty_drop, + clippy::empty_structs_with_brackets, + clippy::float_arithmetic, + clippy::float_cmp_const, + clippy::indexing_slicing, + clippy::let_underscore_must_use, + clippy::mem_forget, + clippy::mod_module_files, + clippy::multiple_inherent_impl, + clippy::mutex_atomic, + clippy::panic, + clippy::partial_pub_fields, + clippy::rc_mutex, + clippy::rest_pat_in_fully_bound_structs, + clippy::same_name_method, + clippy::str_to_string, + clippy::string_to_string, + clippy::todo, + clippy::try_err, + clippy::undocumented_unsafe_blocks, + clippy::unimplemented, + clippy::unnecessary_safety_comment, + clippy::unnecessary_safety_doc, + clippy::unnecessary_self_imports, + clippy::unneeded_field_pattern, + clippy::unseparated_literal_suffix, + clippy::use_debug +)] + use std::sync::Mutex; use std::time::{Duration, Instant}; -use ble_esp32c3::gatt::*; +use ble_esp32c3::gatt::{Characteristic, Permissions, Service}; use once_cell::sync::Lazy; @@ -12,23 +62,29 @@ use once_cell::sync::Lazy; // in order to maximise this throughput, at max 512 - 17 = 495 bytes are being sent per command. const BUFFER_LEN: usize = 495; -const SERVICE_UUID: [u8; 16] = 0x061f8f7050293e727e62a46aa61cda68u128.to_le_bytes(); -const BUFFER_READY_UUID: [u8; 16] = 0x78844add576bb4cd3c40f1f3d536a38au128.to_le_bytes(); -const DATA_BUFFER_UUID: [u8; 16] = 0xb57fc8740ebd1d2695ae2d31db630a54u128.to_le_bytes(); -const BUFFER_LEN_UUID: [u8; 16] = 0x3e0fb4716b176bbc63b82b70b6cf54ddu128.to_le_bytes(); +const SERVICE_UUID: [u8; 16] = 0x061f_8f70_5029_3e72_7e62_a46a_a61c_da68_u128.to_le_bytes(); +const BUFFER_READY_UUID: [u8; 16] = 0x7884_4add_576b_b4cd_3c40_f1f3_d536_a38a_u128.to_le_bytes(); +const DATA_BUFFER_UUID: [u8; 16] = 0xb57f_c874_0ebd_1d26_95ae_2d31_db63_0a54_u128.to_le_bytes(); +const BUFFER_LEN_UUID: [u8; 16] = 0x3e0f_b471_6b17_6bbc_63b8_2b70_b6cf_54dd_u128.to_le_bytes(); static STATE: Lazy> = Lazy::new(|| Mutex::new(ThroughputState::new())); // TODO: include possibility to check payload for steadily increasing numbers struct ThroughputState { + /// Time passed since starting the benchmark. time_passed: Instant, + /// Momentary amount of bytes written. write_len: usize, + /// Total amount of bytes written. total_write_len: usize, + /// Sequence number of the next packet. next_seq: u8, + /// Number of packets missed packets_missed: usize, } impl ThroughputState { + /// Create a new [`ThroughputState`]. pub fn new() -> Self { Self { time_passed: Instant::now(), @@ -39,47 +95,63 @@ impl ThroughputState { } } + /// Receive a packet, writing the necessary fields. pub fn recv(&mut self, payload: &[u8]) { self.add_write_len(payload.len()); - if self.next_seq != payload[0] { - self.packets_missed += 1; + if payload.first().is_some() { + self.packets_missed = self.packets_missed.saturating_add(1); + } else { + log::warn!( + "Payload was empty for packet with sequence number {}", + self.next_seq.saturating_sub(1) + ); } self.next_seq = self.next_seq.wrapping_add(1); } + /// Get the passed time since starting the benchmark. pub fn get_time_passed(&self) -> Duration { self.time_passed.elapsed() } + /// Add to the amount of momentary written bytes. pub fn add_write_len(&mut self, len: usize) { - self.write_len += len; - self.total_write_len += len; + self.write_len = self.write_len.saturating_add(len); + self.total_write_len = self.total_write_len.saturating_add(len); } - pub fn get_write_len(&self) -> usize { + /// Get the momentary amount of bytes written. + pub const fn get_write_len(&self) -> usize { self.write_len } - pub fn get_total_write_len(&self) -> usize { + /// Get total amount of bytes written. + pub const fn get_total_write_len(&self) -> usize { self.total_write_len } - pub fn get_packets_missed(&self) -> usize { + /// Get amount of missed packets. + pub const fn get_packets_missed(&self) -> usize { self.packets_missed } + /// Reset the momentary `write_len`. pub fn reset_write_len(&mut self) { self.write_len = 0; } } +// TODO: change interface of `Characteristic::new` of `ble_esp32c3` +#[allow(clippy::needless_pass_by_value)] +/// Function for handling the buffer write which updates the state. fn handle_buffer_write(payload: Vec) { - let mut state = STATE.lock().unwrap(); + let mut state = STATE.lock().expect("lock not to be poisoned"); state.recv(&payload); } +/// Setup the BLE connection. fn setup(ble: &mut ble_esp32c3::Ble) { let mut buf_ready = Characteristic::new( BUFFER_READY_UUID.into(), @@ -95,7 +167,7 @@ fn setup(ble: &mut ble_esp32c3::Ble) { let mut buf_len = Characteristic::new( BUFFER_LEN_UUID.into(), Permissions::ReadWrite, - std::mem::size_of::() as u16, + u16::try_from(std::mem::size_of::()).expect("sizeof usize to fit into u16"), Some(BUFFER_LEN.to_be_bytes().to_vec()), vec![], None, @@ -105,7 +177,7 @@ fn setup(ble: &mut ble_esp32c3::Ble) { let mut buf_data = Characteristic::new( DATA_BUFFER_UUID.into(), Permissions::ReadWrite, - BUFFER_LEN as u16, + u16::try_from(BUFFER_LEN).expect("BUFFER_LEN to fit into u16"), Some(std::iter::repeat(0).take(BUFFER_LEN).collect::>()), vec![], Some(handle_buffer_write), @@ -129,27 +201,33 @@ fn main() { loop { // TODO: can't handle different connections (will reuse previous STATE) - if let Some(state) = once_cell::sync::Lazy::get(&STATE) { - let mut s = state.lock().unwrap(); - let passed = s.get_time_passed().as_secs(); - let total_len = s.get_total_write_len(); - let momentary_len = s.get_write_len(); - let lost = s.get_packets_missed(); - s.reset_write_len(); - drop(s); + once_cell::sync::Lazy::get(&STATE).map_or_else( + || { + log::info!("Not connected"); + }, + |state| { + let mut s = state.lock().expect("Non-poisoned lock"); + let passed = s.get_time_passed().as_secs(); + let total_len = s.get_total_write_len(); + let momentary_len = s.get_write_len(); + let lost = s.get_packets_missed(); + s.reset_write_len(); + drop(s); - if passed > 0 { - log::info!( + if passed > 0 { + log::info!( "Throughput: {} kbit/s ({} kbit/s momentary) (running {}s, {} packets lost)", - (total_len * 8) / 1000 / passed as usize, - (momentary_len * 8) / 1000, + total_len + .saturating_mul(8) + .saturating_div(1000) + .saturating_div(passed.try_into().expect("Convert u64 to usize")), + momentary_len.saturating_mul(8).saturating_div(1000), passed, lost ); - } - } else { - log::info!("Not connected"); - } + } + }, + ); std::thread::sleep(std::time::Duration::from_millis(1000)); }