Skip to main content

rs_teststand_websocket/client/
inbound.rs

1//! Telling an acknowledgement from an event.
2
3use rs_teststand_bridge::{Ack, Error, MessageEvent};
4
5/// One message read from a host.
6///
7/// Sorted on `command`: an acknowledgement always carries one and an event
8/// never does. Sorting on `code` would be wrong, since both types have a field
9/// with that name meaning different things.
10#[derive(Debug, Clone, PartialEq)]
11#[non_exhaustive]
12pub enum Inbound {
13    /// The answer to a command somebody sent.
14    Ack(Ack),
15    /// Something a run reported, unprompted.
16    Event(Box<MessageEvent>),
17}
18
19impl Inbound {
20    /// The acknowledgement, when this is one.
21    #[must_use]
22    pub const fn as_ack(&self) -> Option<&Ack> {
23        match self {
24            Self::Ack(ack) => Some(ack),
25            Self::Event(_) => None,
26        }
27    }
28
29    /// The event, when this is one.
30    #[must_use]
31    pub fn as_event(&self) -> Option<&MessageEvent> {
32        match self {
33            Self::Event(event) => Some(event),
34            Self::Ack(_) => None,
35        }
36    }
37
38    /// Parses one text frame.
39    ///
40    /// # Errors
41    /// [`Error::Payload`] if the frame is not one of the two shapes.
42    pub fn parse(text: &str) -> Result<Self, Error> {
43        let value: serde_json::Value = serde_json::from_str(text)?;
44        if value.get("command").is_some() {
45            Ok(Self::Ack(serde_json::from_str(text)?))
46        } else {
47            Ok(Self::Event(Box::new(serde_json::from_str(text)?)))
48        }
49    }
50}