From 44edf79e7f629b5c91629c6a62bcc9abe6cfffd4 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Fri, 29 Mar 2024 13:47:48 +0100 Subject: [PATCH 1/5] Update to bt-hci main and adopt to new api --- examples/nrf-sdc/Cargo.toml | 6 +++--- examples/serial-hci/Cargo.toml | 2 +- examples/serial-hci/src/main.rs | 8 ++++---- host/Cargo.toml | 2 +- host/src/adapter.rs | 5 +++-- host/src/channel_manager.rs | 2 +- host/src/gatt.rs | 2 +- host/src/l2cap.rs | 2 +- host/src/lib.rs | 8 ++++---- 9 files changed, 19 insertions(+), 18 deletions(-) diff --git a/examples/nrf-sdc/Cargo.toml b/examples/nrf-sdc/Cargo.toml index b2fb29d9..bd03fc0c 100644 --- a/examples/nrf-sdc/Cargo.toml +++ b/examples/nrf-sdc/Cargo.toml @@ -37,9 +37,9 @@ embassy-futures = { git = "https://github.com/embassy-rs/embassy.git", branch = embassy-time = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" } embassy-time-driver = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" } embassy-embedded-hal = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" } -nrf-sdc = { git = "https://github.com/alexmoon/nrf-sdc.git", branch = "update-api" } -nrf-mpsl = { git = "https://github.com/alexmoon/nrf-sdc.git", branch = "update-api" } -bt-hci = { git = "https://github.com/alexmoon/bt-hci.git", branch = "serial-controller" } +nrf-sdc = { git = "https://github.com/alexmoon/nrf-sdc.git", branch = "main" } +nrf-mpsl = { git = "https://github.com/alexmoon/nrf-sdc.git", branch = "main" } +bt-hci = { git = "https://github.com/alexmoon/bt-hci.git", branch = "main" } #embassy-executor = {path = "../../../embassy/embassy-executor"} #embassy-nrf = {path = "../../../embassy/embassy-nrf"} diff --git a/examples/serial-hci/Cargo.toml b/examples/serial-hci/Cargo.toml index a801a574..769ceb95 100644 --- a/examples/serial-hci/Cargo.toml +++ b/examples/serial-hci/Cargo.toml @@ -24,7 +24,7 @@ bt-hci = { version = "0.1.0", default-features = false, features = ["log"] } trouble-host = { version = "0.1.0", path = "../../host", features = ["log"] } [patch.crates-io] -bt-hci = { git = "https://github.com/alexmoon/bt-hci.git", branch = "serial-controller" } +bt-hci = { git = "https://github.com/alexmoon/bt-hci.git", branch = "main" } embassy-sync = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" } #embassy-executor = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" } #bt-hci = { path = "../../../bt-hci" } diff --git a/examples/serial-hci/src/main.rs b/examples/serial-hci/src/main.rs index f6867515..b111af43 100644 --- a/examples/serial-hci/src/main.rs +++ b/examples/serial-hci/src/main.rs @@ -1,6 +1,6 @@ // Use with any serial HCI -use bt_hci::driver::HciController; -use bt_hci::serial::SerialHciDriver; +use bt_hci::controller::ExternalController; +use bt_hci::transport::SerialTransport; use embassy_futures::join::join3; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use log::*; @@ -56,8 +56,8 @@ async fn main() { let reader = embedded_io_adapters::tokio_1::FromTokio::new(reader); let writer = embedded_io_adapters::tokio_1::FromTokio::new(writer); - let driver: SerialHciDriver = SerialHciDriver::new(reader, writer); - let controller: HciController<_, 10> = HciController::new(driver); + let driver: SerialTransport = SerialTransport::new(reader, writer); + let controller: ExternalController<_, 10> = ExternalController::new(driver); static HOST_RESOURCES: StaticCell> = StaticCell::new(); let host_resources = HOST_RESOURCES.init(HostResources::new(PacketQos::None)); diff --git a/host/Cargo.toml b/host/Cargo.toml index ff7c7a73..b04154b0 100644 --- a/host/Cargo.toml +++ b/host/Cargo.toml @@ -33,5 +33,5 @@ defmt = {version = "0.3", optional = true } defmt = [ "dep:defmt" ] [patch.crates-io] -bt-hci = { git = "https://github.com/alexmoon/bt-hci.git", branch = "serial-controller" } +bt-hci = { git = "https://github.com/alexmoon/bt-hci.git", branch = "main" } embassy-sync = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" } diff --git a/host/src/adapter.rs b/host/src/adapter.rs index b839ed50..3b81bf8a 100644 --- a/host/src/adapter.rs +++ b/host/src/adapter.rs @@ -19,12 +19,13 @@ use bt_hci::cmd::le::{ }; use bt_hci::cmd::link_control::{Disconnect, DisconnectParams}; use bt_hci::cmd::{AsyncCmd, SyncCmd}; +use bt_hci::controller::Controller; +use bt_hci::controller::{ControllerCmdAsync, ControllerCmdSync}; use bt_hci::data::{AclBroadcastFlag, AclPacket, AclPacketBoundary}; use bt_hci::event::le::LeEvent; use bt_hci::event::Event; use bt_hci::param::{BdAddr, ConnHandle, DisconnectReason, EventMask}; -use bt_hci::{Controller, ControllerToHostPacket}; -use bt_hci::{ControllerCmdAsync, ControllerCmdSync}; +use bt_hci::ControllerToHostPacket; use embassy_futures::select::{select, Either}; use embassy_sync::blocking_mutex::raw::RawMutex; use embassy_sync::channel::Channel; diff --git a/host/src/channel_manager.rs b/host/src/channel_manager.rs index 1d2e2471..161a83ea 100644 --- a/host/src/channel_manager.rs +++ b/host/src/channel_manager.rs @@ -4,7 +4,7 @@ use core::{ task::{Context, Poll}, }; -use bt_hci::{param::ConnHandle, Controller}; +use bt_hci::{controller::Controller, param::ConnHandle}; use embassy_sync::{ blocking_mutex::{raw::RawMutex, Mutex}, channel::{Channel, DynamicReceiver}, diff --git a/host/src/gatt.rs b/host/src/gatt.rs index cbdabce4..7f8d0769 100644 --- a/host/src/gatt.rs +++ b/host/src/gatt.rs @@ -10,8 +10,8 @@ use crate::cursor::WriteCursor; use crate::packet_pool::{AllocId, DynamicPacketPool}; use crate::pdu::Pdu; use crate::{AdapterError, Error}; +use bt_hci::controller::Controller; use bt_hci::param::ConnHandle; -use bt_hci::Controller; use embassy_sync::blocking_mutex::raw::RawMutex; use embassy_sync::channel::DynamicReceiver; diff --git a/host/src/l2cap.rs b/host/src/l2cap.rs index 36e6aad2..db1c9ed2 100644 --- a/host/src/l2cap.rs +++ b/host/src/l2cap.rs @@ -8,9 +8,9 @@ use crate::cursor::{ReadCursor, WriteCursor}; use crate::packet_pool::{AllocId, DynamicPacketPool}; use crate::pdu::Pdu; use crate::{AdapterError, Error}; +use bt_hci::controller::Controller; use bt_hci::data::AclPacket; use bt_hci::param::ConnHandle; -use bt_hci::Controller; use embassy_sync::blocking_mutex::raw::RawMutex; use embassy_sync::channel::DynamicReceiver; diff --git a/host/src/lib.rs b/host/src/lib.rs index 62ac68cc..ddb75bda 100644 --- a/host/src/lib.rs +++ b/host/src/lib.rs @@ -65,11 +65,11 @@ impl From for Error { } } -impl From> for AdapterError { - fn from(error: bt_hci::CmdError) -> Self { +impl From> for AdapterError { + fn from(error: bt_hci::controller::CmdError) -> Self { match error { - bt_hci::CmdError::Param(p) => Self::Adapter(Error::HciEncode(p)), - bt_hci::CmdError::Controller(p) => Self::Controller(p), + bt_hci::controller::CmdError::Hci(p) => Self::Adapter(Error::HciEncode(p)), + bt_hci::controller::CmdError::Io(p) => Self::Controller(p), } } } From 0f686ced7f92b240deb92083859b8dccee3e5477 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Fri, 29 Mar 2024 13:54:01 +0100 Subject: [PATCH 2/5] cleanup --- host/src/attribute.rs | 10 ++++++++-- host/src/attribute_server.rs | 6 +++--- host/src/channel_manager.rs | 8 ++++---- host/src/connection_manager.rs | 8 ++++---- host/src/gatt.rs | 6 +++--- host/src/l2cap.rs | 8 ++++---- host/src/packet_pool.rs | 4 ++-- host/src/types/l2cap.rs | 4 ++-- 8 files changed, 30 insertions(+), 24 deletions(-) diff --git a/host/src/attribute.rs b/host/src/attribute.rs index a65efe51..d81337f1 100644 --- a/host/src/attribute.rs +++ b/host/src/attribute.rs @@ -157,7 +157,7 @@ impl<'d> AttributeData<'d> { } else if offset == 1 { w.write(*handle)?; } else if offset == 2 { - w.write(handle.to_le_bytes()[1] as u8)?; + w.write(handle.to_le_bytes()[1])?; } let to_write = w.available().min(val.len()); @@ -257,6 +257,12 @@ impl<'d, const MAX: usize> InnerTable<'d, MAX> { } } +impl<'d, M: RawMutex, const MAX: usize> Default for AttributeTable<'d, M, MAX> { + fn default() -> Self { + Self::new() + } +} + impl<'d, M: RawMutex, const MAX: usize> AttributeTable<'d, M, MAX> { pub fn new() -> Self { Self { @@ -374,7 +380,7 @@ impl<'r, 'd, M: RawMutex, const MAX: usize> ServiceBuilder<'r, 'd, M, MAX> { handle: 0, last_handle_in_group: 0, data: AttributeData::Declaration { - props: props, + props, handle: next, uuid, }, diff --git a/host/src/attribute_server.rs b/host/src/attribute_server.rs index f126376c..ef034935 100644 --- a/host/src/attribute_server.rs +++ b/host/src/attribute_server.rs @@ -245,7 +245,7 @@ impl<'c, 'd, M: RawMutex, const MAX: usize> AttributeServer<'c, 'd, M, MAX> { if att.handle == handle { if att.data.writable() { err = att.data.write(0, data); - if let Ok(_) = &err { + if err.is_ok() { if let AttributeData::Cccd { notifications, indications, @@ -326,8 +326,8 @@ impl<'c, 'd, M: RawMutex, const MAX: usize> AttributeServer<'c, 'd, M, MAX> { } } - fn error_response<'m>( - mut w: WriteCursor<'m>, + fn error_response( + mut w: WriteCursor<'_>, opcode: u8, handle: u16, code: AttErrorCode, diff --git a/host/src/channel_manager.rs b/host/src/channel_manager.rs index 161a83ea..d5abb2bf 100644 --- a/host/src/channel_manager.rs +++ b/host/src/channel_manager.rs @@ -393,7 +393,7 @@ impl<'d, M: RawMutex, const CHANNELS: usize, const L2CAP_TXQ: usize, const L2CAP _ => {} } } - return Err(Error::NotFound); + Err(Error::NotFound) })?; Ok((conn, signal)) } @@ -410,7 +410,7 @@ impl<'d, M: RawMutex, const CHANNELS: usize, const L2CAP_TXQ: usize, const L2CAP _ => {} } } - return Err(Error::NotFound); + Err(Error::NotFound) }) } @@ -421,7 +421,7 @@ impl<'d, M: RawMutex, const CHANNELS: usize, const L2CAP_TXQ: usize, const L2CAP match storage { ChannelState::Connected(s) if cid == s.cid => { if credits <= s.peer_credits as usize { - s.peer_credits = s.peer_credits - credits as u16; + s.peer_credits -= credits as u16; return Poll::Ready(Ok(())); } else { state.credit_wakers[idx].register(cx.waker()); @@ -431,7 +431,7 @@ impl<'d, M: RawMutex, const CHANNELS: usize, const L2CAP_TXQ: usize, const L2CAP _ => {} } } - return Poll::Ready(Err(Error::NotFound)); + Poll::Ready(Err(Error::NotFound)) }) } } diff --git a/host/src/connection_manager.rs b/host/src/connection_manager.rs index f0e9c37e..a7799c88 100644 --- a/host/src/connection_manager.rs +++ b/host/src/connection_manager.rs @@ -75,13 +75,13 @@ impl ConnectionManager { ConnectionState::Connecting(handle, info) => { if let Some(peer) = peer { if info.peer_address == peer { - let handle = handle.clone(); - *storage = ConnectionState::Connected(handle.clone(), info.clone()); + let handle = *handle; + *storage = ConnectionState::Connected(handle, *info); return Poll::Ready(handle); } } else { - let handle = handle.clone(); - *storage = ConnectionState::Connected(handle.clone(), info.clone()); + let handle = *handle; + *storage = ConnectionState::Connected(handle, *info); return Poll::Ready(handle); } } diff --git a/host/src/gatt.rs b/host/src/gatt.rs index 7f8d0769..69a08d64 100644 --- a/host/src/gatt.rs +++ b/host/src/gatt.rs @@ -45,7 +45,7 @@ impl<'reference, 'values, 'resources, M: RawMutex, T: Controller, const MAX: usi data.write(mtu)?; header.write(data.len() as u16)?; - header.write(4 as u16)?; + header.write(4_u16)?; let len = header.len() + data.len(); drop(header); drop(data); @@ -58,7 +58,7 @@ impl<'reference, 'values, 'resources, M: RawMutex, T: Controller, const MAX: usi data.commit(written)?; data.truncate(mtu as usize); header.write(written as u16)?; - header.write(4 as u16)?; + header.write(4_u16)?; let len = header.len() + data.len(); drop(header); drop(data); @@ -112,7 +112,7 @@ impl<'reference, 'values, 'resources, M: RawMutex, T: Controller, const MAX: usi data.append(value)?; header.write(data.len() as u16)?; - header.write(4 as u16)?; + header.write(4_u16)?; let total = header.len() + data.len(); drop(header); drop(data); diff --git a/host/src/l2cap.rs b/host/src/l2cap.rs index db1c9ed2..bc9976b3 100644 --- a/host/src/l2cap.rs +++ b/host/src/l2cap.rs @@ -41,7 +41,7 @@ impl<'d> L2capPacket<'d> { let mut w = WriteCursor::new(dest); w.write(self.payload.len() as u16)?; w.write(self.channel)?; - w.append(&self.payload[..])?; + w.append(self.payload)?; Ok(w.len()) } } @@ -78,7 +78,7 @@ impl<'a, 'd, T: Controller, const MTU: usize> L2capChannel<'a, 'd, T, MTU> { let len = { let mut w = WriteCursor::new(packet.as_mut()); w.write(2 + first.len() as u16)?; - w.write(self.peer_cid as u16)?; + w.write(self.peer_cid)?; let len = buf.len() as u16; w.write(len)?; w.append(first)?; @@ -97,7 +97,7 @@ impl<'a, 'd, T: Controller, const MTU: usize> L2capChannel<'a, 'd, T, MTU> { let len = { let mut w = WriteCursor::new(packet.as_mut()); w.write(chunk.len() as u16)?; - w.write(self.peer_cid as u16)?; + w.write(self.peer_cid)?; w.append(chunk)?; w.len() }; @@ -124,7 +124,7 @@ impl<'a, 'd, T: Controller, const MTU: usize> L2capChannel<'a, 'd, T, MTU> { pub async fn receive(&mut self, buf: &mut [u8]) -> Result> { let mut n_received = 1; let packet = self.receive_pdu().await?; - let mut r = ReadCursor::new(&packet.as_ref()); + let mut r = ReadCursor::new(packet.as_ref()); let remaining: u16 = r.read()?; let data = r.remaining(); diff --git a/host/src/packet_pool.rs b/host/src/packet_pool.rs index 1c3c9717..a7457c69 100644 --- a/host/src/packet_pool.rs +++ b/host/src/packet_pool.rs @@ -137,11 +137,11 @@ impl Packet return None; } - return state.alloc(id).map(|p_ref| Packet { + state.alloc(id).map(|p_ref| Packet { client: id, p_ref: Some(p_ref), pool: self, - }); + }) }) } diff --git a/host/src/types/l2cap.rs b/host/src/types/l2cap.rs index 9c76d5d3..3bb58237 100644 --- a/host/src/types/l2cap.rs +++ b/host/src/types/l2cap.rs @@ -72,7 +72,7 @@ impl Encode for SignalCode { impl Decode for SignalCode { fn decode(src: &[u8]) -> Result { - Ok(src[0].try_into()?) + src[0].try_into() } } @@ -276,7 +276,7 @@ impl Encode for LeCreditConnResultCode { impl Decode for LeCreditConnResultCode { fn decode(src: &[u8]) -> Result { - Ok(u16::from_le_bytes([src[0], src[1]]).try_into()?) + u16::from_le_bytes([src[0], src[1]]).try_into() } } From 8e6d48d653199b759fa03bbd3e782fbec9b336c5 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Fri, 29 Mar 2024 13:59:42 +0100 Subject: [PATCH 3/5] clippy fixes --- host/src/adapter.rs | 1 - host/src/connection_manager.rs | 28 +++++++++++----------------- host/src/gatt.rs | 9 --------- host/src/types/uuid.rs | 2 +- 4 files changed, 12 insertions(+), 28 deletions(-) diff --git a/host/src/adapter.rs b/host/src/adapter.rs index 3b81bf8a..ba6dbd2a 100644 --- a/host/src/adapter.rs +++ b/host/src/adapter.rs @@ -151,7 +151,6 @@ where item.encode(&mut w)?; } let len = w.len(); - drop(w); LeSetAdvData::new(len as u8, data).exec(&self.controller).await?; LeSetAdvEnable::new(true).exec(&self.controller).await?; let conn = Connection::accept(self).await; diff --git a/host/src/connection_manager.rs b/host/src/connection_manager.rs index a7799c88..05bbc049 100644 --- a/host/src/connection_manager.rs +++ b/host/src/connection_manager.rs @@ -54,13 +54,10 @@ impl ConnectionManager { self.state.lock(|state| { let mut state = state.borrow_mut(); for storage in state.connections.iter_mut() { - match storage { - ConnectionState::Disconnected => { - *storage = ConnectionState::Connecting(handle, info); - state.waker.wake(); - return Ok(()); - } - _ => {} + if let ConnectionState::Disconnected = storage { + *storage = ConnectionState::Connecting(handle, info); + state.waker.wake(); + return Ok(()); } } Err(Error::NotFound) @@ -71,21 +68,18 @@ impl ConnectionManager { self.state.lock(|state| { let mut state = state.borrow_mut(); for storage in state.connections.iter_mut() { - match storage { - ConnectionState::Connecting(handle, info) => { - if let Some(peer) = peer { - if info.peer_address == peer { - let handle = *handle; - *storage = ConnectionState::Connected(handle, *info); - return Poll::Ready(handle); - } - } else { + if let ConnectionState::Connecting(handle, info) = storage { + if let Some(peer) = peer { + if info.peer_address == peer { let handle = *handle; *storage = ConnectionState::Connected(handle, *info); return Poll::Ready(handle); } + } else { + let handle = *handle; + *storage = ConnectionState::Connected(handle, *info); + return Poll::Ready(handle); } - _ => {} } } state.waker.register(cx.waker()); diff --git a/host/src/gatt.rs b/host/src/gatt.rs index 69a08d64..33e9799a 100644 --- a/host/src/gatt.rs +++ b/host/src/gatt.rs @@ -47,9 +47,6 @@ impl<'reference, 'values, 'resources, M: RawMutex, T: Controller, const MAX: usi header.write(data.len() as u16)?; header.write(4_u16)?; let len = header.len() + data.len(); - drop(header); - drop(data); - drop(w); self.tx.send(handle, Pdu::new(response, len).as_ref()).await?; } _ => match self.server.process(handle, att, data.write_buf()) { @@ -60,9 +57,6 @@ impl<'reference, 'values, 'resources, M: RawMutex, T: Controller, const MAX: usi header.write(written as u16)?; header.write(4_u16)?; let len = header.len() + data.len(); - drop(header); - drop(data); - drop(w); self.tx.send(handle, Pdu::new(response, len).as_ref()).await?; } Ok(None) => { @@ -114,9 +108,6 @@ impl<'reference, 'values, 'resources, M: RawMutex, T: Controller, const MAX: usi header.write(data.len() as u16)?; header.write(4_u16)?; let total = header.len() + data.len(); - drop(header); - drop(data); - drop(w); self.tx.send(conn, Pdu::new(packet, total).as_ref()).await?; Ok(()) } diff --git a/host/src/types/uuid.rs b/host/src/types/uuid.rs index 92a21cb9..efc73e53 100644 --- a/host/src/types/uuid.rs +++ b/host/src/types/uuid.rs @@ -30,7 +30,7 @@ impl Uuid { } } - pub fn len(&self) -> usize { + pub fn size(&self) -> usize { match self { Uuid::Uuid16(_) => 6, Uuid::Uuid128(_) => 20, From 50dbbd5f7f7c4290735b79c68e9d29a67389e32c Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Fri, 29 Mar 2024 14:01:42 +0100 Subject: [PATCH 4/5] more clippy fixes --- examples/nrf-sdc/src/bin/ble_l2cap_central.rs | 4 ++-- examples/nrf-sdc/src/bin/ble_l2cap_peripheral.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/nrf-sdc/src/bin/ble_l2cap_central.rs b/examples/nrf-sdc/src/bin/ble_l2cap_central.rs index 18b5f86e..03e93a4c 100644 --- a/examples/nrf-sdc/src/bin/ble_l2cap_central.rs +++ b/examples/nrf-sdc/src/bin/ble_l2cap_central.rs @@ -145,8 +145,8 @@ async fn main(spawner: Spawner) { unwrap!(L2capChannel::create(&adapter, &conn, 0x2349).await); info!("New l2cap channel created, sending some data!"); for i in 0..10 { - let mut tx = [i; PAYLOAD_LEN]; - let _ = unwrap!(ch1.send(&mut tx).await); + let tx = [i; PAYLOAD_LEN]; + unwrap!(ch1.send(&tx).await); } info!("Sent data, waiting for them to be sent back"); let mut rx = [0; PAYLOAD_LEN]; diff --git a/examples/nrf-sdc/src/bin/ble_l2cap_peripheral.rs b/examples/nrf-sdc/src/bin/ble_l2cap_peripheral.rs index ef8a5b43..dceb7bb5 100644 --- a/examples/nrf-sdc/src/bin/ble_l2cap_peripheral.rs +++ b/examples/nrf-sdc/src/bin/ble_l2cap_peripheral.rs @@ -157,8 +157,8 @@ async fn main(spawner: Spawner) { info!("L2CAP data received, echoing"); Timer::after(Duration::from_secs(1)).await; for i in 0..10 { - let mut tx = [i; PAYLOAD_LEN]; - let _ = unwrap!(ch1.send(&mut tx).await); + let tx = [i; PAYLOAD_LEN]; + unwrap!(ch1.send(&tx).await); } info!("L2CAP data echoed"); From d8bf54167b51222043e79cf21db4c7eee09f7916 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Fri, 29 Mar 2024 14:01:48 +0100 Subject: [PATCH 5/5] add fmt and clippy check --- .github/workflows/ci.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 46c46d4e..aaf1f63a 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -18,6 +18,8 @@ jobs: run: | cd host cargo check + cargo fmt --check + cargo clippy - name: Test run: | @@ -25,4 +27,4 @@ jobs: cargo test -- --nocapture - name: Build examples - run: for i in nrf-sdc; do pushd examples/$i; cargo build --release; popd; done; + run: for i in nrf-sdc; do pushd examples/$i; cargo fmt --check && cargo clippy && cargo build --release; popd; done;