cue_sdk/device/channel/
device.rs

1use cue_sdk_sys as ffi;
2use num_traits::FromPrimitive;
3
4/// The types of devices that can be attached to a `Channel`.
5#[derive(Debug, Copy, Clone, PartialEq, FromPrimitive)]
6#[repr(u32)]
7pub enum ChannelDeviceType {
8    HdFan = ffi::CorsairChannelDeviceType_CCDT_HD_Fan,
9    SpFan = ffi::CorsairChannelDeviceType_CCDT_SP_Fan,
10    LlFan = ffi::CorsairChannelDeviceType_CCDT_LL_Fan,
11    MlFan = ffi::CorsairChannelDeviceType_CCDT_ML_Fan,
12    Strip = ffi::CorsairChannelDeviceType_CCDT_Strip,
13    Dap = ffi::CorsairChannelDeviceType_CCDT_DAP,
14    Pump = ffi::CorsairChannelDeviceType_CCDT_Pump,
15    QlFan = ffi::CorsairChannelDeviceType_CCDT_QL_Fan,
16    WaterBlock = ffi::CorsairChannelDeviceType_CCDT_WaterBlock,
17    SpProFan = ffi::CorsairChannelDeviceType_CCDT_SPPRO_Fan,
18}
19
20/// Not to be confused with a `CueDevice` a `ChannelDevice` is attached to a `Channel` which is a
21/// "DIY" style LED channel attached to a proper `CueDevice`.
22#[derive(Debug, Clone, PartialEq)]
23pub struct ChannelDevice {
24    pub device_type: Option<ChannelDeviceType>,
25    pub device_led_count: u32,
26}
27
28/// The various errors that can happen when reading a `ChannelDevice` from the iCUE SDK.
29#[derive(Debug, Clone, Fail, PartialEq)]
30#[fail(display = "Invalid device_led_count: {}", device_led_count)]
31pub struct ChannelDeviceFromFfiError {
32    pub device_led_count: i32,
33}
34
35impl ChannelDevice {
36    pub(crate) fn from_ffi(
37        device_info: &ffi::CorsairChannelDeviceInfo,
38    ) -> Result<Self, ChannelDeviceFromFfiError> {
39        let led_count = device_info.deviceLedCount;
40
41        if led_count < 0 {
42            Err(ChannelDeviceFromFfiError {
43                device_led_count: led_count,
44            })
45        } else {
46            let device_led_count: u32 = led_count as u32;
47            let device_type = ChannelDeviceType::from_u32(device_info.type_);
48
49            Ok(ChannelDevice {
50                device_led_count,
51                device_type,
52            })
53        }
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use cue_sdk_sys as ffi;
60
61    use super::{ChannelDevice, ChannelDeviceFromFfiError, ChannelDeviceType};
62
63    #[test]
64    fn channel_device_from_ffi_invalid_led_count() {
65        let channel_device_info = ffi::CorsairChannelDeviceInfo {
66            type_: ffi::CorsairChannelDeviceType_CCDT_Pump,
67            deviceLedCount: -1,
68        };
69        let result = ChannelDevice::from_ffi(&channel_device_info);
70        assert_eq!(
71            result.unwrap_err(),
72            ChannelDeviceFromFfiError {
73                device_led_count: -1
74            }
75        );
76    }
77
78    #[test]
79    fn channel_device_from_ffi_valid_with_device_type() {
80        let channel_device_info = ffi::CorsairChannelDeviceInfo {
81            type_: ffi::CorsairChannelDeviceType_CCDT_Strip,
82            deviceLedCount: 12,
83        };
84        let result = ChannelDevice::from_ffi(&channel_device_info);
85        assert_eq!(
86            result.unwrap(),
87            ChannelDevice {
88                device_led_count: 12,
89                device_type: Some(ChannelDeviceType::Strip),
90            }
91        );
92    }
93
94    #[test]
95    fn channel_device_from_ffi_valid_with_unknown_device_type() {
96        let channel_device_info = ffi::CorsairChannelDeviceInfo {
97            type_: 509,
98            deviceLedCount: 13,
99        };
100        let result = ChannelDevice::from_ffi(&channel_device_info);
101        assert_eq!(
102            result.unwrap(),
103            ChannelDevice {
104                device_led_count: 13,
105                device_type: None,
106            }
107        );
108    }
109}