microsandbox_protocol_client/
message.rs1use microsandbox_protocol::wire::{self, Envelope};
4use serde::{Serialize, de::DeserializeOwned};
5
6use crate::{ClientError, ClientResult, EnvelopeCodec, ErrorKind, Protocol, RawFrame};
7
8pub struct Message {
14 pub v: u8,
16 pub t: String,
18 pub id: u32,
20 pub flags: u8,
22 pub p: Vec<u8>,
24 frame: RawFrame,
25}
26
27pub struct TypedMessage<T> {
29 pub message_type: String,
31 pub payload: T,
33}
34
35pub struct EncodedMessage {
37 pub message_type: String,
39 pub payload: Vec<u8>,
41}
42
43pub struct OutboundMessage {
45 pub flags: u8,
47 pub body: Vec<u8>,
49}
50
51pub trait IntoOutboundMessage<P: Protocol> {
53 fn into_outbound(
55 self,
56 ready: &P::Ready,
57 codec: &dyn EnvelopeCodec,
58 ) -> ClientResult<OutboundMessage>;
59}
60
61impl Message {
66 pub fn new(frame: RawFrame, envelope: Envelope) -> Self {
68 Self {
69 v: envelope.v,
70 t: envelope.t,
71 id: frame.id,
72 flags: frame.flags,
73 p: envelope.p,
74 frame,
75 }
76 }
77
78 pub fn payload<T: DeserializeOwned>(&self) -> ClientResult<T> {
80 let value = wire::decode_value(&self.p)?;
81 value
82 .deserialized()
83 .map_err(|_| ClientError::new(ErrorKind::InvalidData))
84 }
85
86 pub fn raw(&self) -> &RawFrame {
88 &self.frame
89 }
90
91 pub fn into_raw(self) -> RawFrame {
93 self.frame
94 }
95}
96
97impl<T> TypedMessage<T> {
98 pub fn new(message_type: impl AsRef<str>, payload: T) -> Self {
100 Self {
101 message_type: message_type.as_ref().into(),
102 payload,
103 }
104 }
105}
106
107impl EncodedMessage {
108 pub fn new(message_type: impl AsRef<str>, payload: impl Into<Vec<u8>>) -> Self {
110 Self {
111 message_type: message_type.as_ref().into(),
112 payload: payload.into(),
113 }
114 }
115}
116
117impl<P: Protocol, T: Serialize> IntoOutboundMessage<P> for TypedMessage<T> {
122 fn into_outbound(
123 self,
124 ready: &P::Ready,
125 codec: &dyn EnvelopeCodec,
126 ) -> ClientResult<OutboundMessage> {
127 let metadata = P::prepare(ready, &self.message_type)?;
128 let payload =
129 wire::encode(&self.payload).map_err(|_| ClientError::new(ErrorKind::Encode))?;
130 let body = codec.encode(metadata.generation, &self.message_type, payload)?;
131 Ok(OutboundMessage {
132 flags: metadata.flags,
133 body,
134 })
135 }
136}
137
138impl<P: Protocol> IntoOutboundMessage<P> for EncodedMessage {
139 fn into_outbound(
140 self,
141 ready: &P::Ready,
142 codec: &dyn EnvelopeCodec,
143 ) -> ClientResult<OutboundMessage> {
144 let metadata = P::prepare(ready, &self.message_type)?;
145 let body = codec.encode(metadata.generation, &self.message_type, self.payload)?;
146 Ok(OutboundMessage {
147 flags: metadata.flags,
148 body,
149 })
150 }
151}
152
153impl std::fmt::Debug for Message {
154 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
155 f.debug_struct("Message")
156 .field("id", &self.id)
157 .field("flags", &self.flags)
158 .field("generation", &self.v)
159 .field("payload_bytes", &self.p.len())
160 .finish_non_exhaustive()
161 }
162}