1use byteorder::ByteOrder;
4use ctl_error::SysctlError;
5use ctl_info::CtlInfo;
6use ctl_type::CtlType;
7use ctl_value::CtlValue;
8
9use std::f32;
10
11#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
27pub struct Temperature {
28 value: f32, }
30impl Temperature {
31 pub fn kelvin(&self) -> f32 {
32 self.value
33 }
34 pub fn celsius(&self) -> f32 {
35 self.value - 273.15
36 }
37 pub fn fahrenheit(&self) -> f32 {
38 1.8 * self.celsius() + 32.0
39 }
40}
41
42pub fn temperature(info: &CtlInfo, val: &[u8]) -> Result<CtlValue, SysctlError> {
43 let prec: u32 = {
44 match info.fmt.len() {
45 l if l > 2 => match info.fmt[2..3].parse::<u32>() {
46 Ok(x) if x <= 9 => x,
47 _ => 1,
48 },
49 _ => 1,
50 }
51 };
52
53 let base = 10u32.pow(prec) as f32;
54
55 let make_temp = move |f: f32| -> Result<CtlValue, SysctlError> {
56 Ok(CtlValue::Temperature(Temperature { value: f / base }))
57 };
58
59 match info.ctl_type {
60 CtlType::Int => make_temp(byteorder::LittleEndian::read_i32(&val) as f32),
61 CtlType::S64 => make_temp(byteorder::LittleEndian::read_i64(&val) as f32),
62 CtlType::Uint => make_temp(byteorder::LittleEndian::read_u32(&val) as f32),
63 CtlType::Long => make_temp(byteorder::LittleEndian::read_i64(&val) as f32),
64 CtlType::Ulong => make_temp(byteorder::LittleEndian::read_u64(&val) as f32),
65 CtlType::U64 => make_temp(byteorder::LittleEndian::read_u64(&val) as f32),
66 CtlType::U8 => make_temp(val[0] as u8 as f32),
67 CtlType::U16 => make_temp(byteorder::LittleEndian::read_u16(&val) as f32),
68 CtlType::S8 => make_temp(val[0] as i8 as f32),
69 CtlType::S16 => make_temp(byteorder::LittleEndian::read_i16(&val) as f32),
70 CtlType::S32 => make_temp(byteorder::LittleEndian::read_i32(&val) as f32),
71 CtlType::U32 => make_temp(byteorder::LittleEndian::read_u32(&val) as f32),
72 _ => Err(SysctlError::UnknownType),
73 }
74}
75
76#[cfg(all(test, target_os = "freebsd"))]
77mod tests_freebsd {
78 use byteorder::WriteBytesExt;
79
80 #[test]
81 fn ctl_temperature_ik() {
82 let info = crate::CtlInfo {
83 ctl_type: crate::CtlType::Int,
84 fmt: "IK".into(),
85 flags: 0,
86 };
87 let mut val = vec![];
88 val.write_i32::<byteorder::LittleEndian>(3330)
90 .expect("Error parsing value to byte array");
91
92 let t = super::temperature(&info, &val).unwrap();
93 let tt = t.as_temperature().unwrap();
94 assert!(tt.kelvin() - 333.0 < 0.1);
95 assert!(tt.celsius() - 59.85 < 0.1);
96 assert!(tt.fahrenheit() - 139.73 < 0.1);
97 }
98
99 #[test]
100 fn ctl_temperature_ik3() {
101 let info = crate::CtlInfo {
102 ctl_type: crate::CtlType::Int,
103 fmt: "IK3".into(),
104 flags: 0,
105 };
106 let mut val = vec![];
107 val.write_i32::<byteorder::LittleEndian>(333000)
109 .expect("Error parsing value to byte array");
110
111 let t = super::temperature(&info, &val).unwrap();
112 let tt = t.as_temperature().unwrap();
113 assert!(tt.kelvin() - 333.0 < 0.1);
114 }
115}