Skip to main content

scopinator_types/
focuser.rs

1use serde::{Deserialize, Serialize};
2
3/// Focuser position and state.
4#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
5pub struct FocuserPosition {
6    pub position: i32,
7    pub max_position: i32,
8    pub temperature: Option<f64>,
9    pub is_moving: bool,
10}
11
12#[cfg(test)]
13mod tests {
14    use super::*;
15    use proptest::prelude::*;
16
17    // Temperatures with 0.01°C precision: always exactly representable as f64
18    // and roundtrip cleanly through serde_json's Ryu/parser combination.
19    fn temperatures() -> impl Strategy<Value = Option<f64>> {
20        proptest::option::of((-50_000i32..50_000).prop_map(|x| f64::from(x) / 100.0))
21    }
22
23    proptest! {
24        #[test]
25        fn focuser_position_roundtrip(
26            position in any::<i32>(),
27            max_position in any::<i32>(),
28            temperature in temperatures(),
29            is_moving in any::<bool>(),
30        ) {
31            let fp = FocuserPosition { position, max_position, temperature, is_moving };
32            let s = serde_json::to_string(&fp).unwrap();
33            let back: FocuserPosition = serde_json::from_str(&s).unwrap();
34            prop_assert_eq!(fp, back);
35        }
36    }
37}