1#[allow(unused_imports)]
25use crate::alloc;
26use crate::errors::GatewayError;
27use alloc::string::{String, ToString};
28use alloc::vec::Vec;
29use bytes::Bytes;
30use prost::Message;
31use serde::de::DeserializeOwned;
32
33pub trait Codec: Send + Sync + 'static {
38 fn encoder_content_type(&self, accept: Option<&str>) -> String;
43
44 fn encode<T: Message + serde::Serialize>(
53 &self,
54 val: &T,
55 mime: Option<&str>,
56 ) -> Result<Bytes, GatewayError>;
57
58 fn decode<T: Message + Default + DeserializeOwned>(
67 &self,
68 buf: &[u8],
69 mime: Option<&str>,
70 ) -> Result<T, GatewayError>;
71}
72
73#[derive(Debug, Clone, Copy, Default)]
77pub struct ProtobufCodec;
78
79impl Codec for ProtobufCodec {
80 fn encoder_content_type(&self, _accept: Option<&str>) -> String {
81 "application/octet-stream".to_string()
82 }
83
84 fn encode<T: Message + serde::Serialize>(
96 &self,
97 val: &T,
98 _mime: Option<&str>,
99 ) -> Result<Bytes, GatewayError> {
100 let mut buf = Vec::new();
101 val.encode(&mut buf).map_err(|e| {
102 GatewayError::Encoding(
103 #[cfg(feature = "std")]
104 Box::new(e),
105 #[cfg(not(feature = "std"))]
106 e.to_string(),
107 )
108 })?;
109 Ok(Bytes::from(buf))
110 }
111
112 fn decode<T: Message + Default + DeserializeOwned>(
124 &self,
125 buf: &[u8],
126 _mime: Option<&str>,
127 ) -> Result<T, GatewayError> {
128 T::decode(buf).map_err(|e| {
129 GatewayError::Encoding(
130 #[cfg(feature = "std")]
131 Box::new(e),
132 #[cfg(not(feature = "std"))]
133 e.to_string(),
134 )
135 })
136 }
137}
138
139#[derive(Debug, Clone, Default)]
141pub struct JsonEncoderOptions {
142 pub pretty_print: bool,
145
146 pub indent: String,
149}
150
151#[derive(Debug, Clone, Default)]
153pub struct JsonDecoderOptions {
154 }
156
157#[derive(Debug, Clone, Default)]
161pub struct JsonCodec {
162 encoder_opts: JsonEncoderOptions,
163 decoder_opts: JsonDecoderOptions,
164}
165
166impl JsonCodec {
167 pub fn new() -> Self {
169 Self::default()
170 }
171
172 pub fn pretty() -> Self {
174 Self {
175 encoder_opts: JsonEncoderOptions {
176 pretty_print: true,
177 indent: String::new(),
178 },
179 decoder_opts: JsonDecoderOptions::default(),
180 }
181 }
182
183 pub fn with_encoder_options(mut self, options: JsonEncoderOptions) -> Self {
185 self.encoder_opts = options;
186 self
187 }
188
189 pub fn with_decoder_options(mut self, options: JsonDecoderOptions) -> Self {
191 self.decoder_opts = options;
192 self
193 }
194}
195
196impl Codec for JsonCodec {
197 fn encoder_content_type(&self, _accept: Option<&str>) -> String {
198 "application/json".to_string()
199 }
200
201 fn encode<T: Message + serde::Serialize>(
213 &self,
214 val: &T,
215 _mime: Option<&str>,
216 ) -> Result<Bytes, GatewayError> {
217 let mut buf = Vec::new();
218 let indent_str = &self.encoder_opts.indent;
219 let pretty_print = self.encoder_opts.pretty_print;
220
221 let res = if pretty_print || !indent_str.is_empty() {
222 let indent = if indent_str.is_empty() {
223 b" "
224 } else {
225 indent_str.as_bytes()
226 };
227 let formatter = serde_json::ser::PrettyFormatter::with_indent(indent);
228 let mut ser = serde_json::Serializer::with_formatter(&mut buf, formatter);
229 val.serialize(&mut ser)
230 } else {
231 serde_json::to_writer(&mut buf, val)
232 };
233
234 res.map_err(|e| {
235 GatewayError::Encoding(
236 #[cfg(feature = "std")]
237 Box::new(e),
238 #[cfg(not(feature = "std"))]
239 e.to_string(),
240 )
241 })?;
242 Ok(Bytes::from(buf))
243 }
244
245 fn decode<T: Message + Default + DeserializeOwned>(
257 &self,
258 buf: &[u8],
259 _mime: Option<&str>,
260 ) -> Result<T, GatewayError> {
261 serde_json::from_slice(buf).map_err(|e| {
262 GatewayError::Encoding(
263 #[cfg(feature = "std")]
264 Box::new(e),
265 #[cfg(not(feature = "std"))]
266 e.to_string(),
267 )
268 })
269 }
270}
271
272#[derive(Debug, Clone, Default)]
277pub struct MultimediaCodec {
278 json: JsonCodec,
279 proto: ProtobufCodec,
280}
281
282impl MultimediaCodec {
283 pub fn new() -> Self {
285 Self::default()
286 }
287
288 pub fn with_codecs(json: JsonCodec, proto: ProtobufCodec) -> Self {
290 Self { json, proto }
291 }
292}
293
294impl Codec for MultimediaCodec {
295 fn encoder_content_type(&self, accept: Option<&str>) -> String {
296 if let Some(accept) = accept {
297 if accept.contains("application/octet-stream")
298 || accept.contains("application/x-protobuf")
299 {
300 return "application/octet-stream".to_string();
301 }
302 }
303 "application/json".to_string()
305 }
306
307 fn encode<T: Message + serde::Serialize>(
308 &self,
309 val: &T,
310 mime: Option<&str>,
311 ) -> Result<Bytes, GatewayError> {
312 let content_type = self.encoder_content_type(mime);
313 if content_type == "application/octet-stream" {
314 self.proto.encode(val, mime)
315 } else {
316 self.json.encode(val, mime)
317 }
318 }
319
320 fn decode<T: Message + Default + DeserializeOwned>(
321 &self,
322 buf: &[u8],
323 mime: Option<&str>,
324 ) -> Result<T, GatewayError> {
325 if let Some(mime) = mime {
326 if mime.contains("application/octet-stream") || mime.contains("application/x-protobuf")
327 {
328 return self.proto.decode(buf, Some(mime));
329 }
330 }
331 self.json.decode(buf, mime)
332 }
333}
334
335#[cfg(test)]
336mod tests {
337 use super::*;
338 use serde::{Deserialize, Serialize};
339
340 #[derive(Clone, PartialEq, Message, Serialize, Deserialize)]
341 struct TestMessage {
342 #[prost(string, tag = "1")]
343 pub name: String,
344 #[prost(int32, tag = "2")]
345 pub id: i32,
346 }
347
348 #[test]
349 fn test_protobuf_codec_encoding() {
350 let codec = ProtobufCodec;
351 let msg = TestMessage {
352 name: "test".to_string(),
353 id: 123,
354 };
355 let encoded = codec.encode(&msg, None).unwrap();
356
357 let mut expected = Vec::new();
358 msg.encode(&mut expected).unwrap();
359
360 assert_eq!(encoded, Bytes::from(expected));
361 assert_eq!(codec.encoder_content_type(None), "application/octet-stream");
362 }
363
364 #[test]
365 fn test_protobuf_codec_decoding() {
366 let codec = ProtobufCodec;
367 let msg = TestMessage {
368 name: "test".to_string(),
369 id: 123,
370 };
371 let mut buf = Vec::new();
372 msg.encode(&mut buf).unwrap();
373
374 let decoded: TestMessage = codec.decode(&buf, None).unwrap();
375 assert_eq!(decoded, msg);
376 }
377
378 #[test]
379 fn test_json_codec_default_encoding() {
380 let codec = JsonCodec::new();
381 let msg = TestMessage {
382 name: "test".to_string(),
383 id: 123,
384 };
385 let encoded = codec.encode(&msg, None).unwrap();
386
387 let json_str = String::from_utf8(encoded.to_vec()).unwrap();
388 assert_eq!(json_str, r#"{"name":"test","id":123}"#);
389 assert_eq!(codec.encoder_content_type(None), "application/json");
390 }
391
392 #[test]
393 fn test_json_codec_pretty_encoding() {
394 let codec = JsonCodec::pretty();
395 let msg = TestMessage {
396 name: "test".to_string(),
397 id: 123,
398 };
399 let encoded = codec.encode(&msg, None).unwrap();
400
401 let json_str = String::from_utf8(encoded.to_vec()).unwrap();
402 assert!(json_str.contains('\n'));
404 assert!(json_str.contains(" \"name\""));
405 }
406
407 #[test]
408 fn test_json_codec_custom_indent_encoding() {
409 let options = JsonEncoderOptions {
410 pretty_print: true,
411 indent: "\t".to_string(),
412 };
413 let codec = JsonCodec::new().with_encoder_options(options);
414 let msg = TestMessage {
415 name: "test".to_string(),
416 id: 123,
417 };
418 let encoded = codec.encode(&msg, None).unwrap();
419
420 let json_str = String::from_utf8(encoded.to_vec()).unwrap();
421 assert!(json_str.contains("\t\"name\""));
422 }
423
424 #[test]
425 fn test_json_codec_decoding() {
426 let codec = JsonCodec::new();
427 let json_data = r#"{"name":"test","id":123}"#;
428 let decoded: TestMessage = codec.decode(json_data.as_bytes(), None).unwrap();
429
430 assert_eq!(decoded.name, "test");
431 assert_eq!(decoded.id, 123);
432 }
433
434 #[test]
435 fn test_multimedia_codec_default_encoding() {
436 let codec = MultimediaCodec::new();
437 let msg = TestMessage {
438 name: "test".to_string(),
439 id: 123,
440 };
441
442 let encoded = codec.encode(&msg, None).unwrap();
444 let json_str = String::from_utf8(encoded.to_vec()).unwrap();
445 assert_eq!(json_str, r#"{"name":"test","id":123}"#);
446 assert_eq!(codec.encoder_content_type(None), "application/json");
447 }
448
449 #[test]
450 fn test_multimedia_codec_json_encoding() {
451 let codec = MultimediaCodec::new();
452 let msg = TestMessage {
453 name: "test".to_string(),
454 id: 123,
455 };
456
457 let encoded = codec.encode(&msg, Some("application/json")).unwrap();
458 let json_str = String::from_utf8(encoded.to_vec()).unwrap();
459 assert_eq!(json_str, r#"{"name":"test","id":123}"#);
460 assert_eq!(
461 codec.encoder_content_type(Some("application/json")),
462 "application/json"
463 );
464 }
465
466 #[test]
467 fn test_multimedia_codec_protobuf_encoding() {
468 let codec = MultimediaCodec::new();
469 let msg = TestMessage {
470 name: "test".to_string(),
471 id: 123,
472 };
473
474 let encoded = codec
475 .encode(&msg, Some("application/octet-stream"))
476 .unwrap();
477 let mut expected = Vec::new();
478 msg.encode(&mut expected).unwrap();
479 assert_eq!(encoded, Bytes::from(expected));
480 assert_eq!(
481 codec.encoder_content_type(Some("application/octet-stream")),
482 "application/octet-stream"
483 );
484 }
485
486 #[test]
487 fn test_multimedia_codec_protobuf_alias_encoding() {
488 let codec = MultimediaCodec::new();
489 let msg = TestMessage {
490 name: "test".to_string(),
491 id: 123,
492 };
493
494 let encoded = codec.encode(&msg, Some("application/x-protobuf")).unwrap();
496 let mut expected = Vec::new();
497 msg.encode(&mut expected).unwrap();
498 assert_eq!(encoded, Bytes::from(expected));
499 assert_eq!(
500 codec.encoder_content_type(Some("application/x-protobuf")),
501 "application/octet-stream"
502 );
503 }
504
505 #[test]
506 fn test_multimedia_codec_wildcard_json_decoding() {
507 let codec = MultimediaCodec::new();
508 let json_data = r#"{"name":"test","id":123}"#;
509
510 let decoded: TestMessage = codec.decode(json_data.as_bytes(), None).unwrap();
512 assert_eq!(decoded.name, "test");
513 assert_eq!(decoded.id, 123);
514 }
515
516 #[test]
517 fn test_multimedia_codec_explicit_json_decoding() {
518 let codec = MultimediaCodec::new();
519 let json_data = r#"{"name":"test","id":123}"#;
520
521 let decoded: TestMessage = codec
522 .decode(json_data.as_bytes(), Some("application/json"))
523 .unwrap();
524 assert_eq!(decoded.name, "test");
525 assert_eq!(decoded.id, 123);
526 }
527
528 #[test]
529 fn test_multimedia_codec_protobuf_decoding() {
530 let codec = MultimediaCodec::new();
531 let msg = TestMessage {
532 name: "test".to_string(),
533 id: 123,
534 };
535 let mut buf = Vec::new();
536 msg.encode(&mut buf).unwrap();
537
538 let decoded: TestMessage = codec
539 .decode(&buf, Some("application/octet-stream"))
540 .unwrap();
541 assert_eq!(decoded, msg);
542 }
543
544 #[test]
545 fn test_multimedia_codec_with_custom_codecs() {
546 let json_codec = JsonCodec::pretty();
547 let proto_codec = ProtobufCodec;
548 let codec = MultimediaCodec::with_codecs(json_codec, proto_codec);
549
550 let msg = TestMessage {
551 name: "test".to_string(),
552 id: 123,
553 };
554
555 let encoded = codec.encode(&msg, None).unwrap();
557 let json_str = String::from_utf8(encoded.to_vec()).unwrap();
558 assert!(json_str.contains('\n'));
559 }
560
561 #[test]
562 fn test_json_decoding_error() {
563 let codec = JsonCodec::new();
564 let bad_json = r#"{"name": 123}"#; let result: Result<TestMessage, _> = codec.decode(bad_json.as_bytes(), None);
566 assert!(result.is_err());
567 }
568
569 #[test]
570 fn test_protobuf_decoding_error() {
571 let codec = ProtobufCodec;
572 let bad_proto = vec![255, 255, 255]; let result: Result<TestMessage, _> = codec.decode(&bad_proto, None);
574 assert!(result.is_err());
575 }
576
577 #[test]
578 fn test_multimedia_fallback_decoding() {
579 let codec = MultimediaCodec::new();
580 let json_data = r#"{"name":"test","id":123}"#;
582 let decoded: TestMessage = codec
583 .decode(json_data.as_bytes(), Some("text/plain"))
584 .unwrap();
585 assert_eq!(decoded.name, "test");
586 }
587
588 #[test]
589 fn test_multimedia_fallback_encoding() {
590 let codec = MultimediaCodec::new();
591 let msg = TestMessage {
592 name: "test".to_string(),
593 id: 123,
594 };
595 let encoded = codec.encode(&msg, Some("text/html")).unwrap();
597 let json_str = String::from_utf8(encoded.to_vec()).unwrap();
598 assert_eq!(json_str, r#"{"name":"test","id":123}"#);
599 }
600
601 #[test]
602 fn test_json_codec_empty_input() {
603 let codec = JsonCodec::new();
604 let result: Result<TestMessage, _> = codec.decode(&[], None);
605 assert!(result.is_err()); }
607
608 #[test]
609 fn test_protobuf_codec_empty_input() {
610 let codec = ProtobufCodec;
611 let result: Result<TestMessage, _> = codec.decode(&[], None);
612 assert!(result.is_ok());
614 let decoded = result.unwrap();
615 assert_eq!(decoded.name, "");
616 assert_eq!(decoded.id, 0);
617 }
618}