Skip to content

Commit 06eef29

Browse files
committed
Improve usability of build_ble_stream()
Accept `Cow<a, BleId>` instead of `BleId` as the first parameter of `build_ble_stream()`. This allows passing of all: * BleId and &BleId * BleDevice and &BleDevice
1 parent bd5fe19 commit 06eef29

File tree

3 files changed

+84
-7
lines changed

3 files changed

+84
-7
lines changed

src/connections/ble_handler.rs

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use futures::stream::StreamExt;
77
use futures_util::stream::BoxStream;
88
use log::error;
99
use serde::{Deserialize, Serialize};
10+
use std::borrow::Cow;
1011
use std::fmt::Display;
1112
use std::future;
1213
use std::str::FromStr;
@@ -41,7 +42,7 @@ pub enum RadioMessage {
4142
}
4243

4344
/// Bluetooth Low Energy ID, used to filter available devices.
44-
#[derive(Debug, Clone)]
45+
#[derive(Debug, Clone, PartialEq)]
4546
pub enum BleId {
4647
/// A Meshtastic device identified by its broadcast name.
4748
Name(String),
@@ -72,6 +73,15 @@ impl BleId {
7273
}
7374
}
7475

76+
impl TryFrom<u64> for BleId {
77+
type Error = Error;
78+
79+
fn try_from(value: u64) -> Result<Self, Self::Error> {
80+
let mac_address = BDAddr::try_from(value)?;
81+
Ok(Self::MacAddress(mac_address))
82+
}
83+
}
84+
7585
impl From<BDAddr> for BleId {
7686
fn from(mac: BDAddr) -> Self {
7787
BleId::MacAddress(mac)
@@ -96,6 +106,30 @@ pub struct BleDevice {
96106
pub mac_address: BDAddr,
97107
}
98108

109+
impl<'a> From<BleId> for Cow<'a, BleId> {
110+
fn from(ble_id: BleId) -> Self {
111+
Cow::Owned(ble_id)
112+
}
113+
}
114+
115+
impl<'a> From<&'a BleId> for Cow<'a, BleId> {
116+
fn from(ble_id: &'a BleId) -> Self {
117+
Cow::Borrowed(ble_id)
118+
}
119+
}
120+
121+
impl<'a> From<&BleDevice> for Cow<'a, BleId> {
122+
fn from(device: &BleDevice) -> Self {
123+
Cow::Owned(device.mac_address.into())
124+
}
125+
}
126+
127+
impl<'a> From<BleDevice> for Cow<'a, BleId> {
128+
fn from(device: BleDevice) -> Self {
129+
Cow::Owned(device.mac_address.into())
130+
}
131+
}
132+
99133
impl BleHandler {
100134
pub async fn new(ble_id: &BleId, scan_duration: Duration) -> Result<Self, Error> {
101135
let (radio, adapter) = Self::find_ble_radio(ble_id, scan_duration).await?;
@@ -350,3 +384,37 @@ impl BleHandler {
350384
})))
351385
}
352386
}
387+
388+
#[cfg(test)]
389+
mod tests {
390+
use super::*;
391+
392+
#[test]
393+
fn test_ble_id_to_cow() {
394+
let ble_id_name = BleId::from_name("TestDevice");
395+
let cow_from_ref: Cow<'_, BleId> = (&ble_id_name).into();
396+
assert_eq!(*cow_from_ref, ble_id_name);
397+
398+
let cow_from_owned: Cow<'_, BleId> = ble_id_name.into();
399+
assert!(matches!(cow_from_owned, Cow::Owned(_)));
400+
401+
let ble_id_mac = BleId::try_from(0x001122334455).unwrap();
402+
let cow_from_owned_mac: Cow<'_, BleId> = ble_id_mac.clone().into();
403+
assert_eq!(*cow_from_owned_mac, ble_id_mac);
404+
}
405+
406+
#[test]
407+
fn test_ble_device_to_cow() {
408+
let ble_device = BleDevice {
409+
name: None,
410+
mac_address: BDAddr::try_from(0x001122334455).unwrap(),
411+
};
412+
413+
let cow_from_ble_device_ref: Cow<'_, BleId> = (&ble_device).into();
414+
let ble_id_mac = BleId::try_from(0x001122334455).unwrap();
415+
assert_eq!(*cow_from_ble_device_ref, ble_id_mac);
416+
417+
let cow_from_ble_device_owned: Cow<'_, BleId> = ble_device.into();
418+
assert_eq!(*cow_from_ble_device_owned, ble_id_mac);
419+
}
420+
}

src/errors_internal.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ pub enum Error {
7070
/// An error indicating that the library failed when performing an operation on an internal data channel.
7171
#[error(transparent)]
7272
InternalChannelError(#[from] InternalChannelError),
73+
74+
/// An error indicating MAC address parse error
75+
#[cfg(feature = "bluetooth-le")]
76+
#[error(transparent)]
77+
MacAddressParseError(#[from] btleplug::api::ParseBDAddrError),
7378
}
7479

7580
/// An enum that defines the possible internal errors that can occur within the library when handling streams.

src/utils_internal.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ pub async fn build_tcp_stream(
223223
///
224224
/// let ble_devices = utils::available_ble_devices(Duration::from_secs(5)).await?;
225225
/// if let Some(device) = ble_devices.first() {
226-
/// let stream = utils::build_ble_stream(&device.mac_address.into(), Duration::from_secs(10)).await;
226+
/// let stream = utils::build_ble_stream(device, Duration::from_secs(10)).await;
227227
/// ...
228228
/// }
229229
/// ```
@@ -258,7 +258,7 @@ pub async fn available_ble_devices(scan_duration: Duration) -> Result<Vec<BleDev
258258
/// ```
259259
/// // Connect to a radio, identified by its MAC address
260260
/// let duplex_stream = utils::build_ble_stream(
261-
/// &BleId::from_mac_address("E3:44:4E:18:F7:A4").unwrap(),
261+
/// BleId::from_mac_address("E3:44:4E:18:F7:A4").unwrap(),
262262
/// Duration::from_secs(5),
263263
/// )
264264
/// .await?;
@@ -275,15 +275,19 @@ pub async fn available_ble_devices(scan_duration: Duration) -> Result<Vec<BleDev
275275
/// None
276276
///
277277
#[cfg(feature = "bluetooth-le")]
278-
pub async fn build_ble_stream(
279-
ble_id: &crate::connections::ble_handler::BleId,
278+
pub async fn build_ble_stream<'a, B>(
279+
device: B,
280280
scan_duration: Duration,
281-
) -> Result<StreamHandle<DuplexStream>, Error> {
281+
) -> Result<StreamHandle<DuplexStream>, Error>
282+
where
283+
B: Into<std::borrow::Cow<'a, crate::connections::ble_handler::BleId>>,
284+
{
282285
use crate::{
283286
connections::ble_handler::{AdapterEvent, RadioMessage},
284287
errors_internal::InternalStreamError,
285288
};
286-
let ble_handler = BleHandler::new(ble_id, scan_duration).await?;
289+
let ble_id: std::borrow::Cow<_> = device.into();
290+
let ble_handler = BleHandler::new(&ble_id, scan_duration).await?;
287291
// `client` will be returned to the user, server is the opposite end of the channel and it's
288292
// directly connected to a `BleHandler`.
289293
let (client, mut server) = tokio::io::duplex(1024);

0 commit comments

Comments
 (0)