bitwarden_ipc/
message.rs

1use serde::{de::DeserializeOwned, Deserialize, Serialize};
2#[cfg(feature = "wasm")]
3use wasm_bindgen::prelude::*;
4
5use crate::{endpoint::Endpoint, serde_utils};
6
7#[derive(Clone, Debug, Deserialize, Serialize)]
8#[cfg_attr(test, derive(PartialEq))]
9#[cfg_attr(feature = "wasm", wasm_bindgen)]
10pub struct OutgoingMessage {
11    #[cfg_attr(feature = "wasm", wasm_bindgen(getter_with_clone))]
12    pub payload: Vec<u8>,
13    pub destination: Endpoint,
14    #[cfg_attr(feature = "wasm", wasm_bindgen(getter_with_clone))]
15    pub topic: Option<String>,
16}
17
18#[derive(Clone, Debug, Deserialize, Serialize)]
19#[cfg_attr(test, derive(PartialEq))]
20#[cfg_attr(feature = "wasm", wasm_bindgen)]
21pub struct IncomingMessage {
22    #[cfg_attr(feature = "wasm", wasm_bindgen(getter_with_clone))]
23    pub payload: Vec<u8>,
24    pub destination: Endpoint,
25    pub source: Endpoint,
26    #[cfg_attr(feature = "wasm", wasm_bindgen(getter_with_clone))]
27    pub topic: Option<String>,
28}
29
30#[derive(Clone, Debug, Serialize, Deserialize)]
31#[cfg_attr(test, derive(PartialEq))]
32pub struct TypedOutgoingMessage<Payload> {
33    pub payload: Payload,
34    pub destination: Endpoint,
35}
36
37impl<Payload> TryFrom<OutgoingMessage> for TypedOutgoingMessage<Payload>
38where
39    Payload: DeserializeOwned,
40{
41    type Error = serde_utils::SerializeError;
42
43    fn try_from(value: OutgoingMessage) -> Result<Self, Self::Error> {
44        Ok(Self {
45            payload: serde_utils::from_slice(&value.payload)?,
46            destination: value.destination,
47        })
48    }
49}
50
51impl<Payload> TryFrom<TypedOutgoingMessage<Payload>> for OutgoingMessage
52where
53    Payload: Serialize + PayloadTypeName,
54{
55    type Error = serde_utils::DeserializeError;
56
57    fn try_from(value: TypedOutgoingMessage<Payload>) -> Result<Self, Self::Error> {
58        Ok(Self {
59            payload: serde_utils::to_vec(&value.payload)?,
60            destination: value.destination,
61            topic: Some(Payload::PAYLOAD_TYPE_NAME.to_owned()),
62        })
63    }
64}
65
66#[derive(Clone, Debug)]
67#[cfg_attr(test, derive(PartialEq))]
68pub struct TypedIncomingMessage<Payload: PayloadTypeName> {
69    pub payload: Payload,
70    pub destination: Endpoint,
71    pub source: Endpoint,
72}
73
74/// This trait is used to ensure that the payload type has a topic associated with it.
75pub trait PayloadTypeName {
76    const PAYLOAD_TYPE_NAME: &str;
77}
78
79impl<Payload> TryFrom<IncomingMessage> for TypedIncomingMessage<Payload>
80where
81    Payload: DeserializeOwned + PayloadTypeName,
82{
83    type Error = serde_utils::DeserializeError;
84
85    fn try_from(value: IncomingMessage) -> Result<Self, Self::Error> {
86        Ok(Self {
87            payload: serde_utils::from_slice(&value.payload)?,
88            destination: value.destination,
89            source: value.source,
90        })
91    }
92}
93
94impl<Payload> TryFrom<TypedIncomingMessage<Payload>> for IncomingMessage
95where
96    Payload: Serialize + PayloadTypeName,
97{
98    type Error = serde_utils::SerializeError;
99
100    fn try_from(value: TypedIncomingMessage<Payload>) -> Result<Self, Self::Error> {
101        Ok(Self {
102            payload: serde_utils::to_vec(&value.payload)?,
103            destination: value.destination,
104            source: value.source,
105            topic: Some(Payload::PAYLOAD_TYPE_NAME.to_owned()),
106        })
107    }
108}