hyperi_rustlib/transport/
payload.rs1use super::error::{TransportError, TransportResult};
34use super::types::PayloadFormat;
35use serde::{Serialize, de::DeserializeOwned};
36
37#[derive(Debug, Clone)]
39pub enum PayloadValue {
40 Json(serde_json::Value),
42 MsgPack(serde_json::Value),
44}
45
46impl PayloadValue {
47 #[must_use]
49 pub fn as_json(&self) -> &serde_json::Value {
50 match self {
51 Self::Json(v) | Self::MsgPack(v) => v,
52 }
53 }
54
55 #[must_use]
57 pub fn into_json(self) -> serde_json::Value {
58 match self {
59 Self::Json(v) | Self::MsgPack(v) => v,
60 }
61 }
62
63 #[must_use]
65 pub fn is_json(&self) -> bool {
66 matches!(self, Self::Json(_))
67 }
68
69 #[must_use]
71 pub fn is_msgpack(&self) -> bool {
72 matches!(self, Self::MsgPack(_))
73 }
74}
75
76pub fn parse_payload(bytes: &[u8]) -> TransportResult<PayloadValue> {
85 let format = PayloadFormat::detect(bytes);
86 parse_payload_with_format(bytes, format)
87}
88
89pub fn parse_payload_with_format(
95 bytes: &[u8],
96 format: PayloadFormat,
97) -> TransportResult<PayloadValue> {
98 match format {
99 PayloadFormat::Auto => parse_payload(bytes),
100 PayloadFormat::Json => {
101 let value: serde_json::Value = serde_json::from_slice(bytes)
102 .map_err(|e| TransportError::Internal(format!("JSON parse error: {e}")))?;
103 Ok(PayloadValue::Json(value))
104 }
105 PayloadFormat::MsgPack => {
106 let value: serde_json::Value = rmp_serde::from_slice(bytes)
107 .map_err(|e| TransportError::Internal(format!("MsgPack parse error: {e}")))?;
108 Ok(PayloadValue::MsgPack(value))
109 }
110 }
111}
112
113pub fn parse_payload_typed<T: DeserializeOwned>(bytes: &[u8]) -> TransportResult<T> {
121 let format = PayloadFormat::detect(bytes);
122 match format {
123 PayloadFormat::Json | PayloadFormat::Auto => serde_json::from_slice(bytes)
124 .map_err(|e| TransportError::Internal(format!("JSON deserialize error: {e}"))),
125 PayloadFormat::MsgPack => rmp_serde::from_slice(bytes)
126 .map_err(|e| TransportError::Internal(format!("MsgPack deserialize error: {e}"))),
127 }
128}
129
130pub fn serialize_json<T: Serialize>(value: &T) -> TransportResult<Vec<u8>> {
136 serde_json::to_vec(value)
137 .map_err(|e| TransportError::Internal(format!("JSON serialize error: {e}")))
138}
139
140pub fn serialize_msgpack<T: Serialize>(value: &T) -> TransportResult<Vec<u8>> {
146 rmp_serde::to_vec(value)
147 .map_err(|e| TransportError::Internal(format!("MsgPack serialize error: {e}")))
148}
149
150pub fn serialize_payload<T: Serialize>(
156 value: &T,
157 format: PayloadFormat,
158) -> TransportResult<Vec<u8>> {
159 match format {
160 PayloadFormat::Json | PayloadFormat::Auto => serialize_json(value),
161 PayloadFormat::MsgPack => serialize_msgpack(value),
162 }
163}
164
165pub fn extract_field(bytes: &[u8], field: &str) -> TransportResult<Option<serde_json::Value>> {
174 let value: serde_json::Value = serde_json::from_slice(bytes)
175 .map_err(|e| TransportError::Internal(format!("JSON parse error: {e}")))?;
176
177 Ok(value.get(field).cloned())
178}
179
180pub fn extract_nested_field(
186 bytes: &[u8],
187 path: &str,
188) -> TransportResult<Option<serde_json::Value>> {
189 let value: serde_json::Value = serde_json::from_slice(bytes)
190 .map_err(|e| TransportError::Internal(format!("JSON parse error: {e}")))?;
191
192 let mut current = &value;
193 for part in path.split('.') {
194 match current.get(part) {
195 Some(v) => current = v,
196 None => return Ok(None),
197 }
198 }
199
200 Ok(Some(current.clone()))
201}
202
203#[cfg(test)]
204mod tests {
205 use super::*;
206
207 #[test]
208 fn parse_json_object() {
209 let bytes = br#"{"foo": "bar", "num": 42}"#;
210 let value = parse_payload(bytes).unwrap();
211 assert!(value.is_json());
212
213 let json = value.as_json();
214 assert_eq!(json["foo"], "bar");
215 assert_eq!(json["num"], 42);
216 }
217
218 #[test]
219 fn parse_msgpack() {
220 let bytes = [
223 0x81, 0xa3, b'f', b'o', b'o', 0xa3, b'b', b'a', b'r', ];
227 let value = parse_payload(&bytes).unwrap();
228 assert!(value.is_msgpack());
229
230 let json = value.as_json();
231 assert_eq!(json["foo"], "bar");
232 }
233
234 #[test]
235 fn extract_simple_field() {
236 let bytes = br#"{"event": "login", "user_id": 123}"#;
237 let field = extract_field(bytes, "event").unwrap();
238 assert_eq!(field, Some(serde_json::json!("login")));
239 }
240
241 #[test]
242 fn extract_nested_field_path() {
243 let bytes = br#"{"tags": {"event": {"org_id": "acme"}}}"#;
244 let field = extract_nested_field(bytes, "tags.event.org_id").unwrap();
245 assert_eq!(field, Some(serde_json::json!("acme")));
246 }
247
248 #[test]
249 fn extract_missing_field() {
250 let bytes = br#"{"foo": "bar"}"#;
251 let field = extract_field(bytes, "missing").unwrap();
252 assert_eq!(field, None);
253 }
254
255 #[test]
256 fn serialize_roundtrip() {
257 #[derive(Debug, PartialEq, Serialize, serde::Deserialize)]
258 struct Event {
259 name: String,
260 value: i32,
261 }
262
263 let event = Event {
264 name: "test".to_string(),
265 value: 42,
266 };
267
268 let json_bytes = serialize_json(&event).unwrap();
270 let parsed: Event = parse_payload_typed(&json_bytes).unwrap();
271 assert_eq!(event, parsed);
272
273 let msgpack_bytes = serialize_msgpack(&event).unwrap();
275 let parsed: Event = parse_payload_typed(&msgpack_bytes).unwrap();
276 assert_eq!(event, parsed);
277 }
278}