use byteorder::{ByteOrder, LittleEndian};
use core::time::Duration;
#[derive(Clone, Debug)]
pub struct ScanWindow {
interval_width: Duration,
window_width: Duration,
}
impl ScanWindow {
pub fn interval(&self) -> Duration {
self.interval_width
}
pub fn window(&self) -> Duration {
self.window_width
}
pub fn into_bytes(&self, bytes: &mut [u8]) {
assert!(bytes.len() >= 4);
LittleEndian::write_u16(&mut bytes[0..2], ScanWindow::as_u16(self.interval_width));
LittleEndian::write_u16(&mut bytes[2..4], ScanWindow::as_u16(self.window_width));
}
pub fn start_every(interval: Duration) -> Result<ScanWindowBuilder, ScanWindowError> {
Ok(ScanWindowBuilder {
interval: ScanWindow::validate(interval)?,
})
}
fn validate(d: Duration) -> Result<Duration, ScanWindowError> {
const MIN: Duration = Duration::from_micros(2500);
if d < MIN {
return Err(ScanWindowError::TooShort(d));
}
const MAX: Duration = Duration::from_millis(10240);
if d > MAX {
return Err(ScanWindowError::TooLong(d));
}
Ok(d)
}
fn as_u16(d: Duration) -> u16 {
(1600 * d.as_secs() as u32 + (d.subsec_micros() / 625)) as u16
}
}
pub struct ScanWindowBuilder {
interval: Duration,
}
impl ScanWindowBuilder {
pub fn open_for(&self, window: Duration) -> Result<ScanWindow, ScanWindowError> {
if window > self.interval {
return Err(ScanWindowError::Inverted {
interval: self.interval,
window: window,
});
}
Ok(ScanWindow {
interval_width: self.interval,
window_width: ScanWindow::validate(window)?,
})
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum ScanWindowError {
TooShort(Duration),
TooLong(Duration),
Inverted {
interval: Duration,
window: Duration,
},
}