use core::fmt;
use crate::constants::EMC230X_ADDRESSES;
use crate::error::Error;
#[derive(Copy, Clone, Debug, Default)]
pub struct ProbeResult(pub(crate) [bool; 6]);
impl ProbeResult {
pub fn iter(&self) -> impl Iterator<Item = u8> + '_ {
EMC230X_ADDRESSES
.iter()
.zip(self.0.iter())
.filter_map(|(&addr, &found)| found.then_some(addr))
}
pub fn is_empty(&self) -> bool {
self.0.iter().all(|&x| !x)
}
pub fn len(&self) -> usize {
self.0.iter().filter(|&&x| x).count()
}
pub fn contains(&self, address: u8) -> Result<bool, Error> {
let index = EMC230X_ADDRESSES
.iter()
.position(|&a| a == address)
.ok_or(Error::InvalidI2cAddress)?;
Ok(self.0[index])
}
}
impl fmt::Display for ProbeResult {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"0x2C: {}; 0x2D: {}; 0x2E: {}; 0x2F: {}; 0x4C: {}; 0x4D: {}",
self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5]
)
}
}
#[cfg(feature = "defmt")]
impl defmt::Format for ProbeResult {
fn format(&self, f: defmt::Formatter) {
defmt::write!(
f,
"0x2C: {}; 0x2D: {}; 0x2E: {}; 0x2F: {}; 0x4C: {}; 0x4D: {}",
self.0[0],
self.0[1],
self.0[2],
self.0[3],
self.0[4],
self.0[5]
)
}
}
impl IntoIterator for ProbeResult {
type Item = u8;
type IntoIter = core::iter::FilterMap<
core::iter::Zip<core::array::IntoIter<u8, 6>, core::array::IntoIter<bool, 6>>,
fn((u8, bool)) -> Option<u8>,
>;
fn into_iter(self) -> Self::IntoIter {
EMC230X_ADDRESSES
.into_iter()
.zip(self.0)
.filter_map((|(addr, found)| found.then_some(addr)) as fn((u8, bool)) -> Option<u8>)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::*;
#[test]
fn contains_found_address() {
let result = ProbeResult([false, false, false, true, false, false]);
assert!(result.contains(EMC230X_I2C_ADDR_3).unwrap());
}
#[test]
fn contains_not_found_address() {
let result = ProbeResult([false, false, false, true, false, false]);
assert!(!result.contains(EMC230X_I2C_ADDR_0).unwrap());
}
#[test]
fn contains_invalid_address() {
let result = ProbeResult::default();
assert!(result.contains(0xFF).is_err());
}
}