amp_async/
frame.rs

1use std::collections::HashMap;
2use std::convert::TryFrom;
3
4use bytes::Bytes;
5
6use crate::Error;
7
8pub type RawFrame = HashMap<Vec<u8>, Bytes>;
9pub(crate) type Response = Result<RawFrame, WireError>;
10
11#[derive(Debug, Clone)]
12pub(crate) struct WireError {
13    pub(crate) code: Bytes,
14    pub(crate) description: Bytes,
15}
16
17#[derive(Debug, Clone)]
18pub(crate) enum Frame {
19    Request {
20        command: Bytes,
21        tag: Option<Bytes>,
22        fields: RawFrame,
23    },
24    Response {
25        tag: Bytes,
26        response: Response,
27    },
28}
29
30impl TryFrom<RawFrame> for Frame {
31    type Error = crate::Error;
32
33    fn try_from(mut frame: RawFrame) -> Result<Self, Self::Error> {
34        if frame.contains_key(b"_command".as_ref()) {
35            if frame.contains_key(b"_error".as_ref()) || frame.contains_key(b"_answer".as_ref()) {
36                return Err(Error::ConfusedFrame);
37            }
38            let command = frame.remove(b"_command".as_ref()).unwrap();
39            let tag = frame.remove(b"_ask".as_ref());
40
41            Ok(Frame::Request {
42                command,
43                tag,
44                fields: frame,
45            })
46        } else if frame.contains_key(b"_answer".as_ref()) {
47            if frame.contains_key(b"_error".as_ref()) || frame.contains_key(b"_command".as_ref()) {
48                return Err(Error::ConfusedFrame);
49            }
50
51            let tag = frame.remove(b"_answer".as_ref()).unwrap();
52            Ok(Frame::Response {
53                tag,
54                response: Ok(frame),
55            })
56        } else if frame.contains_key(b"_error".as_ref()) {
57            if frame.contains_key(b"_answer".as_ref()) || frame.contains_key(b"_command".as_ref()) {
58                return Err(Error::ConfusedFrame);
59            }
60            let tag = frame.remove(b"_error".as_ref()).unwrap();
61            let code = frame
62                .remove(b"_error_code".as_ref())
63                .ok_or(Error::IncompleteErrorFrame)?;
64            let description = frame
65                .remove(b"_error_description".as_ref())
66                .ok_or(Error::IncompleteErrorFrame)?;
67
68            Ok(Frame::Response {
69                tag,
70                response: Err(WireError { code, description }),
71            })
72        } else {
73            Err(Error::ConfusedFrame)
74        }
75    }
76}