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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
//! BNR device status types.

use std::fmt;

use crate::xfs::{method_response::XfsMethodResponse, params::XfsParam};
use crate::{impl_xfs_struct, Error, Result};

mod content;
mod device;
mod dispenser;
mod hardware;
mod inter_stacker;
mod position;
mod position_capabilities;
mod position_status;
mod safe_door;
mod shutter;
mod transport;

pub use content::*;
pub use device::*;
pub use dispenser::*;
pub use hardware::*;
pub use inter_stacker::*;
pub use position::*;
pub use position_capabilities::*;
pub use position_status::*;
pub use safe_door::*;
pub use shutter::*;
pub use transport::*;

/// Represents the CDR status returned by the
/// [`get_status`](crate::device_handle::DeviceHandle::get_status) call.
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct CdrStatus {
    pub device_status: DeviceStatus,
    pub dispenser_status: DispenserStatus,
    pub intermediate_stacker_status: IntermediateStackerStatus,
    pub safe_door_status: SafeDoorStatus,
    pub shutter_status: ShutterStatus,
    pub transport_status: TransportStatus,
    pub position_status_list: CdrPositionStatusList,
}

impl CdrStatus {
    /// Creates a new [CdrStatus].
    pub const fn new() -> Self {
        Self {
            device_status: DeviceStatus::new(),
            dispenser_status: DispenserStatus::new(),
            intermediate_stacker_status: IntermediateStackerStatus::new(),
            safe_door_status: SafeDoorStatus::new(),
            shutter_status: ShutterStatus::new(),
            transport_status: TransportStatus::new(),
            position_status_list: CdrPositionStatusList::new(),
        }
    }
}

impl From<CdrStatus> for HardwareStatus {
    fn from(val: CdrStatus) -> Self {
        [
            HardwareStatus::from(val.device_status),
            HardwareStatus::from(val.dispenser_status),
            HardwareStatus::from(val.intermediate_stacker_status),
            HardwareStatus::from(val.safe_door_status),
            HardwareStatus::from(val.shutter_status),
            HardwareStatus::from(val.transport_status),
            HardwareStatus::from(val.position_status_list),
        ]
        .into()
    }
}

impl_xfs_struct!(
    CdrStatus,
    "status",
    [
        device_status: DeviceStatus,
        dispenser_status: DispenserStatus,
        intermediate_stacker_status: IntermediateStackerStatus,
        safe_door_status: SafeDoorStatus,
        shutter_status: ShutterStatus,
        transport_status: TransportStatus,
        position_status_list: CdrPositionStatusList
    ]
);

impl From<&CdrStatus> for XfsParam {
    fn from(val: &CdrStatus) -> Self {
        Self::create(val.into())
    }
}

impl From<CdrStatus> for XfsParam {
    fn from(val: CdrStatus) -> Self {
        (&val).into()
    }
}

impl TryFrom<&XfsParam> for CdrStatus {
    type Error = Error;

    fn try_from(val: &XfsParam) -> Result<Self> {
        val.value().try_into()
    }
}

impl TryFrom<XfsParam> for CdrStatus {
    type Error = Error;

    fn try_from(val: XfsParam) -> Result<Self> {
        (&val).try_into()
    }
}

impl TryFrom<&XfsMethodResponse> for CdrStatus {
    type Error = Error;

    fn try_from(val: &XfsMethodResponse) -> Result<Self> {
        val.as_params()?
            .params()
            .iter()
            .map(|p| p.inner())
            .find(|p| p.value().xfs_struct().is_some())
            .ok_or(Error::Xfs(format!(
                "Expected CdrStatus XfsMethodResponse, have: {val}"
            )))?
            .try_into()
    }
}

impl TryFrom<XfsMethodResponse> for CdrStatus {
    type Error = Error;

    fn try_from(val: XfsMethodResponse) -> Result<Self> {
        (&val).try_into()
    }
}

impl fmt::Display for CdrStatus {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, r#"{{"device_status": "{}","#, self.device_status)?;
        write!(f, r#" "dispenser_status": "{}","#, self.dispenser_status)?;
        write!(
            f,
            r#" "intermediate_stacker_status": "{}","#,
            self.intermediate_stacker_status
        )?;
        write!(f, r#" "safe_door_status": "{}","#, self.safe_door_status)?;
        write!(f, r#" "shutter_status": "{}","#, self.shutter_status)?;
        write!(f, r#" "transport_status": "{}","#, self.transport_status)?;
        write!(
            f,
            r#" "position_status_list": {}}}"#,
            self.position_status_list
        )
    }
}