socketio_rs/
payload.rs

1use bytes::Bytes;
2use serde_json::Value;
3
4/// A type which represents a `payload` in the `socket.io` context.
5/// The enum is used for both representing data that's send and
6/// data that's received.
7#[derive(Debug, PartialEq, Eq, Clone)]
8#[non_exhaustive]
9pub enum Payload {
10    Binary(Bytes),
11    Json(Value),
12    Multi(Vec<RawPayload>),
13}
14
15#[derive(Debug, PartialEq, Eq, Clone)]
16pub enum RawPayload {
17    Binary(Bytes),
18    Json(Value),
19}
20
21impl From<serde_json::Value> for Payload {
22    fn from(value: serde_json::Value) -> Self {
23        Self::Json(value)
24    }
25}
26
27impl From<Option<serde_json::Value>> for Payload {
28    fn from(value: Option<serde_json::Value>) -> Self {
29        match value {
30            None => Self::Json(Value::Null),
31            Some(value) => Self::Json(value),
32        }
33    }
34}
35
36impl From<Vec<serde_json::Value>> for Payload {
37    fn from(value: Vec<serde_json::Value>) -> Self {
38        if value.len() == 1 {
39            // SAFETY: first element must exist
40            Self::Json(value.first().unwrap().to_owned())
41        } else {
42            Self::Multi(value.into_iter().map(|v| v.into()).collect())
43        }
44    }
45}
46
47impl From<Vec<u8>> for Payload {
48    fn from(val: Vec<u8>) -> Self {
49        Self::Binary(Bytes::from(val))
50    }
51}
52
53impl From<&'static [u8]> for Payload {
54    fn from(val: &'static [u8]) -> Self {
55        Self::Binary(Bytes::from_static(val))
56    }
57}
58
59impl From<Bytes> for Payload {
60    fn from(bytes: Bytes) -> Self {
61        Self::Binary(bytes)
62    }
63}
64
65impl From<serde_json::Value> for RawPayload {
66    fn from(value: serde_json::Value) -> Self {
67        Self::Json(value)
68    }
69}
70
71impl From<Vec<u8>> for RawPayload {
72    fn from(val: Vec<u8>) -> Self {
73        Self::Binary(Bytes::from(val))
74    }
75}
76
77impl From<&'static [u8]> for RawPayload {
78    fn from(val: &'static [u8]) -> Self {
79        Self::Binary(Bytes::from_static(val))
80    }
81}
82
83impl From<Bytes> for RawPayload {
84    fn from(bytes: Bytes) -> Self {
85        Self::Binary(bytes)
86    }
87}
88
89impl From<RawPayload> for Payload {
90    fn from(val: RawPayload) -> Self {
91        match val {
92            RawPayload::Json(data) => Payload::Json(data),
93            RawPayload::Binary(bin) => Payload::Binary(bin),
94        }
95    }
96}
97
98#[cfg(test)]
99mod tests {
100    use serde_json::json;
101
102    use super::*;
103
104    #[test]
105    fn test_from() {
106        let sut = Payload::from(json!("foo ™"));
107        assert_eq!(Payload::Json(json!("foo ™")), sut);
108
109        let sut = Payload::from(vec![1, 2, 3]);
110        assert_eq!(Payload::Binary(Bytes::from_static(&[1, 2, 3])), sut);
111
112        let sut = Payload::from(&[1_u8, 2_u8, 3_u8][..]);
113        assert_eq!(Payload::Binary(Bytes::from_static(&[1, 2, 3])), sut);
114
115        let sut = Payload::from(Bytes::from_static(&[1, 2, 3]));
116        assert_eq!(Payload::Binary(Bytes::from_static(&[1, 2, 3])), sut);
117
118        let sut = Payload::from(json!(5));
119        assert_eq!(Payload::Json(json!(5)), sut);
120
121        let sut = Payload::from(json!("5"));
122        assert_eq!(Payload::Json(json!("5")), sut);
123    }
124}