1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//! Types related to the expected connection length range.

use byteorder::{ByteOrder, LittleEndian};
use core::time::Duration;

/// Define an expected connection length range
///
/// There is no minimum. The maximum is bounded by what is representable as a u16 at T = N * 0.625
/// ms, so max = 65535 * 0.625 ms = 40.959375 seconds.
#[derive(Clone, Debug)]
pub struct ExpectedConnectionLength {
    range: (Duration, Duration),
}

impl ExpectedConnectionLength {
    /// Creates a new ExpectedConnectionLength, or returns an error if the duration is invalid.
    ///
    /// # Errors
    ///
    /// - [Inverted](ExpectedConnectionLengthError::Inverted) if `min` is greater than `max`
    /// - [TooLong](ExpectedConnectionLengthError::TooLong) if `max` is longer than 40.959375
    ///   seconds.
    pub fn new(
        min: Duration,
        max: Duration,
    ) -> Result<ExpectedConnectionLength, ExpectedConnectionLengthError> {
        if min > max {
            return Err(ExpectedConnectionLengthError::Inverted(min, max));
        }

        const ABSOLUTE_MAX: Duration = Duration::from_micros(40_959_375);
        assert_eq!(Self::as_u16(ABSOLUTE_MAX), 0xFFFF);
        if max > ABSOLUTE_MAX {
            return Err(ExpectedConnectionLengthError::TooLong(max));
        }

        Ok(ExpectedConnectionLength { range: (min, max) })
    }

    /// Serializes the expected connection length range into the given byte buffer.
    ///
    /// # Panics
    ///
    /// The buffer must be at least 4 bytes long.
    pub fn into_bytes(&self, bytes: &mut [u8]) {
        assert!(bytes.len() >= 4);

        LittleEndian::write_u16(&mut bytes[0..2], Self::as_u16(self.range.0));
        LittleEndian::write_u16(&mut bytes[2..4], Self::as_u16(self.range.1));
    }

    fn as_u16(d: Duration) -> u16 {
        // T = 0.625 ms * N
        // so N = T / 0.625 ms
        //      = T / 625 us
        //
        // Note: 1600 = 1_000_000 / 625
        (1600 * d.as_secs() as u32 + (d.subsec_micros() / 625)) as u16
    }
}

/// Types of errors that can occure when creating a [ExpectedConnectionLength].
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum ExpectedConnectionLengthError {
    /// The maximum expected length is too long. The maximum is 40.959375, because nothing higher
    /// can be represented as a u16.
    TooLong(Duration),
    /// The min is greater than the max. Returns the min and max, respectively.
    Inverted(Duration, Duration),
}